skilld 0.0.1 → 0.1.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/LICENSE +21 -0
- package/README.md +119 -88
- package/dist/_chunks/config.mjs +20 -0
- package/dist/_chunks/config.mjs.map +1 -0
- package/dist/_chunks/llm.mjs +877 -0
- package/dist/_chunks/llm.mjs.map +1 -0
- package/dist/_chunks/releases.mjs +986 -0
- package/dist/_chunks/releases.mjs.map +1 -0
- package/dist/_chunks/storage.mjs +198 -0
- package/dist/_chunks/storage.mjs.map +1 -0
- package/dist/_chunks/sync-parallel.mjs +540 -0
- package/dist/_chunks/sync-parallel.mjs.map +1 -0
- package/dist/_chunks/types.d.mts +87 -0
- package/dist/_chunks/types.d.mts.map +1 -0
- package/dist/_chunks/utils.d.mts +352 -0
- package/dist/_chunks/utils.d.mts.map +1 -0
- package/dist/_chunks/version.d.mts +147 -0
- package/dist/_chunks/version.d.mts.map +1 -0
- package/dist/agent/index.d.mts +205 -0
- package/dist/agent/index.d.mts.map +1 -0
- package/dist/agent/index.mjs +2 -0
- package/dist/cache/index.d.mts +2 -0
- package/dist/cache/index.mjs +3 -0
- package/dist/cli.mjs +2650 -449
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +5 -14
- package/dist/index.mjs +7 -181
- package/dist/retriv/index.d.mts +12 -0
- package/dist/retriv/index.d.mts.map +1 -0
- package/dist/retriv/index.mjs +76 -0
- package/dist/retriv/index.mjs.map +1 -0
- package/dist/sources/index.d.mts +2 -0
- package/dist/sources/index.mjs +3 -0
- package/dist/types.d.mts +4 -37
- package/package.json +39 -13
- package/dist/agents.d.mts +0 -56
- package/dist/agents.d.mts.map +0 -1
- package/dist/agents.mjs +0 -148
- package/dist/agents.mjs.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/npm.d.mts +0 -48
- package/dist/npm.d.mts.map +0 -1
- package/dist/npm.mjs +0 -90
- package/dist/npm.mjs.map +0 -1
- package/dist/split-text.d.mts +0 -24
- package/dist/split-text.d.mts.map +0 -1
- package/dist/split-text.mjs +0 -87
- package/dist/split-text.mjs.map +0 -1
- package/dist/types.d.mts.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,181 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const dbPath = join$1(skillDir, "search.db");
|
|
9
|
-
mkdirSync(referencesDir, { recursive: true });
|
|
10
|
-
let docs;
|
|
11
|
-
let skillContent;
|
|
12
|
-
if (!skipLlmsTxt) {
|
|
13
|
-
const llmsResult = await fetchFromLlmsTxt(url, maxPages, onProgress);
|
|
14
|
-
if (llmsResult) {
|
|
15
|
-
docs = llmsResult.docs;
|
|
16
|
-
skillContent = llmsResult.llmsContent;
|
|
17
|
-
} else docs = await crawlSite(url, maxPages, onProgress);
|
|
18
|
-
} else docs = await crawlSite(url, maxPages, onProgress);
|
|
19
|
-
if (docs.length === 0) throw new Error("No documents found to index");
|
|
20
|
-
const skillPath = join$1(skillDir, "SKILL.md");
|
|
21
|
-
if (skillContent) writeFileSync(skillPath, skillContent);
|
|
22
|
-
const { splitText } = await import("./split-text.mjs");
|
|
23
|
-
const { sqliteVec } = await import("retriv/db/sqlite-vec");
|
|
24
|
-
const { transformers } = await import("retriv/embeddings/transformers");
|
|
25
|
-
const documents = [];
|
|
26
|
-
for (const doc of docs) {
|
|
27
|
-
const chunks = splitText(doc.content, {
|
|
28
|
-
chunkSize,
|
|
29
|
-
chunkOverlap
|
|
30
|
-
});
|
|
31
|
-
for (const chunk of chunks) {
|
|
32
|
-
const section = extractSection(chunk.text);
|
|
33
|
-
const docId = chunks.length > 1 ? `${doc.url}#chunk-${chunk.index}` : doc.url;
|
|
34
|
-
const prefix = [doc.title, section].filter(Boolean).join(" > ");
|
|
35
|
-
const content = prefix ? `${prefix}\n\n${chunk.text}` : chunk.text;
|
|
36
|
-
documents.push({
|
|
37
|
-
id: docId,
|
|
38
|
-
content,
|
|
39
|
-
metadata: {
|
|
40
|
-
source: doc.url,
|
|
41
|
-
title: doc.title,
|
|
42
|
-
...section && { section },
|
|
43
|
-
...chunks.length > 1 && {
|
|
44
|
-
chunkIndex: chunk.index,
|
|
45
|
-
chunkTotal: chunks.length
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
writeFileSync(join$1(referencesDir, sanitizeFilename(docId) + ".md"), formatReferenceFile(docId, doc, section, chunk, chunks.length));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
onProgress?.({
|
|
53
|
-
url: "embedding",
|
|
54
|
-
count: documents.length,
|
|
55
|
-
phase: "index"
|
|
56
|
-
});
|
|
57
|
-
const db = await sqliteVec({
|
|
58
|
-
path: dbPath,
|
|
59
|
-
embeddings: transformers({ model })
|
|
60
|
-
});
|
|
61
|
-
await db.index(documents);
|
|
62
|
-
await db.close?.();
|
|
63
|
-
return {
|
|
64
|
-
siteName,
|
|
65
|
-
skillPath,
|
|
66
|
-
referencesDir,
|
|
67
|
-
dbPath,
|
|
68
|
-
chunkCount: documents.length
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function getSiteName(url) {
|
|
72
|
-
return new URL(url).hostname.replace(/^www\./, "");
|
|
73
|
-
}
|
|
74
|
-
function sanitizeFilename(id) {
|
|
75
|
-
return id.replace(/^https?:\/\//, "").replace(/[#?]/g, "-").replace(/[^a-z0-9.-]/gi, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 100);
|
|
76
|
-
}
|
|
77
|
-
function extractSection(text) {
|
|
78
|
-
const headings = [];
|
|
79
|
-
for (const line of text.split("\n")) {
|
|
80
|
-
const match = line.match(/^(#{1,6}) ([^\n]+)$/);
|
|
81
|
-
if (match) {
|
|
82
|
-
const level = match[1].length;
|
|
83
|
-
const heading = match[2].trim();
|
|
84
|
-
headings.length = level - 1;
|
|
85
|
-
headings[level - 1] = heading;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return headings.filter(Boolean).join(" > ") || void 0;
|
|
89
|
-
}
|
|
90
|
-
function formatReferenceFile(docId, doc, section, chunk, totalChunks) {
|
|
91
|
-
const frontmatter = [
|
|
92
|
-
"---",
|
|
93
|
-
`id: "${docId}"`,
|
|
94
|
-
`source: "${doc.url}"`,
|
|
95
|
-
`title: "${doc.title}"`
|
|
96
|
-
];
|
|
97
|
-
if (section) frontmatter.push(`section: "${section}"`);
|
|
98
|
-
if (totalChunks > 1) frontmatter.push(`chunk: ${chunk.index + 1}/${totalChunks}`);
|
|
99
|
-
frontmatter.push("---", "");
|
|
100
|
-
const prefix = [doc.title, section].filter(Boolean).join(" > ");
|
|
101
|
-
return frontmatter.join("\n") + (prefix ? `${prefix}\n\n` : "") + chunk.text;
|
|
102
|
-
}
|
|
103
|
-
async function fetchFromLlmsTxt(baseUrl, maxPages, onProgress) {
|
|
104
|
-
const llmsUrl = `${new URL(baseUrl).origin}/llms.txt`;
|
|
105
|
-
const res = await fetch(llmsUrl, { headers: { "User-Agent": "skilld/1.0" } }).catch(() => null);
|
|
106
|
-
if (!res?.ok) return null;
|
|
107
|
-
const llmsContent = await res.text();
|
|
108
|
-
if (llmsContent.length < 50) return null;
|
|
109
|
-
const links = parseLinks(llmsContent);
|
|
110
|
-
const docs = [];
|
|
111
|
-
let count = 0;
|
|
112
|
-
for (const { title, url } of links.slice(0, maxPages)) {
|
|
113
|
-
count++;
|
|
114
|
-
onProgress?.({
|
|
115
|
-
url,
|
|
116
|
-
count,
|
|
117
|
-
phase: "fetch"
|
|
118
|
-
});
|
|
119
|
-
const content = await fetchMarkdown(url);
|
|
120
|
-
if (content && content.length >= 50) docs.push({
|
|
121
|
-
url,
|
|
122
|
-
title,
|
|
123
|
-
content
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
return {
|
|
127
|
-
docs,
|
|
128
|
-
llmsContent
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
function parseLinks(content) {
|
|
132
|
-
const links = [];
|
|
133
|
-
const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
134
|
-
let match;
|
|
135
|
-
while ((match = linkRegex.exec(content)) !== null) {
|
|
136
|
-
const [, title, url] = match;
|
|
137
|
-
if (url.includes("/raw/") || url.endsWith(".md")) links.push({
|
|
138
|
-
title,
|
|
139
|
-
url
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
return links;
|
|
143
|
-
}
|
|
144
|
-
async function fetchMarkdown(url) {
|
|
145
|
-
const res = await fetch(url, { headers: { "User-Agent": "skilld/1.0" } }).catch(() => null);
|
|
146
|
-
if (!res?.ok) return null;
|
|
147
|
-
return res.text();
|
|
148
|
-
}
|
|
149
|
-
async function crawlSite(url, maxPages, onProgress) {
|
|
150
|
-
const { htmlToMarkdown } = await import("mdream");
|
|
151
|
-
const { crawlAndGenerate } = await import("@mdream/crawl");
|
|
152
|
-
const { tmpdir } = await import("node:os");
|
|
153
|
-
const { join } = await import("node:path");
|
|
154
|
-
const docs = [];
|
|
155
|
-
let count = 0;
|
|
156
|
-
const outputDir = join(tmpdir(), `skilld-crawl-${Date.now()}`);
|
|
157
|
-
await crawlAndGenerate({
|
|
158
|
-
urls: [url],
|
|
159
|
-
outputDir,
|
|
160
|
-
maxRequestsPerCrawl: maxPages,
|
|
161
|
-
followLinks: true,
|
|
162
|
-
onPage: async ({ url: pageUrl, html, title }) => {
|
|
163
|
-
count++;
|
|
164
|
-
onProgress?.({
|
|
165
|
-
url: pageUrl,
|
|
166
|
-
count,
|
|
167
|
-
phase: "fetch"
|
|
168
|
-
});
|
|
169
|
-
const markdown = htmlToMarkdown(html, { origin: new URL(pageUrl).origin });
|
|
170
|
-
if (markdown && markdown.length >= 50) docs.push({
|
|
171
|
-
url: pageUrl,
|
|
172
|
-
title: title || pageUrl,
|
|
173
|
-
content: markdown
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
});
|
|
177
|
-
return docs;
|
|
178
|
-
}
|
|
179
|
-
export { generateSkill };
|
|
180
|
-
|
|
181
|
-
//# sourceMappingURL=index.mjs.map
|
|
1
|
+
import { a as getCacheDir, n as REFERENCES_DIR, o as getCacheKey, r as SEARCH_DB, s as getVersionKey, t as CACHE_DIR } from "./_chunks/config.mjs";
|
|
2
|
+
import { _ as writeToCache, h as readCachedDocs, n as clearCache, p as listCached, r as ensureCacheDir, s as isCached, t as clearAllCache, u as linkReferences } from "./_chunks/storage.mjs";
|
|
3
|
+
import "./cache/index.mjs";
|
|
4
|
+
import { createIndex, search, searchSnippets } from "./retriv/index.mjs";
|
|
5
|
+
import { S as fetchReadmeContent, _ as normalizeLlmsLinks, c as readLocalDependencies, d as resolvePackageDocs, h as fetchLlmsTxt, p as downloadLlmsDocs, r as fetchNpmPackage, v as parseMarkdownLinks } from "./_chunks/releases.mjs";
|
|
6
|
+
import "./sources/index.mjs";
|
|
7
|
+
export { CACHE_DIR, REFERENCES_DIR, SEARCH_DB, clearAllCache, clearCache, createIndex, downloadLlmsDocs, ensureCacheDir, fetchLlmsTxt, fetchNpmPackage, fetchReadmeContent, getCacheDir, getCacheKey, getVersionKey, isCached, linkReferences, listCached, normalizeLlmsLinks, parseMarkdownLinks, readCachedDocs, readLocalDependencies, resolvePackageDocs, search, searchSnippets, writeToCache };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { a as SearchOptions, i as SearchFilter, n as Document, o as SearchResult, r as IndexConfig, s as SearchSnippet, t as ChunkEntity } from "../_chunks/types.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/retriv/index.d.ts
|
|
4
|
+
declare function createIndex(documents: Document[], config: IndexConfig): Promise<void>;
|
|
5
|
+
declare function search(query: string, config: IndexConfig, options?: SearchOptions): Promise<SearchResult[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Search and return formatted snippets
|
|
8
|
+
*/
|
|
9
|
+
declare function searchSnippets(query: string, config: IndexConfig, options?: SearchOptions): Promise<SearchSnippet[]>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type ChunkEntity, type Document, type IndexConfig, type SearchFilter, type SearchOptions, type SearchResult, type SearchSnippet, createIndex, search, searchSnippets };
|
|
12
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/retriv/index.ts"],"mappings":";;;iBAkBsB,WAAA,CACpB,SAAA,EAAW,QAAA,IACX,MAAA,EAAQ,WAAA,GACP,OAAA;AAAA,iBAkBmB,MAAA,CACpB,KAAA,UACA,MAAA,EAAQ,WAAA,EACR,OAAA,GAAS,aAAA,GACR,OAAA,CAAQ,YAAA;;;;iBA6BW,cAAA,CACpB,KAAA,UACA,MAAA,EAAQ,WAAA,EACR,OAAA,GAAS,aAAA,GACR,OAAA,CAAQ,aAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { createRetriv } from "retriv";
|
|
2
|
+
import { autoChunker } from "retriv/chunkers/auto";
|
|
3
|
+
import sqlite from "retriv/db/sqlite";
|
|
4
|
+
import { transformersJs } from "retriv/embeddings/transformers-js";
|
|
5
|
+
function getDb(config) {
|
|
6
|
+
return createRetriv({
|
|
7
|
+
driver: sqlite({
|
|
8
|
+
path: config.dbPath,
|
|
9
|
+
embeddings: transformersJs()
|
|
10
|
+
}),
|
|
11
|
+
chunking: autoChunker()
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
async function createIndex(documents, config) {
|
|
15
|
+
const db = await getDb(config);
|
|
16
|
+
const BATCH_SIZE = 5;
|
|
17
|
+
let indexed = 0;
|
|
18
|
+
for (let i = 0; i < documents.length; i += BATCH_SIZE) {
|
|
19
|
+
const batch = documents.slice(i, i + BATCH_SIZE);
|
|
20
|
+
await db.index(batch);
|
|
21
|
+
indexed += batch.length;
|
|
22
|
+
const last = batch[batch.length - 1];
|
|
23
|
+
config.onProgress?.(indexed, documents.length, {
|
|
24
|
+
id: last.id,
|
|
25
|
+
type: last.metadata?.type
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
await db.close?.();
|
|
29
|
+
}
|
|
30
|
+
async function search(query, config, options = {}) {
|
|
31
|
+
const { limit = 10, filter } = options;
|
|
32
|
+
const db = await getDb(config);
|
|
33
|
+
const results = await db.search(query, {
|
|
34
|
+
limit,
|
|
35
|
+
filter,
|
|
36
|
+
returnContent: true,
|
|
37
|
+
returnMetadata: true,
|
|
38
|
+
returnMeta: true
|
|
39
|
+
});
|
|
40
|
+
await db.close?.();
|
|
41
|
+
return results.map((r) => ({
|
|
42
|
+
id: r.id,
|
|
43
|
+
content: r.content ?? "",
|
|
44
|
+
score: r.score,
|
|
45
|
+
metadata: r.metadata ?? {},
|
|
46
|
+
highlights: r._meta?.highlights ?? [],
|
|
47
|
+
lineRange: r._chunk?.lineRange,
|
|
48
|
+
entities: r._chunk?.entities,
|
|
49
|
+
scope: r._chunk?.scope
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
function stripFrontmatter(content) {
|
|
53
|
+
const match = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n/);
|
|
54
|
+
return match ? content.slice(match[0].length).trim() : content;
|
|
55
|
+
}
|
|
56
|
+
async function searchSnippets(query, config, options = {}) {
|
|
57
|
+
return (await search(query, config, options)).map((r) => {
|
|
58
|
+
const content = stripFrontmatter(r.content);
|
|
59
|
+
const source = r.metadata.source || r.id;
|
|
60
|
+
const lines = content.split("\n").length;
|
|
61
|
+
return {
|
|
62
|
+
package: r.metadata.package || "unknown",
|
|
63
|
+
source,
|
|
64
|
+
lineStart: r.lineRange?.[0] ?? 1,
|
|
65
|
+
lineEnd: r.lineRange?.[1] ?? lines,
|
|
66
|
+
content,
|
|
67
|
+
score: r.score,
|
|
68
|
+
highlights: r.highlights,
|
|
69
|
+
entities: r.entities,
|
|
70
|
+
scope: r.scope
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
export { createIndex, search, searchSnippets };
|
|
75
|
+
|
|
76
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/retriv/index.ts"],"sourcesContent":["import type { ChunkEntity, Document, IndexConfig, SearchFilter, SearchOptions, SearchResult, SearchSnippet } from './types'\nimport { createRetriv } from 'retriv'\nimport { autoChunker } from 'retriv/chunkers/auto'\nimport sqlite from 'retriv/db/sqlite'\nimport { transformersJs } from 'retriv/embeddings/transformers-js'\n\nexport type { ChunkEntity, Document, IndexConfig, SearchFilter, SearchOptions, SearchResult, SearchSnippet }\n\nfunction getDb(config: IndexConfig) {\n return createRetriv({\n driver: sqlite({\n path: config.dbPath,\n embeddings: transformersJs(),\n }),\n chunking: autoChunker(),\n })\n}\n\nexport async function createIndex(\n documents: Document[],\n config: IndexConfig,\n): Promise<void> {\n const db = await getDb(config)\n\n // Batch documents to report progress\n const BATCH_SIZE = 5\n let indexed = 0\n\n for (let i = 0; i < documents.length; i += BATCH_SIZE) {\n const batch = documents.slice(i, i + BATCH_SIZE)\n await db.index(batch)\n indexed += batch.length\n const last = batch[batch.length - 1]!\n config.onProgress?.(indexed, documents.length, { id: last.id, type: last.metadata?.type })\n }\n\n await db.close?.()\n}\n\nexport async function search(\n query: string,\n config: IndexConfig,\n options: SearchOptions = {},\n): Promise<SearchResult[]> {\n const { limit = 10, filter } = options\n const db = await getDb(config)\n const results = await db.search(query, { limit, filter, returnContent: true, returnMetadata: true, returnMeta: true })\n await db.close?.()\n\n return results.map(r => ({\n id: r.id,\n content: r.content ?? '',\n score: r.score,\n metadata: r.metadata ?? {},\n highlights: r._meta?.highlights ?? [],\n lineRange: r._chunk?.lineRange,\n entities: r._chunk?.entities,\n scope: r._chunk?.scope,\n }))\n}\n\n/**\n * Strip YAML frontmatter from markdown content\n */\nfunction stripFrontmatter(content: string): string {\n const match = content.match(/^---\\r?\\n[\\s\\S]*?\\r?\\n---\\r?\\n/)\n return match ? content.slice(match[0].length).trim() : content\n}\n\n/**\n * Search and return formatted snippets\n */\nexport async function searchSnippets(\n query: string,\n config: IndexConfig,\n options: SearchOptions = {},\n): Promise<SearchSnippet[]> {\n const results = await search(query, config, options)\n\n return results.map((r) => {\n const content = stripFrontmatter(r.content)\n const source = r.metadata.source || r.id\n const lines = content.split('\\n').length\n\n return {\n package: r.metadata.package || 'unknown',\n source,\n lineStart: r.lineRange?.[0] ?? 1,\n lineEnd: r.lineRange?.[1] ?? lines,\n content,\n score: r.score,\n highlights: r.highlights,\n entities: r.entities,\n scope: r.scope,\n }\n })\n}\n"],"mappings":";;;;AAQA,SAAS,MAAM,QAAqB;AAClC,QAAO,aAAa;EAClB,QAAQ,OAAO;GACb,MAAM,OAAO;GACb,YAAY,gBAAA;GACb,CAAC;EACF,UAAU,aAAA;EACX,CAAC;;AAGJ,eAAsB,YACpB,WACA,QACe;CACf,MAAM,KAAK,MAAM,MAAM,OAAO;CAG9B,MAAM,aAAa;CACnB,IAAI,UAAU;AAEd,MAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,YAAY;EACrD,MAAM,QAAQ,UAAU,MAAM,GAAG,IAAI,WAAW;AAChD,QAAM,GAAG,MAAM,MAAM;AACrB,aAAW,MAAM;EACjB,MAAM,OAAO,MAAM,MAAM,SAAS;AAClC,SAAO,aAAa,SAAS,UAAU,QAAQ;GAAE,IAAI,KAAK;GAAI,MAAM,KAAK,UAAU;GAAM,CAAC;;AAG5F,OAAM,GAAG,SAAS;;AAGpB,eAAsB,OACpB,OACA,QACA,UAAyB,EAAE,EACF;CACzB,MAAM,EAAE,QAAQ,IAAI,WAAW;CAC/B,MAAM,KAAK,MAAM,MAAM,OAAO;CAC9B,MAAM,UAAU,MAAM,GAAG,OAAO,OAAO;EAAE;EAAO;EAAQ,eAAe;EAAM,gBAAgB;EAAM,YAAY;EAAM,CAAC;AACtH,OAAM,GAAG,SAAS;AAElB,QAAO,QAAQ,KAAI,OAAM;EACvB,IAAI,EAAE;EACN,SAAS,EAAE,WAAW;EACtB,OAAO,EAAE;EACT,UAAU,EAAE,YAAY,EAAE;EAC1B,YAAY,EAAE,OAAO,cAAc,EAAE;EACrC,WAAW,EAAE,QAAQ;EACrB,UAAU,EAAE,QAAQ;EACpB,OAAO,EAAE,QAAQ;EAClB,EAAE;;AAML,SAAS,iBAAiB,SAAyB;CACjD,MAAM,QAAQ,QAAQ,MAAM,iCAAiC;AAC7D,QAAO,QAAQ,QAAQ,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG;;AAMzD,eAAsB,eACpB,OACA,QACA,UAAyB,EAAE,EACD;AAG1B,SAFgB,MAAM,OAAO,OAAO,QAAQ,QAAQ,EAErC,KAAK,MAAM;EACxB,MAAM,UAAU,iBAAiB,EAAE,QAAQ;EAC3C,MAAM,SAAS,EAAE,SAAS,UAAU,EAAE;EACtC,MAAM,QAAQ,QAAQ,MAAM,KAAK,CAAC;AAElC,SAAO;GACL,SAAS,EAAE,SAAS,WAAW;GAC/B;GACA,WAAW,EAAE,YAAY,MAAM;GAC/B,SAAS,EAAE,YAAY,MAAM;GAC7B;GACA,OAAO,EAAE;GACT,YAAY,EAAE;GACd,UAAU,EAAE;GACZ,OAAO,EAAE;GACV;GACD"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { A as parseMarkdownLinks, B as fetchGitHubIssues, C as resolvePackageDocs, D as fetchLlmsTxt, E as extractSections, F as NpmPackageInfo, G as fetchGitHubRepoMeta, H as isGhAvailable, I as ResolveAttempt, J as EntryFile, K as fetchReadme, L as ResolveResult, M as LlmsContent, N as LlmsLink, O as fetchLlmsUrl, P as LocalDependency, Q as formatDiscussionsAsMarkdown, R as ResolvedPackage, S as resolveLocalPackageDocs, T as downloadLlmsDocs, U as GitDocsResult, V as formatIssuesAsMarkdown, W as fetchGitDocs, X as GitHubDiscussion, Y as resolveEntryFiles, Z as fetchGitHubDiscussions, _ as fetchPkgDist, a as verifyUrl, b as readLocalDependencies, c as DOC_OVERRIDES, d as LocalPackageInfo, f as ResolveOptions, g as fetchNpmRegistryMeta, h as fetchNpmPackage, i as parseGitHubUrl, j as FetchedDoc, k as normalizeLlmsLinks, l as DocOverride, m as fetchLatestVersion, n as isGitHubRepoUrl, o as GitHubRelease, p as ResolveStep, q as fetchReadmeContent, r as normalizeRepoUrl, s as fetchReleaseNotes, t as fetchText, u as getDocOverride, v as getInstalledSkillVersion, w as resolvePackageDocsWithAttempts, x as readLocalPackageInfo, y as parseVersionSpecifier, z as GitHubIssue } from "../_chunks/utils.mjs";
|
|
2
|
+
export { DOC_OVERRIDES, type DocOverride, type EntryFile, type FetchedDoc, type GitDocsResult, type GitHubDiscussion, type GitHubIssue, type GitHubRelease, type LlmsContent, type LlmsLink, type LocalDependency, type LocalPackageInfo, type NpmPackageInfo, type ResolveAttempt, type ResolveOptions, type ResolveResult, type ResolveStep, type ResolvedPackage, downloadLlmsDocs, extractSections, fetchGitDocs, fetchGitHubDiscussions, fetchGitHubIssues, fetchGitHubRepoMeta, fetchLatestVersion, fetchLlmsTxt, fetchLlmsUrl, fetchNpmPackage, fetchNpmRegistryMeta, fetchPkgDist, fetchReadme, fetchReadmeContent, fetchReleaseNotes, fetchText, formatDiscussionsAsMarkdown, formatIssuesAsMarkdown, getDocOverride, getInstalledSkillVersion, isGhAvailable, isGitHubRepoUrl, normalizeLlmsLinks, normalizeRepoUrl, parseGitHubUrl, parseMarkdownLinks, parseVersionSpecifier, readLocalDependencies, readLocalPackageInfo, resolveEntryFiles, resolveLocalPackageDocs, resolvePackageDocs, resolvePackageDocsWithAttempts, verifyUrl };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import "../_chunks/config.mjs";
|
|
2
|
+
import { A as resolveEntryFiles, C as fetchText, D as verifyUrl, E as parseGitHubUrl, F as isGhAvailable, M as formatDiscussionsAsMarkdown, N as fetchGitHubIssues, O as DOC_OVERRIDES, P as formatIssuesAsMarkdown, S as fetchReadmeContent, T as normalizeRepoUrl, _ as normalizeLlmsLinks, a as fetchPkgDist, b as fetchGitHubRepoMeta, c as readLocalDependencies, d as resolvePackageDocs, f as resolvePackageDocsWithAttempts, g as fetchLlmsUrl, h as fetchLlmsTxt, i as fetchNpmRegistryMeta, j as fetchGitHubDiscussions, k as getDocOverride, l as readLocalPackageInfo, m as extractSections, n as fetchLatestVersion, o as getInstalledSkillVersion, p as downloadLlmsDocs, r as fetchNpmPackage, s as parseVersionSpecifier, t as fetchReleaseNotes, u as resolveLocalPackageDocs, v as parseMarkdownLinks, w as isGitHubRepoUrl, x as fetchReadme, y as fetchGitDocs } from "../_chunks/releases.mjs";
|
|
3
|
+
export { DOC_OVERRIDES, downloadLlmsDocs, extractSections, fetchGitDocs, fetchGitHubDiscussions, fetchGitHubIssues, fetchGitHubRepoMeta, fetchLatestVersion, fetchLlmsTxt, fetchLlmsUrl, fetchNpmPackage, fetchNpmRegistryMeta, fetchPkgDist, fetchReadme, fetchReadmeContent, fetchReleaseNotes, fetchText, formatDiscussionsAsMarkdown, formatIssuesAsMarkdown, getDocOverride, getInstalledSkillVersion, isGhAvailable, isGitHubRepoUrl, normalizeLlmsLinks, normalizeRepoUrl, parseGitHubUrl, parseMarkdownLinks, parseVersionSpecifier, readLocalDependencies, readLocalPackageInfo, resolveEntryFiles, resolveLocalPackageDocs, resolvePackageDocs, resolvePackageDocsWithAttempts, verifyUrl };
|
package/dist/types.d.mts
CHANGED
|
@@ -1,37 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
/** Output directory for skill files */
|
|
6
|
-
outputDir?: string;
|
|
7
|
-
/** Chunk size in characters */
|
|
8
|
-
chunkSize?: number;
|
|
9
|
-
/** Chunk overlap in characters */
|
|
10
|
-
chunkOverlap?: number;
|
|
11
|
-
/** Max pages to fetch */
|
|
12
|
-
maxPages?: number;
|
|
13
|
-
/** Skip llms.txt check and always crawl */
|
|
14
|
-
skipLlmsTxt?: boolean;
|
|
15
|
-
/** Embedding model */
|
|
16
|
-
model?: string;
|
|
17
|
-
}
|
|
18
|
-
interface SkillResult {
|
|
19
|
-
/** Site name (hostname) */
|
|
20
|
-
siteName: string;
|
|
21
|
-
/** Path to SKILL.md */
|
|
22
|
-
skillPath: string;
|
|
23
|
-
/** Path to references directory */
|
|
24
|
-
referencesDir: string;
|
|
25
|
-
/** Path to search database */
|
|
26
|
-
dbPath: string;
|
|
27
|
-
/** Number of chunks indexed */
|
|
28
|
-
chunkCount: number;
|
|
29
|
-
}
|
|
30
|
-
interface FetchedDoc {
|
|
31
|
-
url: string;
|
|
32
|
-
title: string;
|
|
33
|
-
content: string;
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
|
-
export { FetchedDoc, SkillConfig, SkillResult };
|
|
37
|
-
//# sourceMappingURL=types.d.mts.map
|
|
1
|
+
import { S as CacheConfig, w as CachedPackage } from "./_chunks/version.mjs";
|
|
2
|
+
import { a as SearchOptions, i as SearchFilter, n as Document, o as SearchResult, r as IndexConfig, s as SearchSnippet } from "./_chunks/types.mjs";
|
|
3
|
+
import { M as LlmsContent, N as LlmsLink, j as FetchedDoc } from "./_chunks/utils.mjs";
|
|
4
|
+
export { type CacheConfig, type CachedPackage, type Document, type FetchedDoc, type IndexConfig, type LlmsContent, type LlmsLink, type SearchFilter, type SearchOptions, type SearchResult, type SearchSnippet };
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skilld",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"description": "Generate
|
|
4
|
+
"version": "0.1.1",
|
|
5
|
+
"description": "Generate AI agent skills from npm package documentation",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Harlan Wilton",
|
|
8
8
|
"email": "harlan@harlanzw.com",
|
|
@@ -13,6 +13,17 @@
|
|
|
13
13
|
"type": "git",
|
|
14
14
|
"url": "https://github.com/harlan-zw/skilld"
|
|
15
15
|
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agent",
|
|
19
|
+
"skills",
|
|
20
|
+
"npm",
|
|
21
|
+
"documentation",
|
|
22
|
+
"claude",
|
|
23
|
+
"llm",
|
|
24
|
+
"cursor",
|
|
25
|
+
"codex"
|
|
26
|
+
],
|
|
16
27
|
"exports": {
|
|
17
28
|
".": {
|
|
18
29
|
"types": "./dist/index.d.mts",
|
|
@@ -25,28 +36,43 @@
|
|
|
25
36
|
"skilld": "./dist/cli.mjs"
|
|
26
37
|
},
|
|
27
38
|
"files": [
|
|
28
|
-
"dist"
|
|
39
|
+
"dist",
|
|
40
|
+
"skills"
|
|
29
41
|
],
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=18"
|
|
44
|
+
},
|
|
30
45
|
"dependencies": {
|
|
46
|
+
"@clack/prompts": "^1.0.0",
|
|
31
47
|
"@huggingface/transformers": "^3.8.1",
|
|
32
|
-
"
|
|
33
|
-
"citty": "^0.1.6",
|
|
48
|
+
"citty": "^0.2.0",
|
|
34
49
|
"consola": "^3.4.2",
|
|
35
|
-
"
|
|
36
|
-
"
|
|
50
|
+
"globby": "^16.1.0",
|
|
51
|
+
"log-update": "^7.1.0",
|
|
52
|
+
"mlly": "^1.8.0",
|
|
53
|
+
"oxc-parser": "^0.112.0",
|
|
54
|
+
"p-limit": "^7.3.0",
|
|
55
|
+
"retriv": "^0.8.3",
|
|
56
|
+
"sqlite-vec": "^0.1.6",
|
|
57
|
+
"typescript": "^5.9.3"
|
|
37
58
|
},
|
|
38
59
|
"devDependencies": {
|
|
39
|
-
"@antfu/eslint-config": "^
|
|
40
|
-
"@types/node": "^
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
60
|
+
"@antfu/eslint-config": "^7.2.0",
|
|
61
|
+
"@types/node": "^25.2.1",
|
|
62
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
63
|
+
"bumpp": "^10.4.1",
|
|
64
|
+
"evalite": "^0.19.0",
|
|
65
|
+
"obuild": "^0.4.27",
|
|
66
|
+
"vitest": "^4.0.18"
|
|
44
67
|
},
|
|
45
68
|
"scripts": {
|
|
46
69
|
"build": "obuild",
|
|
47
70
|
"dev:prepare": "obuild --stub",
|
|
48
71
|
"lint": "eslint .",
|
|
72
|
+
"lint:fix": "eslint . --fix",
|
|
49
73
|
"typecheck": "tsc --noEmit",
|
|
50
|
-
"test": "vitest"
|
|
74
|
+
"test": "vitest",
|
|
75
|
+
"test:run": "vitest run",
|
|
76
|
+
"release": "bumpp && pnpm publish"
|
|
51
77
|
}
|
|
52
78
|
}
|
package/dist/agents.d.mts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
//#region src/agents.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Agent detection and skill installation
|
|
4
|
-
* Writes directly to agent skill directories in the project
|
|
5
|
-
*/
|
|
6
|
-
type AgentType = 'claude-code' | 'cursor' | 'windsurf' | 'cline' | 'codex' | 'github-copilot' | 'gemini-cli' | 'goose' | 'amp' | 'opencode' | 'roo';
|
|
7
|
-
interface AgentConfig {
|
|
8
|
-
name: AgentType;
|
|
9
|
-
displayName: string;
|
|
10
|
-
/** Project-level skills directory (e.g., .claude/skills) */
|
|
11
|
-
skillsDir: string;
|
|
12
|
-
/** Global skills directory (e.g., ~/.claude/skills) */
|
|
13
|
-
globalSkillsDir: string | undefined;
|
|
14
|
-
/** Check if agent is installed on the system */
|
|
15
|
-
detectInstalled: () => boolean;
|
|
16
|
-
}
|
|
17
|
-
declare const agents: Record<AgentType, AgentConfig>;
|
|
18
|
-
/**
|
|
19
|
-
* Detect which agents are installed on the system
|
|
20
|
-
*/
|
|
21
|
-
declare function detectInstalledAgents(): AgentType[];
|
|
22
|
-
/**
|
|
23
|
-
* Detect which agent is currently running this command
|
|
24
|
-
* Returns the active agent based on environment variables and context
|
|
25
|
-
*/
|
|
26
|
-
declare function detectCurrentAgent(): AgentType | null;
|
|
27
|
-
/**
|
|
28
|
-
* Sanitize skill name for filesystem
|
|
29
|
-
*/
|
|
30
|
-
declare function sanitizeName(name: string): string;
|
|
31
|
-
/**
|
|
32
|
-
* Install a skill directly to agent skill directories
|
|
33
|
-
* Writes to each agent's skill folder in the project (e.g., .claude/skills/package-name/)
|
|
34
|
-
*/
|
|
35
|
-
declare function installSkillForAgents(skillName: string, skillContent: string, options?: {
|
|
36
|
-
global?: boolean;
|
|
37
|
-
cwd?: string;
|
|
38
|
-
agents?: AgentType[]; /** Additional files to write (filename -> content) */
|
|
39
|
-
files?: Record<string, string>;
|
|
40
|
-
}): {
|
|
41
|
-
installed: AgentType[];
|
|
42
|
-
paths: string[];
|
|
43
|
-
};
|
|
44
|
-
interface SkillMetadata {
|
|
45
|
-
name: string;
|
|
46
|
-
version?: string;
|
|
47
|
-
description?: string;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Generate SKILL.md frontmatter content
|
|
51
|
-
* The description tells the agent when to use this skill
|
|
52
|
-
*/
|
|
53
|
-
declare function generateSkillMd(meta: SkillMetadata, body: string): string;
|
|
54
|
-
//#endregion
|
|
55
|
-
export { AgentConfig, AgentType, SkillMetadata, agents, detectCurrentAgent, detectInstalledAgents, generateSkillMd, installSkillForAgents, sanitizeName };
|
|
56
|
-
//# sourceMappingURL=agents.d.mts.map
|
package/dist/agents.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"agents.d.mts","names":[],"sources":["../src/agents.ts"],"mappings":";;AAcA;;;KAAY,SAAA;AAAA,UAaK,WAAA;EACf,IAAA,EAAM,SAAA;EACN,WAAA;;EAEA,SAAA;EAHA;EAKA,eAAA;EAJA;EAMA,eAAA;AAAA;AAAA,cAGW,MAAA,EAAQ,MAAA,CAAO,SAAA,EAAW,WAAA;;;AAAvC;iBAmFgB,qBAAA,CAAA,GAAyB,SAAA;;;;;iBAUzB,kBAAA,CAAA,GAAsB,SAAA;;;;iBAyDtB,YAAA,CAAa,IAAA;;;AAnE7B;;iBA+EgB,qBAAA,CACd,SAAA,UACA,YAAA,UACA,OAAA;EACE,MAAA;EACA,GAAA;EACA,MAAA,GAAS,SAAA,IA3EqB;EA6E9B,KAAA,GAAQ,MAAA;AAAA;EAEP,SAAA,EAAW,SAAA;EAAa,KAAA;AAAA;AAAA,UAuCZ,aAAA;EACf,IAAA;EACA,OAAA;EACA,WAAA;AAAA;;;;;iBAOc,eAAA,CACd,IAAA,EAAM,aAAA,EACN,IAAA"}
|
package/dist/agents.mjs
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { homedir } from "node:os";
|
|
4
|
-
const home = homedir();
|
|
5
|
-
const configHome = process.env.XDG_CONFIG_HOME || join(home, ".config");
|
|
6
|
-
const claudeHome = process.env.CLAUDE_CONFIG_DIR || join(home, ".claude");
|
|
7
|
-
const codexHome = process.env.CODEX_HOME || join(home, ".codex");
|
|
8
|
-
const agents = {
|
|
9
|
-
"claude-code": {
|
|
10
|
-
name: "claude-code",
|
|
11
|
-
displayName: "Claude Code",
|
|
12
|
-
skillsDir: ".claude/skills",
|
|
13
|
-
globalSkillsDir: join(claudeHome, "skills"),
|
|
14
|
-
detectInstalled: () => existsSync(claudeHome)
|
|
15
|
-
},
|
|
16
|
-
cursor: {
|
|
17
|
-
name: "cursor",
|
|
18
|
-
displayName: "Cursor",
|
|
19
|
-
skillsDir: ".cursor/skills",
|
|
20
|
-
globalSkillsDir: join(home, ".cursor/skills"),
|
|
21
|
-
detectInstalled: () => existsSync(join(home, ".cursor"))
|
|
22
|
-
},
|
|
23
|
-
windsurf: {
|
|
24
|
-
name: "windsurf",
|
|
25
|
-
displayName: "Windsurf",
|
|
26
|
-
skillsDir: ".windsurf/skills",
|
|
27
|
-
globalSkillsDir: join(home, ".codeium/windsurf/skills"),
|
|
28
|
-
detectInstalled: () => existsSync(join(home, ".codeium/windsurf"))
|
|
29
|
-
},
|
|
30
|
-
cline: {
|
|
31
|
-
name: "cline",
|
|
32
|
-
displayName: "Cline",
|
|
33
|
-
skillsDir: ".cline/skills",
|
|
34
|
-
globalSkillsDir: join(home, ".cline/skills"),
|
|
35
|
-
detectInstalled: () => existsSync(join(home, ".cline"))
|
|
36
|
-
},
|
|
37
|
-
codex: {
|
|
38
|
-
name: "codex",
|
|
39
|
-
displayName: "Codex",
|
|
40
|
-
skillsDir: ".codex/skills",
|
|
41
|
-
globalSkillsDir: join(codexHome, "skills"),
|
|
42
|
-
detectInstalled: () => existsSync(codexHome)
|
|
43
|
-
},
|
|
44
|
-
"github-copilot": {
|
|
45
|
-
name: "github-copilot",
|
|
46
|
-
displayName: "GitHub Copilot",
|
|
47
|
-
skillsDir: ".github/skills",
|
|
48
|
-
globalSkillsDir: join(home, ".copilot/skills"),
|
|
49
|
-
detectInstalled: () => existsSync(join(home, ".copilot"))
|
|
50
|
-
},
|
|
51
|
-
"gemini-cli": {
|
|
52
|
-
name: "gemini-cli",
|
|
53
|
-
displayName: "Gemini CLI",
|
|
54
|
-
skillsDir: ".gemini/skills",
|
|
55
|
-
globalSkillsDir: join(home, ".gemini/skills"),
|
|
56
|
-
detectInstalled: () => existsSync(join(home, ".gemini"))
|
|
57
|
-
},
|
|
58
|
-
goose: {
|
|
59
|
-
name: "goose",
|
|
60
|
-
displayName: "Goose",
|
|
61
|
-
skillsDir: ".goose/skills",
|
|
62
|
-
globalSkillsDir: join(configHome, "goose/skills"),
|
|
63
|
-
detectInstalled: () => existsSync(join(configHome, "goose"))
|
|
64
|
-
},
|
|
65
|
-
amp: {
|
|
66
|
-
name: "amp",
|
|
67
|
-
displayName: "Amp",
|
|
68
|
-
skillsDir: ".agents/skills",
|
|
69
|
-
globalSkillsDir: join(configHome, "agents/skills"),
|
|
70
|
-
detectInstalled: () => existsSync(join(configHome, "amp"))
|
|
71
|
-
},
|
|
72
|
-
opencode: {
|
|
73
|
-
name: "opencode",
|
|
74
|
-
displayName: "OpenCode",
|
|
75
|
-
skillsDir: ".opencode/skills",
|
|
76
|
-
globalSkillsDir: join(configHome, "opencode/skills"),
|
|
77
|
-
detectInstalled: () => existsSync(join(configHome, "opencode"))
|
|
78
|
-
},
|
|
79
|
-
roo: {
|
|
80
|
-
name: "roo",
|
|
81
|
-
displayName: "Roo Code",
|
|
82
|
-
skillsDir: ".roo/skills",
|
|
83
|
-
globalSkillsDir: join(home, ".roo/skills"),
|
|
84
|
-
detectInstalled: () => existsSync(join(home, ".roo"))
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
|
-
function detectInstalledAgents() {
|
|
88
|
-
return Object.entries(agents).filter(([_, config]) => config.detectInstalled()).map(([type]) => type);
|
|
89
|
-
}
|
|
90
|
-
function detectCurrentAgent() {
|
|
91
|
-
if (process.env.CLAUDE_CODE || process.env.CLAUDE_CONFIG_DIR) return "claude-code";
|
|
92
|
-
if (process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID) return "cursor";
|
|
93
|
-
if (process.env.WINDSURF_SESSION) return "windsurf";
|
|
94
|
-
if (process.env.CLINE_TASK_ID) return "cline";
|
|
95
|
-
if (process.env.CODEX_HOME || process.env.CODEX_SESSION) return "codex";
|
|
96
|
-
if (process.env.GITHUB_COPILOT_SESSION) return "github-copilot";
|
|
97
|
-
if (process.env.GEMINI_API_KEY && process.env.GEMINI_SESSION) return "gemini-cli";
|
|
98
|
-
if (process.env.GOOSE_SESSION) return "goose";
|
|
99
|
-
if (process.env.AMP_SESSION) return "amp";
|
|
100
|
-
if (process.env.OPENCODE_SESSION) return "opencode";
|
|
101
|
-
if (process.env.ROO_SESSION) return "roo";
|
|
102
|
-
const cwd = process.cwd();
|
|
103
|
-
if (existsSync(join(cwd, ".claude"))) return "claude-code";
|
|
104
|
-
if (existsSync(join(cwd, ".cursor"))) return "cursor";
|
|
105
|
-
if (existsSync(join(cwd, ".windsurf"))) return "windsurf";
|
|
106
|
-
if (existsSync(join(cwd, ".cline"))) return "cline";
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
109
|
-
function sanitizeName(name) {
|
|
110
|
-
return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
|
|
111
|
-
}
|
|
112
|
-
function installSkillForAgents(skillName, skillContent, options = {}) {
|
|
113
|
-
const isGlobal = options.global ?? false;
|
|
114
|
-
const cwd = options.cwd || process.cwd();
|
|
115
|
-
const sanitized = sanitizeName(skillName);
|
|
116
|
-
const targetAgents = options.agents || detectInstalledAgents();
|
|
117
|
-
const installed = [];
|
|
118
|
-
const paths = [];
|
|
119
|
-
for (const agentType of targetAgents) {
|
|
120
|
-
const agent = agents[agentType];
|
|
121
|
-
if (isGlobal && !agent.globalSkillsDir) continue;
|
|
122
|
-
const skillDir = join(isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir), sanitized);
|
|
123
|
-
mkdirSync(skillDir, { recursive: true });
|
|
124
|
-
writeFileSync(join(skillDir, "SKILL.md"), skillContent);
|
|
125
|
-
if (options.files) for (const [filename, content] of Object.entries(options.files)) writeFileSync(join(skillDir, filename), content);
|
|
126
|
-
installed.push(agentType);
|
|
127
|
-
paths.push(skillDir);
|
|
128
|
-
}
|
|
129
|
-
return {
|
|
130
|
-
installed,
|
|
131
|
-
paths
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
function generateSkillMd(meta, body) {
|
|
135
|
-
const { name, version, description: packageDescription } = meta;
|
|
136
|
-
const description = packageDescription ? `${packageDescription} Use this skill when working with ${name}, importing from "${name}", or when the user asks about ${name} features, API, or usage.` : `Documentation for ${name}. Use this skill when working with ${name} or importing from "${name}".`;
|
|
137
|
-
const frontmatter = [
|
|
138
|
-
"---",
|
|
139
|
-
`name: ${name}`,
|
|
140
|
-
`description: ${description}`
|
|
141
|
-
];
|
|
142
|
-
if (version) frontmatter.push(`version: "${version}"`);
|
|
143
|
-
frontmatter.push("---");
|
|
144
|
-
return frontmatter.join("\n") + "\n\n" + body;
|
|
145
|
-
}
|
|
146
|
-
export { agents, detectCurrentAgent, detectInstalledAgents, generateSkillMd, installSkillForAgents, sanitizeName };
|
|
147
|
-
|
|
148
|
-
//# sourceMappingURL=agents.mjs.map
|