skilld 0.3.2 โ 0.4.1
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 +9 -8
- package/dist/_chunks/detect-imports.mjs +51 -37
- package/dist/_chunks/detect-imports.mjs.map +1 -1
- package/dist/_chunks/{pool.mjs โ pool2.mjs} +7 -2
- package/dist/_chunks/pool2.mjs.map +1 -0
- package/dist/_chunks/releases.mjs +278 -33
- package/dist/_chunks/releases.mjs.map +1 -1
- package/dist/_chunks/utils.d.mts +54 -1
- package/dist/_chunks/utils.d.mts.map +1 -1
- package/dist/_chunks/yaml.mjs +24 -0
- package/dist/_chunks/yaml.mjs.map +1 -0
- package/dist/agent/index.d.mts +11 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +2 -2
- package/dist/cli.mjs +496 -50
- package/dist/cli.mjs.map +1 -1
- package/dist/retriv/index.mjs +1 -1
- package/dist/retriv/index.mjs.map +1 -1
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/_chunks/pool.mjs.map +0 -1
- package/dist/_chunks/sync-parallel.mjs +0 -296
- package/dist/_chunks/sync-parallel.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -34,22 +34,23 @@ Skilld leverages maintainers existing effort. Maintainers write great docs for u
|
|
|
34
34
|
|
|
35
35
|
## Features
|
|
36
36
|
|
|
37
|
-
- ๐ **
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
37
|
+
- ๐ **Any Source: Opt-in** - Any NPM dependency or GitHub source, docs auto-resolved
|
|
38
|
+
- ๐ฆ **Bleeding Edge Context** - Latest issues, discussions, and releases synced on
|
|
39
|
+
every update. Always use the latest best practices and avoid deprecated patterns.
|
|
40
|
+
- ๐ **Opt-in LLM Sections** - Enhance skills with LLM-generated `Best practices`, `LLM Gaps`, `Doc Map`, or your own prompts
|
|
41
|
+
- ๐ **Semantic Search** - Query indexed docs across all skills via [retriv](https://github.com/harlan-zw/retriv) embeddings
|
|
42
|
+
- ๐ฏ **Safe & Versioned** - Prompt injection sanitization, version-aware caching, auto-updates on new releases
|
|
43
|
+
- ๐ค **Ecosystem** - Compatible with [`npx skills`](https://skills.sh/) and [skills-npm](https://github.com/antfu/skills-npm)
|
|
43
44
|
|
|
44
45
|
## Quick Start
|
|
45
46
|
|
|
46
47
|
Run skilld in a project to generate skills for your dependencies through a simple interactive wizard:
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
npx skilld
|
|
50
|
+
npx -y skilld
|
|
50
51
|
```
|
|
51
52
|
|
|
52
|
-
If you need to re-configure skilld, just run `npx skilld config` to update your agent, model, or preferences.
|
|
53
|
+
If you need to re-configure skilld, just run `npx -y skilld config` to update your agent, model, or preferences.
|
|
53
54
|
|
|
54
55
|
### Tips
|
|
55
56
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { _ as writeSections, b as sanitizeMarkdown, h as readCachedSection, y as repairMarkdown } from "./storage.mjs";
|
|
2
|
+
import { t as yamlEscape } from "./yaml.mjs";
|
|
2
3
|
import { createRequire } from "node:module";
|
|
3
4
|
import { homedir } from "node:os";
|
|
4
|
-
import { dirname, join } from "pathe";
|
|
5
|
-
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, unlinkSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { dirname, join, relative } from "pathe";
|
|
6
|
+
import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
|
|
6
7
|
import { exec, spawn, spawnSync } from "node:child_process";
|
|
7
8
|
import { globby } from "globby";
|
|
8
9
|
import { findDynamicImports, findStaticImports } from "mlly";
|
|
9
10
|
import { createHash } from "node:crypto";
|
|
11
|
+
import { promisify } from "node:util";
|
|
10
12
|
import { readFile } from "node:fs/promises";
|
|
13
|
+
import { parseSync } from "oxc-parser";
|
|
11
14
|
var __defProp = Object.defineProperty;
|
|
12
15
|
var __exportAll = (all, no_symbols) => {
|
|
13
16
|
let target = {};
|
|
@@ -695,16 +698,24 @@ function generateImportantBlock({ packageName, hasIssues, hasDiscussions, hasRel
|
|
|
695
698
|
if (hasDiscussions) rows.push(["Discussions", `\`${skillDir}/.skilld/discussions/\``]);
|
|
696
699
|
if (hasChangelog) rows.push(["Changelog", `\`${skillDir}/.skilld/pkg/${hasChangelog}\``]);
|
|
697
700
|
if (hasReleases) rows.push(["Releases", `\`${skillDir}/.skilld/releases/\``]);
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
| Resource | Command |
|
|
701
|
-
|----------|---------|
|
|
702
|
-
| Search all | \`Bash 'npx skilld search "<query>" -p ${packageName}'\` |
|
|
703
|
-
${[
|
|
701
|
+
const table = [
|
|
704
702
|
"| Resource | Path |",
|
|
705
703
|
"|----------|------|",
|
|
706
704
|
...rows.map(([desc, cmd]) => `| ${desc} | ${cmd} |`)
|
|
707
|
-
].join("\n")
|
|
705
|
+
].join("\n");
|
|
706
|
+
return `**IMPORTANT:** Use these references
|
|
707
|
+
|
|
708
|
+
## Search
|
|
709
|
+
|
|
710
|
+
Use \`npx -y skilld search\` as your primary research tool โ search before manually reading files. Hybrid semantic + keyword search across all indexed docs, issues, and releases.
|
|
711
|
+
|
|
712
|
+
\`\`\`bash
|
|
713
|
+
npx -y skilld search "<query>" -p ${packageName}
|
|
714
|
+
${hasIssues ? `npx -y skilld search "issues:<query>" -p ${packageName}\n` : ""}${hasReleases ? `npx -y skilld search "releases:<query>" -p ${packageName}\n` : ""}\`\`\`
|
|
715
|
+
|
|
716
|
+
Filters: \`docs:\`, \`issues:\`, \`releases:\` prefix narrows by source type.
|
|
717
|
+
|
|
718
|
+
${table}`;
|
|
708
719
|
}
|
|
709
720
|
function buildPreamble(opts) {
|
|
710
721
|
const { packageName, skillDir, hasIssues, hasDiscussions, hasReleases, hasChangelog, docFiles, docsType = "docs", hasShippedDocs = false, versionContext } = opts;
|
|
@@ -803,27 +814,6 @@ function buildAllSectionPrompts(opts) {
|
|
|
803
814
|
}
|
|
804
815
|
return result;
|
|
805
816
|
}
|
|
806
|
-
const NEEDS_QUOTING = /[:"'\\\n\r\t#{}[\],&*!|>%@`]/;
|
|
807
|
-
function yamlEscape(value) {
|
|
808
|
-
if (!NEEDS_QUOTING.test(value)) return value;
|
|
809
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
|
|
810
|
-
}
|
|
811
|
-
function yamlUnescape(raw) {
|
|
812
|
-
const trimmed = raw.trim();
|
|
813
|
-
if (!trimmed) return "";
|
|
814
|
-
if (trimmed.startsWith("\"") && trimmed.endsWith("\"")) return trimmed.slice(1, -1).replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\t/g, " ").replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
|
|
815
|
-
if (trimmed.startsWith("'") && trimmed.endsWith("'")) return trimmed.slice(1, -1);
|
|
816
|
-
return trimmed;
|
|
817
|
-
}
|
|
818
|
-
function yamlParseKV(line) {
|
|
819
|
-
const trimmed = line.trim();
|
|
820
|
-
const colonIdx = trimmed.indexOf(":");
|
|
821
|
-
if (colonIdx === -1) return null;
|
|
822
|
-
const key = trimmed.slice(0, colonIdx).trim();
|
|
823
|
-
const rawValue = trimmed.slice(colonIdx + 1);
|
|
824
|
-
if (!key) return null;
|
|
825
|
-
return [key, yamlUnescape(rawValue)];
|
|
826
|
-
}
|
|
827
817
|
function sanitizeName(name) {
|
|
828
818
|
return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
|
|
829
819
|
}
|
|
@@ -857,6 +847,32 @@ function installSkillForAgents(skillName, skillContent, options = {}) {
|
|
|
857
847
|
paths
|
|
858
848
|
};
|
|
859
849
|
}
|
|
850
|
+
function linkSkillToAgents(skillName, sharedDir, cwd) {
|
|
851
|
+
for (const [, agent] of Object.entries(targets)) {
|
|
852
|
+
const agentSkillsDir = join(cwd, agent.skillsDir);
|
|
853
|
+
if (!existsSync(join(cwd, agent.skillsDir.split("/")[0]))) continue;
|
|
854
|
+
const target = join(agentSkillsDir, skillName);
|
|
855
|
+
let isSymlink = false;
|
|
856
|
+
let targetExists = false;
|
|
857
|
+
try {
|
|
858
|
+
const stat = lstatSync(target);
|
|
859
|
+
targetExists = true;
|
|
860
|
+
isSymlink = stat.isSymbolicLink();
|
|
861
|
+
} catch {}
|
|
862
|
+
if (targetExists && !isSymlink) continue;
|
|
863
|
+
if (isSymlink) unlinkSync(target);
|
|
864
|
+
mkdirSync(agentSkillsDir, { recursive: true });
|
|
865
|
+
symlinkSync(relative(agentSkillsDir, join(sharedDir, skillName)), target);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
function unlinkSkillFromAgents(skillName, cwd) {
|
|
869
|
+
for (const [, agent] of Object.entries(targets)) {
|
|
870
|
+
const target = join(cwd, agent.skillsDir, skillName);
|
|
871
|
+
try {
|
|
872
|
+
if (lstatSync(target).isSymbolicLink()) unlinkSync(target);
|
|
873
|
+
} catch {}
|
|
874
|
+
}
|
|
875
|
+
}
|
|
860
876
|
const FILE_PATTERN_MAP = {
|
|
861
877
|
"vue": ["*.vue"],
|
|
862
878
|
"svelte": ["*.svelte"],
|
|
@@ -1018,12 +1034,12 @@ function generateFrontmatter({ name, version, description: pkgDescription, globs
|
|
|
1018
1034
|
return lines.join("\n");
|
|
1019
1035
|
}
|
|
1020
1036
|
function generateSearchBlock(name, hasIssues, hasReleases) {
|
|
1021
|
-
const examples = [`npx skilld search "query" -p ${name}`];
|
|
1022
|
-
if (hasIssues) examples.push(`npx skilld search "issues:error handling" -p ${name}`);
|
|
1023
|
-
if (hasReleases) examples.push(`npx skilld search "releases:deprecated" -p ${name}`);
|
|
1037
|
+
const examples = [`npx -y skilld search "query" -p ${name}`];
|
|
1038
|
+
if (hasIssues) examples.push(`npx -y skilld search "issues:error handling" -p ${name}`);
|
|
1039
|
+
if (hasReleases) examples.push(`npx -y skilld search "releases:deprecated" -p ${name}`);
|
|
1024
1040
|
return `## Search
|
|
1025
1041
|
|
|
1026
|
-
Use \`npx skilld search\` instead of grepping \`.skilld/\` directories โ hybrid semantic + keyword search across all indexed docs, issues, and releases.
|
|
1042
|
+
Use \`npx -y skilld search\` instead of grepping \`.skilld/\` directories โ hybrid semantic + keyword search across all indexed docs, issues, and releases.
|
|
1027
1043
|
|
|
1028
1044
|
\`\`\`bash
|
|
1029
1045
|
${examples.join("\n")}
|
|
@@ -1300,7 +1316,6 @@ function getModelLabel(id) {
|
|
|
1300
1316
|
return `${targets[config.agentId]?.displayName ?? config.cli} ยท ${config.name}`;
|
|
1301
1317
|
}
|
|
1302
1318
|
async function getAvailableModels() {
|
|
1303
|
-
const { promisify } = await import("node:util");
|
|
1304
1319
|
const execAsync = promisify(exec);
|
|
1305
1320
|
const agentsWithCli = detectInstalledAgents().filter((id) => targets[id].cli);
|
|
1306
1321
|
const cliChecks = await Promise.all(agentsWithCli.map(async (agentId) => {
|
|
@@ -1718,7 +1733,6 @@ function extractModuleStrings(node) {
|
|
|
1718
1733
|
async function detectNuxtModules(cwd) {
|
|
1719
1734
|
const config = await findNuxtConfig(cwd);
|
|
1720
1735
|
if (!config) return [];
|
|
1721
|
-
const { parseSync } = await import("oxc-parser");
|
|
1722
1736
|
const modules = extractModuleStrings(parseSync(config.path, config.content).program);
|
|
1723
1737
|
const seen = /* @__PURE__ */ new Set();
|
|
1724
1738
|
const packages = [];
|
|
@@ -1832,6 +1846,6 @@ function isNodeBuiltin(pkg) {
|
|
|
1832
1846
|
const base = pkg.startsWith("node:") ? pkg.slice(5) : pkg;
|
|
1833
1847
|
return NODE_BUILTINS.has(base.split("/")[0]);
|
|
1834
1848
|
}
|
|
1835
|
-
export {
|
|
1849
|
+
export { detectInstalledAgents as _, optimizeDocs as a, targets as b, computeSkillDirName as c, sanitizeName as d, unlinkSkillFromAgents as f, buildSectionPrompt as g, buildAllSectionPrompts as h, getModelName as i, installSkillForAgents as l, SECTION_OUTPUT_FILES as m, getAvailableModels as n, generateSkillMd as o, SECTION_MERGE_ORDER as p, getModelLabel as r, FILE_PATTERN_MAP as s, detectImportedPackages as t, linkSkillToAgents as u, detectTargetAgent as v, __exportAll as x, getAgentVersion as y };
|
|
1836
1850
|
|
|
1837
1851
|
//# sourceMappingURL=detect-imports.mjs.map
|