skilld 0.9.5 → 0.10.0
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/_chunks/detect-imports.mjs +195 -126
- package/dist/_chunks/detect-imports.mjs.map +1 -1
- package/dist/_chunks/npm.mjs +201 -98
- package/dist/_chunks/npm.mjs.map +1 -1
- package/dist/_chunks/storage.mjs +12 -1
- package/dist/_chunks/storage.mjs.map +1 -1
- package/dist/_chunks/utils.d.mts +14 -1
- package/dist/_chunks/utils.d.mts.map +1 -1
- package/dist/_chunks/version.d.mts.map +1 -1
- package/dist/_chunks/yaml.mjs +1 -20
- package/dist/_chunks/yaml.mjs.map +1 -1
- package/dist/agent/index.d.mts +5 -1
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/cli.mjs +408 -270
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/sources/index.d.mts +2 -2
- package/dist/sources/index.mjs +3 -3
- package/dist/types.d.mts +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -5,8 +5,8 @@ import { a as getShippedSkills, b as sanitizeMarkdown, c as linkCachedDir, d as
|
|
|
5
5
|
import "./cache/index.mjs";
|
|
6
6
|
import { n as clearEmbeddingCache } from "./_chunks/embedding-cache.mjs";
|
|
7
7
|
import { closePool, createIndex, openPool, searchPooled, searchSnippets } from "./retriv/index.mjs";
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { i as getBlogPreset, n as yamlParseKV, r as yamlUnescape, t as yamlEscape } from "./_chunks/yaml.mjs";
|
|
9
|
+
import { $ as SHARED_SKILLS_DIR, E as normalizeLlmsLinks, F as fetchBlogReleases, K as parseGitHubUrl, L as fetchReleaseNotes, M as fetchGitHubDiscussions, N as formatDiscussionAsMarkdown, O as fetchGitSkills, P as generateDiscussionIndex, Q as isGhAvailable, R as generateReleaseIndex, S as downloadLlmsDocs, V as $fetch, X as formatIssueAsMarkdown, Y as fetchGitHubIssues, Z as generateIssueIndex, b as resolveGitHubRepo, d as resolvePackageDocs, et as getSharedSkillsDir, f as resolvePackageDocsWithAttempts, h as fetchGitDocs, i as fetchPkgDist, j as resolveEntryFiles, k as parseGitSkillInput, n as fetchNpmPackage, nt as semverGt, p as searchNpmPackages, q as parsePackageSpec, r as fetchNpmRegistryMeta, s as readLocalDependencies, t as fetchLatestVersion, tt as mapInsert, u as resolveLocalPackageDocs, v as fetchReadmeContent, w as fetchLlmsTxt, y as isShallowGitDocs } from "./_chunks/npm.mjs";
|
|
10
10
|
import "./sources/index.mjs";
|
|
11
11
|
import { S as targets, _ as maxItems, a as getModelName, b as detectTargetAgent, c as computeSkillDirName, d as sanitizeName, f as unlinkSkillFromAgents, i as getModelLabel, n as createToolProgress, o as optimizeDocs, r as getAvailableModels, s as generateSkillMd, t as detectImportedPackages, u as linkSkillToAgents, v as maxLines, x as getAgentVersion, y as detectInstalledAgents } from "./_chunks/detect-imports.mjs";
|
|
12
12
|
import "./agent/index.mjs";
|
|
@@ -960,7 +960,8 @@ async function fetchAndCacheResources(opts) {
|
|
|
960
960
|
results.push(...batchResults);
|
|
961
961
|
}
|
|
962
962
|
for (const r of results) if (r) {
|
|
963
|
-
const
|
|
963
|
+
const stripped = gitDocs.docsPrefix ? r.file.replace(gitDocs.docsPrefix, "") : r.file;
|
|
964
|
+
const cachePath = stripped.startsWith("docs/") ? stripped : `docs/${stripped}`;
|
|
964
965
|
cachedDocs.push({
|
|
965
966
|
path: cachePath,
|
|
966
967
|
content: r.content
|
|
@@ -1275,6 +1276,258 @@ function copyCachedSubdir(cacheDir, refsDir, subdir) {
|
|
|
1275
1276
|
}
|
|
1276
1277
|
walk(srcDir, "");
|
|
1277
1278
|
}
|
|
1279
|
+
async function ensureGitignore(skillsDir, cwd, isGlobal) {
|
|
1280
|
+
if (isGlobal) return;
|
|
1281
|
+
const gitignorePath = join(cwd, ".gitignore");
|
|
1282
|
+
const pattern = ".skilld";
|
|
1283
|
+
if (existsSync(gitignorePath)) {
|
|
1284
|
+
if (readFileSync(gitignorePath, "utf-8").split("\n").some((line) => line.trim() === pattern)) return;
|
|
1285
|
+
}
|
|
1286
|
+
if (!isInteractive()) {
|
|
1287
|
+
const entry = `\n# Skilld references (recreated by \`skilld install\`)\n${pattern}\n`;
|
|
1288
|
+
if (existsSync(gitignorePath)) appendFileSync(gitignorePath, `${readFileSync(gitignorePath, "utf-8").endsWith("\n") ? "" : "\n"}${entry}`);
|
|
1289
|
+
else writeFileSync(gitignorePath, entry);
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
p.log.info(`\x1B[1mGit guidance:\x1B[0m\n \x1B[32m✓\x1B[0m Commit: \x1B[36m${skillsDir}/*/SKILL.md\x1B[0m\n \x1B[32m✓\x1B[0m Commit: \x1B[36m${skillsDir}/skilld-lock.yaml\x1B[0m\n \x1B[31m✗\x1B[0m Ignore: \x1B[36m${pattern}\x1B[0m \x1B[90m(recreated by \`skilld install\`)\x1B[0m`);
|
|
1293
|
+
const add = await p.confirm({
|
|
1294
|
+
message: `Add \`${pattern}\` to .gitignore?`,
|
|
1295
|
+
initialValue: true
|
|
1296
|
+
});
|
|
1297
|
+
if (p.isCancel(add) || !add) return;
|
|
1298
|
+
const entry = `\n# Skilld references (recreated by \`skilld install\`)\n${pattern}\n`;
|
|
1299
|
+
if (existsSync(gitignorePath)) appendFileSync(gitignorePath, `${readFileSync(gitignorePath, "utf-8").endsWith("\n") ? "" : "\n"}${entry}`);
|
|
1300
|
+
else writeFileSync(gitignorePath, entry);
|
|
1301
|
+
p.log.success("Updated .gitignore");
|
|
1302
|
+
}
|
|
1303
|
+
const SKILLD_MARKER_START = "<!-- skilld -->";
|
|
1304
|
+
const SKILLD_MARKER_END = "<!-- /skilld -->";
|
|
1305
|
+
const SKILLD_INSTRUCTIONS = `${SKILLD_MARKER_START}
|
|
1306
|
+
Before modifying code, evaluate each installed skill against the current task.
|
|
1307
|
+
For each skill, determine YES/NO relevance and invoke all YES skills before proceeding.
|
|
1308
|
+
${SKILLD_MARKER_END}`;
|
|
1309
|
+
async function ensureAgentInstructions(agent, cwd, isGlobal) {
|
|
1310
|
+
if (isGlobal) return;
|
|
1311
|
+
const agentConfig = targets[agent];
|
|
1312
|
+
if (!agentConfig.instructionFile) return;
|
|
1313
|
+
const filePath = join(cwd, agentConfig.instructionFile);
|
|
1314
|
+
if (existsSync(filePath)) {
|
|
1315
|
+
if (readFileSync(filePath, "utf-8").includes(SKILLD_MARKER_START)) return;
|
|
1316
|
+
}
|
|
1317
|
+
if (!isInteractive()) {
|
|
1318
|
+
if (existsSync(filePath)) appendFileSync(filePath, `${readFileSync(filePath, "utf-8").endsWith("\n") ? "" : "\n"}\n${SKILLD_INSTRUCTIONS}\n`);
|
|
1319
|
+
else writeFileSync(filePath, `${SKILLD_INSTRUCTIONS}\n`);
|
|
1320
|
+
return;
|
|
1321
|
+
}
|
|
1322
|
+
p.note(SKILLD_INSTRUCTIONS, `Will be added to ${agentConfig.instructionFile}`);
|
|
1323
|
+
const add = await p.confirm({
|
|
1324
|
+
message: `Add skill activation instructions to ${agentConfig.instructionFile}?`,
|
|
1325
|
+
initialValue: true
|
|
1326
|
+
});
|
|
1327
|
+
if (p.isCancel(add) || !add) return;
|
|
1328
|
+
if (existsSync(filePath)) appendFileSync(filePath, `${readFileSync(filePath, "utf-8").endsWith("\n") ? "" : "\n"}\n${SKILLD_INSTRUCTIONS}\n`);
|
|
1329
|
+
else writeFileSync(filePath, `${SKILLD_INSTRUCTIONS}\n`);
|
|
1330
|
+
p.log.success(`Updated ${agentConfig.instructionFile}`);
|
|
1331
|
+
}
|
|
1332
|
+
async function selectModel(skipPrompt) {
|
|
1333
|
+
const config = readConfig();
|
|
1334
|
+
const available = await getAvailableModels();
|
|
1335
|
+
if (available.length === 0) {
|
|
1336
|
+
p.log.warn("No LLM CLIs found (claude, gemini, codex)");
|
|
1337
|
+
return null;
|
|
1338
|
+
}
|
|
1339
|
+
if (config.model && available.some((m) => m.id === config.model)) return config.model;
|
|
1340
|
+
if (skipPrompt) return available.find((m) => m.recommended)?.id ?? available[0].id;
|
|
1341
|
+
const modelChoice = await p.select({
|
|
1342
|
+
message: "Model for SKILL.md generation",
|
|
1343
|
+
options: available.map((m) => ({
|
|
1344
|
+
label: m.recommended ? `${m.name} (Recommended)` : m.name,
|
|
1345
|
+
value: m.id,
|
|
1346
|
+
hint: `${m.agentName} · ${m.hint}`
|
|
1347
|
+
})),
|
|
1348
|
+
initialValue: available.find((m) => m.recommended)?.id ?? available[0].id
|
|
1349
|
+
});
|
|
1350
|
+
if (p.isCancel(modelChoice)) {
|
|
1351
|
+
p.cancel("Cancelled");
|
|
1352
|
+
return null;
|
|
1353
|
+
}
|
|
1354
|
+
updateConfig({ model: modelChoice });
|
|
1355
|
+
return modelChoice;
|
|
1356
|
+
}
|
|
1357
|
+
const DEFAULT_SECTIONS = ["best-practices", "api-changes"];
|
|
1358
|
+
async function selectSkillSections(message = "Generate SKILL.md with LLM") {
|
|
1359
|
+
p.log.info("More sections = less budget each. Fewer sections = deeper coverage.");
|
|
1360
|
+
const selected = await p.multiselect({
|
|
1361
|
+
message,
|
|
1362
|
+
options: [
|
|
1363
|
+
{
|
|
1364
|
+
label: "API changes",
|
|
1365
|
+
value: "api-changes",
|
|
1366
|
+
hint: "new/deprecated APIs from version history"
|
|
1367
|
+
},
|
|
1368
|
+
{
|
|
1369
|
+
label: "Best practices",
|
|
1370
|
+
value: "best-practices",
|
|
1371
|
+
hint: "gotchas, pitfalls, patterns"
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
label: "Doc map",
|
|
1375
|
+
value: "api",
|
|
1376
|
+
hint: "compact index of exports linked to source files"
|
|
1377
|
+
},
|
|
1378
|
+
{
|
|
1379
|
+
label: "Custom section",
|
|
1380
|
+
value: "custom",
|
|
1381
|
+
hint: "add your own section"
|
|
1382
|
+
}
|
|
1383
|
+
],
|
|
1384
|
+
initialValues: DEFAULT_SECTIONS,
|
|
1385
|
+
required: false
|
|
1386
|
+
});
|
|
1387
|
+
if (p.isCancel(selected)) return {
|
|
1388
|
+
sections: [],
|
|
1389
|
+
cancelled: true
|
|
1390
|
+
};
|
|
1391
|
+
const sections = selected;
|
|
1392
|
+
if (sections.length === 0) return {
|
|
1393
|
+
sections: [],
|
|
1394
|
+
cancelled: false
|
|
1395
|
+
};
|
|
1396
|
+
if (sections.length > 1) {
|
|
1397
|
+
const n = sections.length;
|
|
1398
|
+
const budgetLines = [];
|
|
1399
|
+
for (const s of sections) switch (s) {
|
|
1400
|
+
case "api-changes":
|
|
1401
|
+
budgetLines.push(` API changes ≤${maxLines(50, 80, n)} lines, ${maxItems(6, 12, n)} items`);
|
|
1402
|
+
break;
|
|
1403
|
+
case "best-practices":
|
|
1404
|
+
budgetLines.push(` Best practices ≤${maxLines(80, 150, n)} lines, ${maxItems(4, 10, n)} items`);
|
|
1405
|
+
break;
|
|
1406
|
+
case "api":
|
|
1407
|
+
budgetLines.push(` Doc map ≤${maxLines(15, 25, n)} lines`);
|
|
1408
|
+
break;
|
|
1409
|
+
case "custom":
|
|
1410
|
+
budgetLines.push(` Custom ≤${maxLines(50, 80, n)} lines`);
|
|
1411
|
+
break;
|
|
1412
|
+
}
|
|
1413
|
+
p.log.info(`Budget (${n} sections):\n${budgetLines.join("\n")}`);
|
|
1414
|
+
}
|
|
1415
|
+
let customPrompt;
|
|
1416
|
+
if (sections.includes("custom")) {
|
|
1417
|
+
const heading = await p.text({
|
|
1418
|
+
message: "Section heading",
|
|
1419
|
+
placeholder: "e.g. \"Migration from v2\" or \"SSR Patterns\""
|
|
1420
|
+
});
|
|
1421
|
+
if (p.isCancel(heading)) return {
|
|
1422
|
+
sections: [],
|
|
1423
|
+
cancelled: true
|
|
1424
|
+
};
|
|
1425
|
+
const body = await p.text({
|
|
1426
|
+
message: "Instructions for this section",
|
|
1427
|
+
placeholder: "e.g. \"Document breaking changes and migration steps from v2 to v3\""
|
|
1428
|
+
});
|
|
1429
|
+
if (p.isCancel(body)) return {
|
|
1430
|
+
sections: [],
|
|
1431
|
+
cancelled: true
|
|
1432
|
+
};
|
|
1433
|
+
customPrompt = {
|
|
1434
|
+
heading,
|
|
1435
|
+
body
|
|
1436
|
+
};
|
|
1437
|
+
}
|
|
1438
|
+
return {
|
|
1439
|
+
sections,
|
|
1440
|
+
customPrompt,
|
|
1441
|
+
cancelled: false
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
async function selectLlmConfig(presetModel, message) {
|
|
1445
|
+
if (presetModel) return {
|
|
1446
|
+
model: presetModel,
|
|
1447
|
+
sections: DEFAULT_SECTIONS
|
|
1448
|
+
};
|
|
1449
|
+
if (!isInteractive()) {
|
|
1450
|
+
const model = await selectModel(true);
|
|
1451
|
+
if (!model) return null;
|
|
1452
|
+
return {
|
|
1453
|
+
model,
|
|
1454
|
+
sections: DEFAULT_SECTIONS
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
const model = await selectModel(false);
|
|
1458
|
+
if (!model) return null;
|
|
1459
|
+
const modelName = getModelName(model);
|
|
1460
|
+
const { sections, customPrompt, cancelled } = await selectSkillSections(message ? `${message} (${modelName})` : `Generate SKILL.md with ${modelName}`);
|
|
1461
|
+
if (cancelled || sections.length === 0) return null;
|
|
1462
|
+
return {
|
|
1463
|
+
model,
|
|
1464
|
+
sections,
|
|
1465
|
+
customPrompt
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
async function enhanceSkillWithLLM(opts) {
|
|
1469
|
+
const { packageName, version, skillDir, dirName, model, resolved, relatedSkills, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs: shippedDocs, pkgFiles, force, debug, sections, customPrompt, packages, features, eject } = opts;
|
|
1470
|
+
const effectiveFeatures = eject && features ? {
|
|
1471
|
+
...features,
|
|
1472
|
+
search: false
|
|
1473
|
+
} : features;
|
|
1474
|
+
const llmLog = p.taskLog({ title: `Agent exploring ${packageName}` });
|
|
1475
|
+
const docFiles = listReferenceFiles(skillDir);
|
|
1476
|
+
const { optimized, wasOptimized, usage, cost, warnings, debugLogsDir } = await optimizeDocs({
|
|
1477
|
+
packageName,
|
|
1478
|
+
skillDir,
|
|
1479
|
+
model,
|
|
1480
|
+
version,
|
|
1481
|
+
hasGithub: hasIssues || hasDiscussions,
|
|
1482
|
+
hasReleases,
|
|
1483
|
+
hasChangelog,
|
|
1484
|
+
docFiles,
|
|
1485
|
+
docsType,
|
|
1486
|
+
hasShippedDocs: shippedDocs,
|
|
1487
|
+
noCache: force,
|
|
1488
|
+
debug,
|
|
1489
|
+
sections,
|
|
1490
|
+
customPrompt,
|
|
1491
|
+
features: effectiveFeatures,
|
|
1492
|
+
pkgFiles,
|
|
1493
|
+
onProgress: createToolProgress(llmLog)
|
|
1494
|
+
});
|
|
1495
|
+
if (wasOptimized) {
|
|
1496
|
+
const costParts = [];
|
|
1497
|
+
if (usage) {
|
|
1498
|
+
const totalK = Math.round(usage.totalTokens / 1e3);
|
|
1499
|
+
costParts.push(`${totalK}k tokens`);
|
|
1500
|
+
}
|
|
1501
|
+
if (cost) costParts.push(`$${cost.toFixed(2)}`);
|
|
1502
|
+
const costSuffix = costParts.length > 0 ? ` (${costParts.join(", ")})` : "";
|
|
1503
|
+
llmLog.success(`Generated best practices${costSuffix}`);
|
|
1504
|
+
if (debugLogsDir) p.log.info(`Debug logs: ${debugLogsDir}`);
|
|
1505
|
+
if (warnings?.length) for (const w of warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
|
|
1506
|
+
const skillMd = generateSkillMd({
|
|
1507
|
+
name: packageName,
|
|
1508
|
+
version,
|
|
1509
|
+
releasedAt: resolved.releasedAt,
|
|
1510
|
+
dependencies: resolved.dependencies,
|
|
1511
|
+
distTags: resolved.distTags,
|
|
1512
|
+
body: optimized,
|
|
1513
|
+
relatedSkills,
|
|
1514
|
+
hasIssues,
|
|
1515
|
+
hasDiscussions,
|
|
1516
|
+
hasReleases,
|
|
1517
|
+
hasChangelog,
|
|
1518
|
+
docsType,
|
|
1519
|
+
hasShippedDocs: shippedDocs,
|
|
1520
|
+
pkgFiles,
|
|
1521
|
+
generatedBy: getModelLabel(model),
|
|
1522
|
+
dirName,
|
|
1523
|
+
packages,
|
|
1524
|
+
repoUrl: resolved.repoUrl,
|
|
1525
|
+
features,
|
|
1526
|
+
eject
|
|
1527
|
+
});
|
|
1528
|
+
writeFileSync(join(skillDir, "SKILL.md"), skillMd);
|
|
1529
|
+
} else llmLog.error("LLM optimization failed");
|
|
1530
|
+
}
|
|
1278
1531
|
const TELEMETRY_URL = "https://add-skill.vercel.sh/t";
|
|
1279
1532
|
const SKILLS_VERSION = "1.3.9";
|
|
1280
1533
|
function isEnabled() {
|
|
@@ -1300,6 +1553,10 @@ async function syncGitSkills(opts) {
|
|
|
1300
1553
|
spin.start(`Fetching skills from ${label}`);
|
|
1301
1554
|
const { skills, commitSha } = await fetchGitSkills(source, (msg) => spin.message(msg));
|
|
1302
1555
|
if (skills.length === 0) {
|
|
1556
|
+
if (source.type === "github" && source.owner && source.repo) {
|
|
1557
|
+
spin.stop(`No pre-authored skills in ${label}, generating from repo docs...`);
|
|
1558
|
+
return syncGitHubRepo(opts);
|
|
1559
|
+
}
|
|
1303
1560
|
spin.stop(`No skills found in ${label}`);
|
|
1304
1561
|
return;
|
|
1305
1562
|
}
|
|
@@ -1353,6 +1610,140 @@ async function syncGitSkills(opts) {
|
|
|
1353
1610
|
const names = selected.map((s) => `\x1B[36m${s.name}\x1B[0m`).join(", ");
|
|
1354
1611
|
p.log.success(`Installed ${names}`);
|
|
1355
1612
|
}
|
|
1613
|
+
async function syncGitHubRepo(opts) {
|
|
1614
|
+
const { source, agent, global: isGlobal, yes } = opts;
|
|
1615
|
+
const owner = source.owner;
|
|
1616
|
+
const repo = source.repo;
|
|
1617
|
+
const cwd = process.cwd();
|
|
1618
|
+
const spin = timedSpinner();
|
|
1619
|
+
spin.start(`Resolving ${owner}/${repo}`);
|
|
1620
|
+
const resolved = await resolveGitHubRepo(owner, repo, (msg) => spin.message(msg));
|
|
1621
|
+
if (!resolved) {
|
|
1622
|
+
spin.stop(`Could not find docs for ${owner}/${repo}`);
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
const repoUrl = `https://github.com/${owner}/${repo}`;
|
|
1626
|
+
const packageName = `${owner}-${repo}`;
|
|
1627
|
+
const version = resolved.version || "main";
|
|
1628
|
+
const versionKey = getVersionKey(version);
|
|
1629
|
+
const useCache = isCached(packageName, version);
|
|
1630
|
+
spin.stop(`Resolved ${owner}/${repo}@${useCache ? versionKey : version}${useCache ? " (cached)" : ""}`);
|
|
1631
|
+
ensureCacheDir();
|
|
1632
|
+
const baseDir = resolveBaseDir(cwd, agent, isGlobal);
|
|
1633
|
+
const skillDirName = sanitizeName(`${owner}-${repo}`);
|
|
1634
|
+
const skillDir = join(baseDir, skillDirName);
|
|
1635
|
+
mkdirSync(skillDir, { recursive: true });
|
|
1636
|
+
const features = readConfig().features ?? defaultFeatures;
|
|
1637
|
+
const resSpin = timedSpinner();
|
|
1638
|
+
resSpin.start("Finding resources");
|
|
1639
|
+
const resources = await fetchAndCacheResources({
|
|
1640
|
+
packageName,
|
|
1641
|
+
resolved,
|
|
1642
|
+
version,
|
|
1643
|
+
useCache,
|
|
1644
|
+
features,
|
|
1645
|
+
from: opts.from,
|
|
1646
|
+
onProgress: (msg) => resSpin.message(msg)
|
|
1647
|
+
});
|
|
1648
|
+
const resParts = [];
|
|
1649
|
+
if (resources.docsToIndex.length > 0) {
|
|
1650
|
+
const docCount = resources.docsToIndex.filter((d) => d.metadata?.type === "doc").length;
|
|
1651
|
+
if (docCount > 0) resParts.push(`${docCount} docs`);
|
|
1652
|
+
}
|
|
1653
|
+
if (resources.hasIssues) resParts.push("issues");
|
|
1654
|
+
if (resources.hasDiscussions) resParts.push("discussions");
|
|
1655
|
+
if (resources.hasReleases) resParts.push("releases");
|
|
1656
|
+
resSpin.stop(`Fetched ${resParts.length > 0 ? resParts.join(", ") : "resources"}`);
|
|
1657
|
+
for (const w of resources.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
|
|
1658
|
+
linkAllReferences(skillDir, packageName, cwd, version, resources.docsType, void 0, features);
|
|
1659
|
+
if (features.search) {
|
|
1660
|
+
const idxSpin = timedSpinner();
|
|
1661
|
+
idxSpin.start("Creating search index");
|
|
1662
|
+
await indexResources({
|
|
1663
|
+
packageName,
|
|
1664
|
+
version,
|
|
1665
|
+
cwd,
|
|
1666
|
+
docsToIndex: resources.docsToIndex,
|
|
1667
|
+
features,
|
|
1668
|
+
onProgress: (msg) => idxSpin.message(msg)
|
|
1669
|
+
});
|
|
1670
|
+
idxSpin.stop("Search index ready");
|
|
1671
|
+
}
|
|
1672
|
+
const hasChangelog = detectChangelog(resolvePkgDir(packageName, cwd, version), getCacheDir(packageName, version));
|
|
1673
|
+
const shippedDocs = hasShippedDocs(packageName, cwd, version);
|
|
1674
|
+
const pkgFiles = getPkgKeyFiles(packageName, cwd, version);
|
|
1675
|
+
writeLock(baseDir, skillDirName, {
|
|
1676
|
+
packageName,
|
|
1677
|
+
version,
|
|
1678
|
+
repo: `${owner}/${repo}`,
|
|
1679
|
+
source: resources.docSource,
|
|
1680
|
+
syncedAt: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
|
|
1681
|
+
generator: "skilld"
|
|
1682
|
+
});
|
|
1683
|
+
const baseSkillMd = generateSkillMd({
|
|
1684
|
+
name: packageName,
|
|
1685
|
+
version,
|
|
1686
|
+
releasedAt: resolved.releasedAt,
|
|
1687
|
+
description: resolved.description,
|
|
1688
|
+
relatedSkills: [],
|
|
1689
|
+
hasIssues: resources.hasIssues,
|
|
1690
|
+
hasDiscussions: resources.hasDiscussions,
|
|
1691
|
+
hasReleases: resources.hasReleases,
|
|
1692
|
+
hasChangelog,
|
|
1693
|
+
docsType: resources.docsType,
|
|
1694
|
+
hasShippedDocs: shippedDocs,
|
|
1695
|
+
pkgFiles,
|
|
1696
|
+
dirName: skillDirName,
|
|
1697
|
+
repoUrl,
|
|
1698
|
+
features
|
|
1699
|
+
});
|
|
1700
|
+
writeFileSync(join(skillDir, "SKILL.md"), baseSkillMd);
|
|
1701
|
+
p.log.success(`Created base skill: ${relative(cwd, skillDir)}`);
|
|
1702
|
+
if (!readConfig().skipLlm && (!yes || opts.model)) {
|
|
1703
|
+
const llmConfig = await selectLlmConfig(opts.model);
|
|
1704
|
+
if (llmConfig) {
|
|
1705
|
+
p.log.step(getModelLabel(llmConfig.model));
|
|
1706
|
+
await enhanceSkillWithLLM({
|
|
1707
|
+
packageName,
|
|
1708
|
+
version,
|
|
1709
|
+
skillDir,
|
|
1710
|
+
dirName: skillDirName,
|
|
1711
|
+
model: llmConfig.model,
|
|
1712
|
+
resolved,
|
|
1713
|
+
relatedSkills: [],
|
|
1714
|
+
hasIssues: resources.hasIssues,
|
|
1715
|
+
hasDiscussions: resources.hasDiscussions,
|
|
1716
|
+
hasReleases: resources.hasReleases,
|
|
1717
|
+
hasChangelog,
|
|
1718
|
+
docsType: resources.docsType,
|
|
1719
|
+
hasShippedDocs: shippedDocs,
|
|
1720
|
+
pkgFiles,
|
|
1721
|
+
force: opts.force,
|
|
1722
|
+
debug: opts.debug,
|
|
1723
|
+
sections: llmConfig.sections,
|
|
1724
|
+
customPrompt: llmConfig.customPrompt,
|
|
1725
|
+
features
|
|
1726
|
+
});
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
const shared = !isGlobal && getSharedSkillsDir(cwd);
|
|
1730
|
+
if (shared) linkSkillToAgents(skillDirName, shared, cwd);
|
|
1731
|
+
if (!isGlobal) {
|
|
1732
|
+
registerProject(cwd);
|
|
1733
|
+
await ensureGitignore(shared || targets[agent].skillsDir, cwd, isGlobal);
|
|
1734
|
+
await ensureAgentInstructions(agent, cwd, isGlobal);
|
|
1735
|
+
}
|
|
1736
|
+
await shutdownWorker();
|
|
1737
|
+
track({
|
|
1738
|
+
event: "install",
|
|
1739
|
+
source: `${owner}/${repo}`,
|
|
1740
|
+
skills: skillDirName,
|
|
1741
|
+
agents: agent,
|
|
1742
|
+
...isGlobal && { global: "1" },
|
|
1743
|
+
sourceType: "github-generated"
|
|
1744
|
+
});
|
|
1745
|
+
p.outro(`Synced ${owner}/${repo} to ${relative(cwd, skillDir)}`);
|
|
1746
|
+
}
|
|
1356
1747
|
const STATUS_ICONS = {
|
|
1357
1748
|
pending: "○",
|
|
1358
1749
|
resolving: "◐",
|
|
@@ -1466,9 +1857,10 @@ async function syncPackagesParallel(config) {
|
|
|
1466
1857
|
await shutdownWorker();
|
|
1467
1858
|
p.outro(`${pastVerb} ${successfulPkgs.length}/${packages.length} packages`);
|
|
1468
1859
|
}
|
|
1469
|
-
async function syncBaseSkill(
|
|
1860
|
+
async function syncBaseSkill(packageSpec, config, cwd, update) {
|
|
1861
|
+
const { name: packageName, tag: requestedTag } = parsePackageSpec(packageSpec);
|
|
1470
1862
|
const localVersion = (await readLocalDependencies(cwd).catch(() => [])).find((d) => d.name === packageName)?.version;
|
|
1471
|
-
const { package: resolvedPkg, attempts } = await resolvePackageDocsWithAttempts(packageName, {
|
|
1863
|
+
const { package: resolvedPkg, attempts } = await resolvePackageDocsWithAttempts(requestedTag ? packageSpec : packageName, {
|
|
1472
1864
|
version: localVersion,
|
|
1473
1865
|
cwd,
|
|
1474
1866
|
onProgress: (step) => update(packageName, "resolving", RESOLVE_STEP_LABELS[step])
|
|
@@ -1612,6 +2004,7 @@ async function enhanceWithLLM(packageName, data, config, cwd, update, sections,
|
|
|
1612
2004
|
sections,
|
|
1613
2005
|
customPrompt,
|
|
1614
2006
|
features: data.features,
|
|
2007
|
+
pkgFiles: data.pkgFiles,
|
|
1615
2008
|
onProgress: (progress) => {
|
|
1616
2009
|
const status = progress.type === "reasoning" ? "exploring" : "generating";
|
|
1617
2010
|
const sectionPrefix = progress.section ? `[${progress.section}] ` : "";
|
|
@@ -1740,17 +2133,8 @@ async function runWizard() {
|
|
|
1740
2133
|
p.outro("Thanks, you're all set! Change config anytime with `skilld config`.");
|
|
1741
2134
|
}
|
|
1742
2135
|
var sync_exports = /* @__PURE__ */ __exportAll({
|
|
1743
|
-
DEFAULT_SECTIONS: () => DEFAULT_SECTIONS,
|
|
1744
|
-
SKILLD_MARKER_END: () => SKILLD_MARKER_END,
|
|
1745
|
-
SKILLD_MARKER_START: () => SKILLD_MARKER_START,
|
|
1746
2136
|
addCommandDef: () => addCommandDef,
|
|
1747
2137
|
ejectCommandDef: () => ejectCommandDef,
|
|
1748
|
-
enhanceSkillWithLLM: () => enhanceSkillWithLLM,
|
|
1749
|
-
ensureAgentInstructions: () => ensureAgentInstructions,
|
|
1750
|
-
ensureGitignore: () => ensureGitignore,
|
|
1751
|
-
selectLlmConfig: () => selectLlmConfig,
|
|
1752
|
-
selectModel: () => selectModel,
|
|
1753
|
-
selectSkillSections: () => selectSkillSections,
|
|
1754
2138
|
syncCommand: () => syncCommand,
|
|
1755
2139
|
updateCommandDef: () => updateCommandDef
|
|
1756
2140
|
});
|
|
@@ -1764,59 +2148,6 @@ function showResolveAttempts(attempts) {
|
|
|
1764
2148
|
p.log.message(` ${icon} ${source}${msg}`);
|
|
1765
2149
|
}
|
|
1766
2150
|
}
|
|
1767
|
-
async function ensureGitignore(skillsDir, cwd, isGlobal) {
|
|
1768
|
-
if (isGlobal) return;
|
|
1769
|
-
const gitignorePath = join(cwd, ".gitignore");
|
|
1770
|
-
const pattern = ".skilld";
|
|
1771
|
-
if (existsSync(gitignorePath)) {
|
|
1772
|
-
if (readFileSync(gitignorePath, "utf-8").split("\n").some((line) => line.trim() === pattern)) return;
|
|
1773
|
-
}
|
|
1774
|
-
if (!isInteractive()) {
|
|
1775
|
-
const entry = `\n# Skilld references (recreated by \`skilld install\`)\n${pattern}\n`;
|
|
1776
|
-
if (existsSync(gitignorePath)) appendFileSync(gitignorePath, `${readFileSync(gitignorePath, "utf-8").endsWith("\n") ? "" : "\n"}${entry}`);
|
|
1777
|
-
else writeFileSync(gitignorePath, entry);
|
|
1778
|
-
return;
|
|
1779
|
-
}
|
|
1780
|
-
p.log.info(`\x1B[1mGit guidance:\x1B[0m\n \x1B[32m✓\x1B[0m Commit: \x1B[36m${skillsDir}/*/SKILL.md\x1B[0m\n \x1B[32m✓\x1B[0m Commit: \x1B[36m${skillsDir}/skilld-lock.yaml\x1B[0m\n \x1B[31m✗\x1B[0m Ignore: \x1B[36m${pattern}\x1B[0m \x1B[90m(recreated by \`skilld install\`)\x1B[0m`);
|
|
1781
|
-
const add = await p.confirm({
|
|
1782
|
-
message: `Add \`${pattern}\` to .gitignore?`,
|
|
1783
|
-
initialValue: true
|
|
1784
|
-
});
|
|
1785
|
-
if (p.isCancel(add) || !add) return;
|
|
1786
|
-
const entry = `\n# Skilld references (recreated by \`skilld install\`)\n${pattern}\n`;
|
|
1787
|
-
if (existsSync(gitignorePath)) appendFileSync(gitignorePath, `${readFileSync(gitignorePath, "utf-8").endsWith("\n") ? "" : "\n"}${entry}`);
|
|
1788
|
-
else writeFileSync(gitignorePath, entry);
|
|
1789
|
-
p.log.success("Updated .gitignore");
|
|
1790
|
-
}
|
|
1791
|
-
const SKILLD_MARKER_START = "<!-- skilld -->";
|
|
1792
|
-
const SKILLD_MARKER_END = "<!-- /skilld -->";
|
|
1793
|
-
const SKILLD_INSTRUCTIONS = `${SKILLD_MARKER_START}
|
|
1794
|
-
Before modifying code, evaluate each installed skill against the current task.
|
|
1795
|
-
For each skill, determine YES/NO relevance and invoke all YES skills before proceeding.
|
|
1796
|
-
${SKILLD_MARKER_END}`;
|
|
1797
|
-
async function ensureAgentInstructions(agent, cwd, isGlobal) {
|
|
1798
|
-
if (isGlobal) return;
|
|
1799
|
-
const agentConfig = targets[agent];
|
|
1800
|
-
if (!agentConfig.instructionFile) return;
|
|
1801
|
-
const filePath = join(cwd, agentConfig.instructionFile);
|
|
1802
|
-
if (existsSync(filePath)) {
|
|
1803
|
-
if (readFileSync(filePath, "utf-8").includes(SKILLD_MARKER_START)) return;
|
|
1804
|
-
}
|
|
1805
|
-
if (!isInteractive()) {
|
|
1806
|
-
if (existsSync(filePath)) appendFileSync(filePath, `${readFileSync(filePath, "utf-8").endsWith("\n") ? "" : "\n"}\n${SKILLD_INSTRUCTIONS}\n`);
|
|
1807
|
-
else writeFileSync(filePath, `${SKILLD_INSTRUCTIONS}\n`);
|
|
1808
|
-
return;
|
|
1809
|
-
}
|
|
1810
|
-
p.note(SKILLD_INSTRUCTIONS, `Will be added to ${agentConfig.instructionFile}`);
|
|
1811
|
-
const add = await p.confirm({
|
|
1812
|
-
message: `Add skill activation instructions to ${agentConfig.instructionFile}?`,
|
|
1813
|
-
initialValue: true
|
|
1814
|
-
});
|
|
1815
|
-
if (p.isCancel(add) || !add) return;
|
|
1816
|
-
if (existsSync(filePath)) appendFileSync(filePath, `${readFileSync(filePath, "utf-8").endsWith("\n") ? "" : "\n"}\n${SKILLD_INSTRUCTIONS}\n`);
|
|
1817
|
-
else writeFileSync(filePath, `${SKILLD_INSTRUCTIONS}\n`);
|
|
1818
|
-
p.log.success(`Updated ${agentConfig.instructionFile}`);
|
|
1819
|
-
}
|
|
1820
2151
|
async function syncCommand(state, opts) {
|
|
1821
2152
|
if (opts.packages && opts.packages.length > 0) {
|
|
1822
2153
|
if (opts.packages.length > 1) return syncPackagesParallel({
|
|
@@ -1905,148 +2236,13 @@ async function pickFromList(packages, state) {
|
|
|
1905
2236
|
}
|
|
1906
2237
|
return selected;
|
|
1907
2238
|
}
|
|
1908
|
-
async function
|
|
1909
|
-
const
|
|
1910
|
-
const available = await getAvailableModels();
|
|
1911
|
-
if (available.length === 0) {
|
|
1912
|
-
p.log.warn("No LLM CLIs found (claude, gemini, codex)");
|
|
1913
|
-
return null;
|
|
1914
|
-
}
|
|
1915
|
-
if (config.model && available.some((m) => m.id === config.model)) return config.model;
|
|
1916
|
-
if (skipPrompt) return available.find((m) => m.recommended)?.id ?? available[0].id;
|
|
1917
|
-
const modelChoice = await p.select({
|
|
1918
|
-
message: "Model for SKILL.md generation",
|
|
1919
|
-
options: available.map((m) => ({
|
|
1920
|
-
label: m.recommended ? `${m.name} (Recommended)` : m.name,
|
|
1921
|
-
value: m.id,
|
|
1922
|
-
hint: `${m.agentName} · ${m.hint}`
|
|
1923
|
-
})),
|
|
1924
|
-
initialValue: available.find((m) => m.recommended)?.id ?? available[0].id
|
|
1925
|
-
});
|
|
1926
|
-
if (p.isCancel(modelChoice)) {
|
|
1927
|
-
p.cancel("Cancelled");
|
|
1928
|
-
return null;
|
|
1929
|
-
}
|
|
1930
|
-
updateConfig({ model: modelChoice });
|
|
1931
|
-
return modelChoice;
|
|
1932
|
-
}
|
|
1933
|
-
const DEFAULT_SECTIONS = ["best-practices", "api-changes"];
|
|
1934
|
-
async function selectSkillSections(message = "Generate SKILL.md with LLM") {
|
|
1935
|
-
p.log.info("More sections = less budget each. Fewer sections = deeper coverage.");
|
|
1936
|
-
const selected = await p.multiselect({
|
|
1937
|
-
message,
|
|
1938
|
-
options: [
|
|
1939
|
-
{
|
|
1940
|
-
label: "API changes",
|
|
1941
|
-
value: "api-changes",
|
|
1942
|
-
hint: "new/deprecated APIs from version history"
|
|
1943
|
-
},
|
|
1944
|
-
{
|
|
1945
|
-
label: "Best practices",
|
|
1946
|
-
value: "best-practices",
|
|
1947
|
-
hint: "gotchas, pitfalls, patterns"
|
|
1948
|
-
},
|
|
1949
|
-
{
|
|
1950
|
-
label: "Doc map",
|
|
1951
|
-
value: "api",
|
|
1952
|
-
hint: "compact index of exports linked to source files"
|
|
1953
|
-
},
|
|
1954
|
-
{
|
|
1955
|
-
label: "Custom section",
|
|
1956
|
-
value: "custom",
|
|
1957
|
-
hint: "add your own section"
|
|
1958
|
-
}
|
|
1959
|
-
],
|
|
1960
|
-
initialValues: DEFAULT_SECTIONS,
|
|
1961
|
-
required: false
|
|
1962
|
-
});
|
|
1963
|
-
if (p.isCancel(selected)) return {
|
|
1964
|
-
sections: [],
|
|
1965
|
-
cancelled: true
|
|
1966
|
-
};
|
|
1967
|
-
const sections = selected;
|
|
1968
|
-
if (sections.length === 0) return {
|
|
1969
|
-
sections: [],
|
|
1970
|
-
cancelled: false
|
|
1971
|
-
};
|
|
1972
|
-
if (sections.length > 1) {
|
|
1973
|
-
const n = sections.length;
|
|
1974
|
-
const budgetLines = [];
|
|
1975
|
-
for (const s of sections) switch (s) {
|
|
1976
|
-
case "api-changes":
|
|
1977
|
-
budgetLines.push(` API changes ≤${maxLines(50, 80, n)} lines, ${maxItems(6, 12, n)} items`);
|
|
1978
|
-
break;
|
|
1979
|
-
case "best-practices":
|
|
1980
|
-
budgetLines.push(` Best practices ≤${maxLines(80, 150, n)} lines, ${maxItems(4, 10, n)} items`);
|
|
1981
|
-
break;
|
|
1982
|
-
case "api":
|
|
1983
|
-
budgetLines.push(` Doc map ≤${maxLines(15, 25, n)} lines`);
|
|
1984
|
-
break;
|
|
1985
|
-
case "custom":
|
|
1986
|
-
budgetLines.push(` Custom ≤${maxLines(50, 80, n)} lines`);
|
|
1987
|
-
break;
|
|
1988
|
-
}
|
|
1989
|
-
p.log.info(`Budget (${n} sections):\n${budgetLines.join("\n")}`);
|
|
1990
|
-
}
|
|
1991
|
-
let customPrompt;
|
|
1992
|
-
if (sections.includes("custom")) {
|
|
1993
|
-
const heading = await p.text({
|
|
1994
|
-
message: "Section heading",
|
|
1995
|
-
placeholder: "e.g. \"Migration from v2\" or \"SSR Patterns\""
|
|
1996
|
-
});
|
|
1997
|
-
if (p.isCancel(heading)) return {
|
|
1998
|
-
sections: [],
|
|
1999
|
-
cancelled: true
|
|
2000
|
-
};
|
|
2001
|
-
const body = await p.text({
|
|
2002
|
-
message: "Instructions for this section",
|
|
2003
|
-
placeholder: "e.g. \"Document breaking changes and migration steps from v2 to v3\""
|
|
2004
|
-
});
|
|
2005
|
-
if (p.isCancel(body)) return {
|
|
2006
|
-
sections: [],
|
|
2007
|
-
cancelled: true
|
|
2008
|
-
};
|
|
2009
|
-
customPrompt = {
|
|
2010
|
-
heading,
|
|
2011
|
-
body
|
|
2012
|
-
};
|
|
2013
|
-
}
|
|
2014
|
-
return {
|
|
2015
|
-
sections,
|
|
2016
|
-
customPrompt,
|
|
2017
|
-
cancelled: false
|
|
2018
|
-
};
|
|
2019
|
-
}
|
|
2020
|
-
async function selectLlmConfig(presetModel, message) {
|
|
2021
|
-
if (presetModel) return {
|
|
2022
|
-
model: presetModel,
|
|
2023
|
-
sections: DEFAULT_SECTIONS
|
|
2024
|
-
};
|
|
2025
|
-
if (!isInteractive()) {
|
|
2026
|
-
const model = await selectModel(true);
|
|
2027
|
-
if (!model) return null;
|
|
2028
|
-
return {
|
|
2029
|
-
model,
|
|
2030
|
-
sections: DEFAULT_SECTIONS
|
|
2031
|
-
};
|
|
2032
|
-
}
|
|
2033
|
-
const model = await selectModel(false);
|
|
2034
|
-
if (!model) return null;
|
|
2035
|
-
const modelName = getModelName(model);
|
|
2036
|
-
const { sections, customPrompt, cancelled } = await selectSkillSections(message ? `${message} (${modelName})` : `Generate SKILL.md with ${modelName}`);
|
|
2037
|
-
if (cancelled || sections.length === 0) return null;
|
|
2038
|
-
return {
|
|
2039
|
-
model,
|
|
2040
|
-
sections,
|
|
2041
|
-
customPrompt
|
|
2042
|
-
};
|
|
2043
|
-
}
|
|
2044
|
-
async function syncSinglePackage(packageName, config) {
|
|
2239
|
+
async function syncSinglePackage(packageSpec, config) {
|
|
2240
|
+
const { name: packageName, tag: requestedTag } = parsePackageSpec(packageSpec);
|
|
2045
2241
|
const spin = timedSpinner();
|
|
2046
|
-
spin.start(`Resolving ${
|
|
2242
|
+
spin.start(`Resolving ${packageSpec}`);
|
|
2047
2243
|
const cwd = process.cwd();
|
|
2048
2244
|
const localVersion = (await readLocalDependencies(cwd).catch(() => [])).find((d) => d.name === packageName)?.version;
|
|
2049
|
-
const resolveResult = await resolvePackageDocsWithAttempts(packageName, {
|
|
2245
|
+
const resolveResult = await resolvePackageDocsWithAttempts(requestedTag ? packageSpec : packageName, {
|
|
2050
2246
|
version: localVersion,
|
|
2051
2247
|
cwd,
|
|
2052
2248
|
onProgress: (step) => spin.message(`${packageName}: ${RESOLVE_STEP_LABELS[step]}`)
|
|
@@ -2102,7 +2298,7 @@ async function syncSinglePackage(packageName, config) {
|
|
|
2102
2298
|
ensureCacheDir();
|
|
2103
2299
|
const baseDir = resolveBaseDir(cwd, config.agent, config.global);
|
|
2104
2300
|
const skillDirName = config.name ? sanitizeName(config.name) : computeSkillDirName(packageName, resolved.repoUrl);
|
|
2105
|
-
const skillDir = config.eject ? typeof config.eject === "string" ? resolve(cwd, config.eject) : join(cwd, "skills", skillDirName) : join(baseDir, skillDirName);
|
|
2301
|
+
const skillDir = config.eject ? typeof config.eject === "string" ? join(resolve(cwd, config.eject), skillDirName) : join(cwd, "skills", skillDirName) : join(baseDir, skillDirName);
|
|
2106
2302
|
mkdirSync(skillDir, { recursive: true });
|
|
2107
2303
|
const existingLock = config.eject ? void 0 : readLock(baseDir)?.skills[skillDirName];
|
|
2108
2304
|
if (existingLock && existingLock.packageName !== packageName) {
|
|
@@ -2267,68 +2463,6 @@ async function syncSinglePackage(packageName, config) {
|
|
|
2267
2463
|
const ejectMsg = isEject ? " (ejected)" : "";
|
|
2268
2464
|
p.outro(config.mode === "update" ? `Updated ${packageName}${ejectMsg}` : `Synced ${packageName} to ${relative(cwd, skillDir)}${ejectMsg}`);
|
|
2269
2465
|
}
|
|
2270
|
-
async function enhanceSkillWithLLM(opts) {
|
|
2271
|
-
const { packageName, version, skillDir, dirName, model, resolved, relatedSkills, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs: shippedDocs, pkgFiles, force, debug, sections, customPrompt, packages, features, eject } = opts;
|
|
2272
|
-
const effectiveFeatures = eject && features ? {
|
|
2273
|
-
...features,
|
|
2274
|
-
search: false
|
|
2275
|
-
} : features;
|
|
2276
|
-
const llmLog = p.taskLog({ title: `Agent exploring ${packageName}` });
|
|
2277
|
-
const docFiles = listReferenceFiles(skillDir);
|
|
2278
|
-
const { optimized, wasOptimized, usage, cost, warnings, debugLogsDir } = await optimizeDocs({
|
|
2279
|
-
packageName,
|
|
2280
|
-
skillDir,
|
|
2281
|
-
model,
|
|
2282
|
-
version,
|
|
2283
|
-
hasGithub: hasIssues || hasDiscussions,
|
|
2284
|
-
hasReleases,
|
|
2285
|
-
hasChangelog,
|
|
2286
|
-
docFiles,
|
|
2287
|
-
docsType,
|
|
2288
|
-
hasShippedDocs: shippedDocs,
|
|
2289
|
-
noCache: force,
|
|
2290
|
-
debug,
|
|
2291
|
-
sections,
|
|
2292
|
-
customPrompt,
|
|
2293
|
-
features: effectiveFeatures,
|
|
2294
|
-
onProgress: createToolProgress(llmLog)
|
|
2295
|
-
});
|
|
2296
|
-
if (wasOptimized) {
|
|
2297
|
-
const costParts = [];
|
|
2298
|
-
if (usage) {
|
|
2299
|
-
const totalK = Math.round(usage.totalTokens / 1e3);
|
|
2300
|
-
costParts.push(`${totalK}k tokens`);
|
|
2301
|
-
}
|
|
2302
|
-
if (cost) costParts.push(`$${cost.toFixed(2)}`);
|
|
2303
|
-
const costSuffix = costParts.length > 0 ? ` (${costParts.join(", ")})` : "";
|
|
2304
|
-
llmLog.success(`Generated best practices${costSuffix}`);
|
|
2305
|
-
if (debugLogsDir) p.log.info(`Debug logs: ${debugLogsDir}`);
|
|
2306
|
-
if (warnings?.length) for (const w of warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
|
|
2307
|
-
const skillMd = generateSkillMd({
|
|
2308
|
-
name: packageName,
|
|
2309
|
-
version,
|
|
2310
|
-
releasedAt: resolved.releasedAt,
|
|
2311
|
-
dependencies: resolved.dependencies,
|
|
2312
|
-
distTags: resolved.distTags,
|
|
2313
|
-
body: optimized,
|
|
2314
|
-
relatedSkills,
|
|
2315
|
-
hasIssues,
|
|
2316
|
-
hasDiscussions,
|
|
2317
|
-
hasReleases,
|
|
2318
|
-
hasChangelog,
|
|
2319
|
-
docsType,
|
|
2320
|
-
hasShippedDocs: shippedDocs,
|
|
2321
|
-
pkgFiles,
|
|
2322
|
-
generatedBy: getModelLabel(model),
|
|
2323
|
-
dirName,
|
|
2324
|
-
packages,
|
|
2325
|
-
repoUrl: resolved.repoUrl,
|
|
2326
|
-
features,
|
|
2327
|
-
eject
|
|
2328
|
-
});
|
|
2329
|
-
writeFileSync(join(skillDir, "SKILL.md"), skillMd);
|
|
2330
|
-
} else llmLog.error("LLM optimization failed");
|
|
2331
|
-
}
|
|
2332
2466
|
const addCommandDef = defineCommand({
|
|
2333
2467
|
meta: {
|
|
2334
2468
|
name: "add",
|
|
@@ -2362,7 +2496,10 @@ const addCommandDef = defineCommand({
|
|
|
2362
2496
|
source,
|
|
2363
2497
|
global: args.global,
|
|
2364
2498
|
agent,
|
|
2365
|
-
yes: args.yes
|
|
2499
|
+
yes: args.yes,
|
|
2500
|
+
model: args.model,
|
|
2501
|
+
force: args.force,
|
|
2502
|
+
debug: args.debug
|
|
2366
2503
|
});
|
|
2367
2504
|
if (npmTokens.length > 0) {
|
|
2368
2505
|
const packages = [...new Set(npmTokens.flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean))];
|
|
@@ -2886,6 +3023,7 @@ async function enhanceRegenerated(pkgName, version, skillDir, model, sections, c
|
|
|
2886
3023
|
sections,
|
|
2887
3024
|
customPrompt,
|
|
2888
3025
|
features,
|
|
3026
|
+
pkgFiles: getPkgKeyFiles(pkgName, process.cwd(), version),
|
|
2889
3027
|
onProgress: createToolProgress(llmLog)
|
|
2890
3028
|
});
|
|
2891
3029
|
if (wasOptimized) {
|