skilld 1.7.4 → 2.0.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/add.mjs +66 -0
- package/dist/_chunks/add.mjs.map +1 -0
- package/dist/_chunks/agent-prompt.mjs +88 -0
- package/dist/_chunks/agent-prompt.mjs.map +1 -0
- package/dist/_chunks/agent.mjs +81 -57
- package/dist/_chunks/agent.mjs.map +1 -1
- package/dist/_chunks/args.mjs +42 -0
- package/dist/_chunks/args.mjs.map +1 -0
- package/dist/_chunks/assemble.mjs +10 -7
- package/dist/_chunks/assemble.mjs.map +1 -1
- package/dist/_chunks/author.mjs +33 -17
- package/dist/_chunks/author.mjs.map +1 -1
- package/dist/_chunks/cache.mjs +143 -183
- package/dist/_chunks/cache.mjs.map +1 -1
- package/dist/_chunks/cache2.mjs +7 -6
- package/dist/_chunks/cache2.mjs.map +1 -1
- package/dist/_chunks/client.mjs +117 -0
- package/dist/_chunks/client.mjs.map +1 -0
- package/dist/_chunks/core.mjs +5 -5
- package/dist/_chunks/detect.mjs +53 -43
- package/dist/_chunks/detect.mjs.map +1 -1
- package/dist/_chunks/eject.mjs +69 -0
- package/dist/_chunks/eject.mjs.map +1 -0
- package/dist/_chunks/embedding-cache2.mjs +1 -1
- package/dist/_chunks/env.mjs +19 -0
- package/dist/_chunks/env.mjs.map +1 -0
- package/dist/_chunks/install-many.mjs +376 -0
- package/dist/_chunks/install-many.mjs.map +1 -0
- package/dist/_chunks/install.mjs +81 -326
- package/dist/_chunks/install.mjs.map +1 -1
- package/dist/_chunks/intro.mjs +63 -0
- package/dist/_chunks/intro.mjs.map +1 -0
- package/dist/_chunks/list.mjs +2 -2
- package/dist/_chunks/list.mjs.map +1 -1
- package/dist/_chunks/lockfile.mjs +3 -2
- package/dist/_chunks/lockfile.mjs.map +1 -1
- package/dist/_chunks/login.mjs +233 -0
- package/dist/_chunks/login.mjs.map +1 -0
- package/dist/_chunks/logout.mjs +27 -0
- package/dist/_chunks/logout.mjs.map +1 -0
- package/dist/_chunks/map.mjs +11 -0
- package/dist/_chunks/map.mjs.map +1 -0
- package/dist/_chunks/markdown.mjs +79 -54
- package/dist/_chunks/markdown.mjs.map +1 -1
- package/dist/_chunks/menu.mjs +33 -0
- package/dist/_chunks/menu.mjs.map +1 -0
- package/dist/_chunks/model-picker.mjs +61 -0
- package/dist/_chunks/model-picker.mjs.map +1 -0
- package/dist/_chunks/monorepo.mjs +4 -2
- package/dist/_chunks/monorepo.mjs.map +1 -1
- package/dist/_chunks/package-json.mjs.map +1 -1
- package/dist/_chunks/paths.mjs +3 -5
- package/dist/_chunks/paths.mjs.map +1 -1
- package/dist/_chunks/{sync-pipeline.mjs → pipeline.mjs} +346 -313
- package/dist/_chunks/pipeline.mjs.map +1 -0
- package/dist/_chunks/pool2.mjs +1 -1
- package/dist/_chunks/portable.mjs +151 -0
- package/dist/_chunks/portable.mjs.map +1 -0
- package/dist/_chunks/prepare-hook.mjs +2 -0
- package/dist/_chunks/prepare-hook2.mjs +61 -0
- package/dist/_chunks/prepare-hook2.mjs.map +1 -0
- package/dist/_chunks/prepare.mjs +47 -3
- package/dist/_chunks/prepare.mjs.map +1 -1
- package/dist/_chunks/prepare2.mjs +7 -6
- package/dist/_chunks/prepare2.mjs.map +1 -1
- package/dist/_chunks/prompts.mjs +484 -74
- package/dist/_chunks/prompts.mjs.map +1 -1
- package/dist/_chunks/pull.mjs +219 -0
- package/dist/_chunks/pull.mjs.map +1 -0
- package/dist/_chunks/regex.mjs +19 -0
- package/dist/_chunks/regex.mjs.map +1 -0
- package/dist/_chunks/retriv.mjs +2 -171
- package/dist/_chunks/retriv2.mjs +159 -0
- package/dist/_chunks/retriv2.mjs.map +1 -0
- package/dist/_chunks/sanitize.mjs +12 -9
- package/dist/_chunks/sanitize.mjs.map +1 -1
- package/dist/_chunks/search-helpers.mjs +8 -6
- package/dist/_chunks/search-helpers.mjs.map +1 -1
- package/dist/_chunks/search-interactive.mjs +23 -20
- package/dist/_chunks/search-interactive.mjs.map +1 -1
- package/dist/_chunks/search.mjs +3 -3
- package/dist/_chunks/search.mjs.map +1 -1
- package/dist/_chunks/semver.mjs +2755 -1
- package/dist/_chunks/semver.mjs.map +1 -1
- package/dist/_chunks/skill-installer2.mjs +10 -11
- package/dist/_chunks/skill-installer2.mjs.map +1 -1
- package/dist/_chunks/skills.mjs +6 -7
- package/dist/_chunks/skills.mjs.map +1 -1
- package/dist/_chunks/store.mjs +107 -0
- package/dist/_chunks/store.mjs.map +1 -0
- package/dist/_chunks/sync.mjs +411 -910
- package/dist/_chunks/sync.mjs.map +1 -1
- package/dist/_chunks/sync2.mjs +2 -5
- package/dist/_chunks/telemetry.mjs +26 -0
- package/dist/_chunks/telemetry.mjs.map +1 -0
- package/dist/_chunks/uninstall.mjs +12 -9
- package/dist/_chunks/uninstall.mjs.map +1 -1
- package/dist/_chunks/update.mjs +171 -0
- package/dist/_chunks/update.mjs.map +1 -0
- package/dist/_chunks/upload.mjs +3 -3
- package/dist/_chunks/validate.mjs +1 -1
- package/dist/_chunks/version.mjs +16 -17
- package/dist/_chunks/version.mjs.map +1 -1
- package/dist/_chunks/whoami.mjs +21 -0
- package/dist/_chunks/whoami.mjs.map +1 -0
- package/dist/_chunks/wizard.mjs +2 -190
- package/dist/_chunks/wizard2.mjs +200 -0
- package/dist/_chunks/wizard2.mjs.map +1 -0
- package/dist/cli.mjs +72 -53
- package/dist/cli.mjs.map +1 -1
- package/dist/prepare.mjs +4 -3
- package/dist/prepare.mjs.map +1 -1
- package/dist/retriv/worker.d.mts +5 -1
- package/dist/retriv/worker.d.mts.map +1 -1
- package/dist/retriv/worker.mjs +1 -1
- package/package.json +19 -28
- package/dist/_chunks/author-group.mjs +0 -17
- package/dist/_chunks/author-group.mjs.map +0 -1
- package/dist/_chunks/cli-helpers.mjs +0 -335
- package/dist/_chunks/cli-helpers.mjs.map +0 -1
- package/dist/_chunks/cli-helpers2.mjs +0 -2
- package/dist/_chunks/index.d.mts +0 -344
- package/dist/_chunks/index.d.mts.map +0 -1
- package/dist/_chunks/index2.d.mts +0 -279
- package/dist/_chunks/index2.d.mts.map +0 -1
- package/dist/_chunks/index3.d.mts +0 -44
- package/dist/_chunks/index3.d.mts.map +0 -1
- package/dist/_chunks/index4.d.mts +0 -553
- package/dist/_chunks/index4.d.mts.map +0 -1
- package/dist/_chunks/package-registry.mjs +0 -465
- package/dist/_chunks/package-registry.mjs.map +0 -1
- package/dist/_chunks/retriv.mjs.map +0 -1
- package/dist/_chunks/setup.mjs +0 -17
- package/dist/_chunks/setup.mjs.map +0 -1
- package/dist/_chunks/sources.mjs +0 -2654
- package/dist/_chunks/sources.mjs.map +0 -1
- package/dist/_chunks/sync-pipeline.mjs.map +0 -1
- package/dist/_chunks/sync-registry.mjs +0 -65
- package/dist/_chunks/sync-registry.mjs.map +0 -1
- package/dist/_chunks/types.d.mts +0 -76
- package/dist/_chunks/types.d.mts.map +0 -1
- package/dist/_chunks/types2.d.mts +0 -88
- package/dist/_chunks/types2.d.mts.map +0 -1
- package/dist/_chunks/wizard.mjs.map +0 -1
- package/dist/agent/index.d.mts +0 -2
- package/dist/agent/index.mjs +0 -4
- package/dist/cache/index.d.mts +0 -2
- package/dist/cache/index.mjs +0 -5
- package/dist/index.d.mts +0 -6
- package/dist/index.mjs +0 -6
- package/dist/retriv/index.d.mts +0 -3
- package/dist/retriv/index.mjs +0 -2
- package/dist/sources/index.d.mts +0 -3
- package/dist/sources/index.mjs +0 -3
- package/dist/types.d.mts +0 -4
- package/dist/types.mjs +0 -1
package/dist/_chunks/sync.mjs
CHANGED
|
@@ -1,42 +1,22 @@
|
|
|
1
|
-
import { d as getSharedSkillsDir, g as skillRefsSection, t as CACHE_DIR } from "./paths.mjs";
|
|
2
|
-
import { A as getActiveFeatures, M as hasCompletedWizard, P as readConfig, h as listReferenceFiles, i as ensureCacheDir, t as createReferenceCache } from "./cache.mjs";
|
|
3
|
-
import { r as getVersionKey } from "./version.mjs";
|
|
4
|
-
import { n as sanitizeMarkdown } from "./sanitize.mjs";
|
|
5
|
-
import { i as parseFrontmatter } from "./markdown.mjs";
|
|
6
|
-
import { P as resolveGitHubRepo, a as toStoragePackageName, b as fetchGitSkills, dt as parsePackageSpec, i as resolveSkillName, l as fetchPkgDist, lt as parseGitHubRepoSlug, n as isCrateSpec, r as parseSkillInput, t as resolvePackageOrCrate, tt as isPrerelease, v as searchNpmPackages } from "./sources.mjs";
|
|
7
|
-
import { a as targets } from "./detect.mjs";
|
|
8
1
|
import { i as getModelLabel, n as detectImportedPackages } from "./agent.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import { t as
|
|
13
|
-
import {
|
|
14
|
-
import { t as
|
|
15
|
-
import {
|
|
16
|
-
import { a as
|
|
2
|
+
import { a as sanitizeName, c as formatDuration, g as todayIsoDate, h as timedSpinner, i as linkSkillToAgents, r as computeSkillDirName, t as writeGeneratedSkillMd } from "./prompts.mjs";
|
|
3
|
+
import { _ as skillRefsSection, f as getSharedSkillsDir } from "./paths.mjs";
|
|
4
|
+
import { c as getVersionKey } from "./prepare.mjs";
|
|
5
|
+
import { d as readConfig, r as ensureCacheDir, s as getActiveFeatures, t as createReferenceCache } from "./cache.mjs";
|
|
6
|
+
import { r as suggestPrepareHook } from "./prepare-hook2.mjs";
|
|
7
|
+
import { E as resolveGitHubRepo, L as parseGitHubRepoSlug, U as isPrerelease, i as resolvePackageOrCrate, l as toStoragePackageName, m as searchNpmPackages, o as isCrateSpec, p as fetchPkgDist, t as semverDiff, z as parsePackageSpec } from "./semver.mjs";
|
|
8
|
+
import { i as parseFrontmatter } from "./markdown.mjs";
|
|
9
|
+
import { a as parsePackageNames, c as readLock, n as findSkillDirByPackage } from "./lockfile.mjs";
|
|
10
|
+
import { a as ensureProjectFiles, c as linkShippedToAgents, l as resolveBaseDir, o as handleShippedSkills, s as installSkill } from "./skill-installer2.mjs";
|
|
11
|
+
import { a as prepareSkillReferences, c as selectLlmConfig, d as runSkillEnhancement, f as writeBaseSkill, i as findRelatedSkills, l as applyCachedSections, o as DEFAULT_SECTIONS, p as writePromptFiles, r as fetchAndCacheResources, s as resolveAutoModel, t as buildSkillContext } from "./pipeline.mjs";
|
|
17
12
|
import { n as shutdownWorker } from "./pool2.mjs";
|
|
18
|
-
import { existsSync, mkdirSync, readFileSync
|
|
19
|
-
import {
|
|
20
|
-
import pLimit from "p-limit";
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
14
|
+
import { styleText } from "node:util";
|
|
21
15
|
import * as p from "@clack/prompts";
|
|
22
|
-
import
|
|
23
|
-
import {
|
|
16
|
+
import pLimit from "p-limit";
|
|
17
|
+
import { join, relative, resolve } from "pathe";
|
|
24
18
|
import logUpdate from "log-update";
|
|
25
|
-
|
|
26
|
-
const SKILLS_VERSION = "1.3.9";
|
|
27
|
-
function isEnabled() {
|
|
28
|
-
return !process.env.DISABLE_TELEMETRY && !process.env.DO_NOT_TRACK;
|
|
29
|
-
}
|
|
30
|
-
function track(data) {
|
|
31
|
-
if (!isEnabled()) return;
|
|
32
|
-
try {
|
|
33
|
-
const params = new URLSearchParams();
|
|
34
|
-
params.set("v", SKILLS_VERSION);
|
|
35
|
-
if (isCI) params.set("ci", "1");
|
|
36
|
-
for (const [key, value] of Object.entries(data)) if (value !== void 0 && value !== null) params.set(key, String(value));
|
|
37
|
-
fetch(`${TELEMETRY_URL}?${params.toString()}`).catch(() => {});
|
|
38
|
-
} catch {}
|
|
39
|
-
}
|
|
19
|
+
import { createHooks } from "hookable";
|
|
40
20
|
const npmResolver = async (spec, opts) => {
|
|
41
21
|
const resolution = await resolvePackageOrCrate(spec, {
|
|
42
22
|
cwd: opts.cwd,
|
|
@@ -92,20 +72,31 @@ function createGithubResolver(owner, repo) {
|
|
|
92
72
|
};
|
|
93
73
|
}
|
|
94
74
|
const RATE_LIMIT_RE = /\b429\b|rate.?limit|exhausted.*capacity|quota.*reset/i;
|
|
95
|
-
async function runBaseSync(spec, config,
|
|
96
|
-
|
|
75
|
+
async function runBaseSync(spec, config, hooks, resolver, cwd, defaultSections) {
|
|
76
|
+
await hooks.callHook("resolve:start", { spec });
|
|
97
77
|
const resolverResult = await resolver(spec, {
|
|
98
78
|
cwd,
|
|
99
79
|
agent: config.agent,
|
|
100
80
|
global: config.global,
|
|
101
|
-
onProgress: (msg) =>
|
|
81
|
+
onProgress: (msg) => hooks.callHook("resolve:progress", {
|
|
82
|
+
spec,
|
|
83
|
+
message: msg
|
|
84
|
+
})
|
|
102
85
|
});
|
|
103
86
|
if (!("resolved" in resolverResult)) {
|
|
104
87
|
if (resolverResult.shipped && resolverResult.shipped.length > 0) {
|
|
105
|
-
for (const s of resolverResult.shipped)
|
|
88
|
+
for (const s of resolverResult.shipped) await hooks.callHook("shipped:installed", {
|
|
89
|
+
spec,
|
|
90
|
+
skillName: s.skillName,
|
|
91
|
+
skillDir: s.skillDir
|
|
92
|
+
});
|
|
106
93
|
return { kind: "shipped" };
|
|
107
94
|
}
|
|
108
|
-
|
|
95
|
+
await hooks.callHook("resolve:failed", {
|
|
96
|
+
spec,
|
|
97
|
+
identityName: resolverResult.identityName,
|
|
98
|
+
attempts: resolverResult.attempts
|
|
99
|
+
});
|
|
109
100
|
return {
|
|
110
101
|
kind: "unresolved",
|
|
111
102
|
unresolved: resolverResult
|
|
@@ -116,24 +107,33 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
116
107
|
if (config.force) cache.clearForce();
|
|
117
108
|
const useCache = cache.has();
|
|
118
109
|
if (kind !== "crate" && !existsSync(join(cwd, "node_modules", identityName))) {
|
|
119
|
-
|
|
110
|
+
await hooks.callHook("dist:downloading", { spec });
|
|
120
111
|
await fetchPkgDist(identityName, version);
|
|
121
112
|
}
|
|
122
113
|
if (kind !== "crate") {
|
|
123
114
|
const shipped = handleShippedSkills(identityName, version, cwd, config.agent, config.global);
|
|
124
115
|
if (shipped) {
|
|
125
116
|
linkShippedToAgents(shipped.shipped, cwd, config.agent, config.global);
|
|
126
|
-
for (const s of shipped.shipped)
|
|
117
|
+
for (const s of shipped.shipped) await hooks.callHook("shipped:installed", {
|
|
118
|
+
spec,
|
|
119
|
+
skillName: s.skillName,
|
|
120
|
+
skillDir: s.skillDir
|
|
121
|
+
});
|
|
127
122
|
return { kind: "shipped" };
|
|
128
123
|
}
|
|
129
124
|
}
|
|
130
|
-
|
|
125
|
+
await hooks.callHook("resolve:done", {
|
|
126
|
+
spec,
|
|
127
|
+
version,
|
|
131
128
|
cached: useCache,
|
|
132
129
|
force: config.force
|
|
133
130
|
});
|
|
134
131
|
if (kind === "npm" && !localVersion && !requestedTag && !isPrerelease(version)) {
|
|
135
132
|
const nextTag = resolved.distTags?.next ?? resolved.distTags?.beta ?? resolved.distTags?.alpha;
|
|
136
|
-
if (nextTag && (!resolved.releasedAt || !nextTag.releasedAt || nextTag.releasedAt > resolved.releasedAt))
|
|
133
|
+
if (nextTag && (!resolved.releasedAt || !nextTag.releasedAt || nextTag.releasedAt > resolved.releasedAt)) await hooks.callHook("warn", {
|
|
134
|
+
spec,
|
|
135
|
+
message: `No local dependency found — using latest stable (${version}). Prerelease ${nextTag.version} available: skilld add ${identityName}@beta`
|
|
136
|
+
});
|
|
137
137
|
}
|
|
138
138
|
cache.ensure();
|
|
139
139
|
const isEject = !!config.eject;
|
|
@@ -171,7 +171,7 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
171
171
|
})()
|
|
172
172
|
} : void 0;
|
|
173
173
|
const features = getActiveFeatures(config.noSearch ? { search: false } : void 0);
|
|
174
|
-
|
|
174
|
+
await hooks.callHook("fetch:start", { spec });
|
|
175
175
|
const resources = await fetchAndCacheResources({
|
|
176
176
|
packageName: storageName,
|
|
177
177
|
resolved,
|
|
@@ -179,7 +179,10 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
179
179
|
useCache,
|
|
180
180
|
features,
|
|
181
181
|
from: config.from,
|
|
182
|
-
onProgress: (msg) =>
|
|
182
|
+
onProgress: (msg) => hooks.callHook("fetch:progress", {
|
|
183
|
+
spec,
|
|
184
|
+
message: msg
|
|
185
|
+
})
|
|
183
186
|
});
|
|
184
187
|
const parts = [];
|
|
185
188
|
if (resources.docsToIndex.length > 0) {
|
|
@@ -189,9 +192,16 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
189
192
|
if (resources.hasIssues) parts.push("issues");
|
|
190
193
|
if (resources.hasDiscussions) parts.push("discussions");
|
|
191
194
|
if (resources.hasReleases) parts.push("releases");
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
await hooks.callHook("fetch:done", {
|
|
196
|
+
spec,
|
|
197
|
+
parts,
|
|
198
|
+
cached: resources.usedCache
|
|
199
|
+
});
|
|
200
|
+
for (const w of resources.warnings) await hooks.callHook("warn", {
|
|
201
|
+
spec,
|
|
202
|
+
message: w
|
|
203
|
+
});
|
|
204
|
+
if (features.search) await hooks.callHook("index:start", { spec });
|
|
195
205
|
const prepared = await prepareSkillReferences({
|
|
196
206
|
packageName: storageName,
|
|
197
207
|
version,
|
|
@@ -200,9 +210,12 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
200
210
|
resources,
|
|
201
211
|
features,
|
|
202
212
|
baseDir,
|
|
203
|
-
onIndexProgress: (msg) =>
|
|
213
|
+
onIndexProgress: (msg) => hooks.callHook("index:progress", {
|
|
214
|
+
spec,
|
|
215
|
+
message: msg
|
|
216
|
+
})
|
|
204
217
|
});
|
|
205
|
-
if (features.search)
|
|
218
|
+
if (features.search) await hooks.callHook("index:done", { spec });
|
|
206
219
|
if (!isEject) {
|
|
207
220
|
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl);
|
|
208
221
|
cache.linkPkgNamed(skillDir, cwd);
|
|
@@ -239,9 +252,13 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
239
252
|
features
|
|
240
253
|
});
|
|
241
254
|
ctx.overheadLines = writeBaseSkill(ctx, { eject: isEject }).split("\n").length;
|
|
242
|
-
|
|
255
|
+
await hooks.callHook("base:done", {
|
|
256
|
+
spec,
|
|
257
|
+
skillDir: relative(cwd, skillDir),
|
|
258
|
+
mode: config.mode === "update" ? "update" : "add"
|
|
259
|
+
});
|
|
243
260
|
const allSectionsCached = !config.force && applyCachedSections(ctx, defaultSections, { eject: isEject });
|
|
244
|
-
if (allSectionsCached)
|
|
261
|
+
if (allSectionsCached) await hooks.callHook("sections:cached", { spec });
|
|
245
262
|
return {
|
|
246
263
|
kind: "ready",
|
|
247
264
|
state: {
|
|
@@ -259,8 +276,9 @@ async function runBaseSync(spec, config, ui, resolver, cwd, defaultSections) {
|
|
|
259
276
|
}
|
|
260
277
|
};
|
|
261
278
|
}
|
|
262
|
-
async function runEnhancePhase(state, llmConfig, config,
|
|
279
|
+
async function runEnhancePhase(state, llmConfig, config, hooks, cwd) {
|
|
263
280
|
const isEject = !!config.eject;
|
|
281
|
+
const spec = state.identityName;
|
|
264
282
|
if (llmConfig?.promptOnly) writePromptFiles({
|
|
265
283
|
...state.ctx,
|
|
266
284
|
packageName: state.ctx.cachePackageName ?? state.ctx.packageName,
|
|
@@ -269,10 +287,10 @@ async function runEnhancePhase(state, llmConfig, config, ui, cwd) {
|
|
|
269
287
|
sections: llmConfig.sections,
|
|
270
288
|
customPrompt: llmConfig.customPrompt
|
|
271
289
|
});
|
|
272
|
-
else if (llmConfig) await
|
|
290
|
+
else if (llmConfig) await enhanceWithHooks(state.ctx, llmConfig, {
|
|
273
291
|
...config,
|
|
274
292
|
eject: isEject
|
|
275
|
-
},
|
|
293
|
+
}, hooks, spec);
|
|
276
294
|
if (isEject) {
|
|
277
295
|
const cache = createReferenceCache(state.storageName, state.version);
|
|
278
296
|
if (!config.debug) cache.clearSkillInternal(state.skillDir);
|
|
@@ -291,8 +309,11 @@ async function runEnhancePhase(state, llmConfig, config, ui, cwd) {
|
|
|
291
309
|
shared
|
|
292
310
|
});
|
|
293
311
|
}
|
|
294
|
-
async function
|
|
295
|
-
|
|
312
|
+
async function enhanceWithHooks(ctx, llmConfig, config, hooks, spec) {
|
|
313
|
+
await hooks.callHook("enhance:start", {
|
|
314
|
+
spec,
|
|
315
|
+
modelLabel: getModelLabel(llmConfig.model)
|
|
316
|
+
});
|
|
296
317
|
const result = await runSkillEnhancement(ctx, {
|
|
297
318
|
model: llmConfig.model,
|
|
298
319
|
force: config.force,
|
|
@@ -300,276 +321,199 @@ async function enhanceWithUi(ctx, llmConfig, config, ui) {
|
|
|
300
321
|
sections: llmConfig.sections,
|
|
301
322
|
customPrompt: llmConfig.customPrompt,
|
|
302
323
|
eject: !!config.eject
|
|
303
|
-
}, (progress) =>
|
|
304
|
-
|
|
324
|
+
}, (progress) => hooks.callHook("enhance:progress", {
|
|
325
|
+
spec,
|
|
326
|
+
progress
|
|
327
|
+
}));
|
|
328
|
+
if (result.wasOptimized) await hooks.callHook("enhance:done", {
|
|
329
|
+
spec,
|
|
305
330
|
usage: result.usage ? { totalTokens: result.usage.totalTokens } : void 0,
|
|
306
331
|
cost: result.cost,
|
|
307
332
|
debugLogsDir: result.debugLogsDir,
|
|
308
333
|
error: result.error,
|
|
309
334
|
warnings: result.warnings
|
|
310
335
|
});
|
|
311
|
-
else
|
|
336
|
+
else await hooks.callHook("enhance:failed", {
|
|
337
|
+
spec,
|
|
338
|
+
error: result.error ?? "",
|
|
339
|
+
rateLimited: !!result.error && RATE_LIMIT_RE.test(result.error)
|
|
340
|
+
});
|
|
312
341
|
}
|
|
313
|
-
function
|
|
342
|
+
function createSyncRun(opts) {
|
|
343
|
+
const hooks = createHooks();
|
|
344
|
+
async function runBase(spec) {
|
|
345
|
+
const result = await runBaseSync(spec, {
|
|
346
|
+
agent: opts.agent,
|
|
347
|
+
global: opts.global,
|
|
348
|
+
mode: opts.mode,
|
|
349
|
+
force: opts.force,
|
|
350
|
+
noSearch: opts.noSearch,
|
|
351
|
+
name: opts.name,
|
|
352
|
+
from: opts.from,
|
|
353
|
+
eject: opts.eject
|
|
354
|
+
}, hooks, opts.resolver, opts.cwd, opts.defaultSections);
|
|
355
|
+
if (result.kind === "shipped") return {
|
|
356
|
+
kind: "shipped",
|
|
357
|
+
spec
|
|
358
|
+
};
|
|
359
|
+
if (result.kind === "unresolved") return {
|
|
360
|
+
kind: "unresolved",
|
|
361
|
+
spec,
|
|
362
|
+
identityName: result.unresolved.identityName,
|
|
363
|
+
attempts: result.unresolved.attempts
|
|
364
|
+
};
|
|
365
|
+
if (result.kind === "merge-needed") {
|
|
366
|
+
if (opts.onMergeNeeded) {
|
|
367
|
+
await opts.onMergeNeeded(result.state);
|
|
368
|
+
return {
|
|
369
|
+
kind: "merged",
|
|
370
|
+
spec
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
return {
|
|
374
|
+
kind: "error",
|
|
375
|
+
spec,
|
|
376
|
+
reason: `Skill dir already holds ${result.state.existingLock.packageName} — run sequentially to merge`
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
kind: "ready",
|
|
381
|
+
spec,
|
|
382
|
+
state: result.state
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
async function runEnhance(state, llmConfig) {
|
|
386
|
+
await runEnhancePhase(state, llmConfig, {
|
|
387
|
+
agent: opts.agent,
|
|
388
|
+
global: opts.global,
|
|
389
|
+
force: opts.force,
|
|
390
|
+
debug: opts.debug,
|
|
391
|
+
eject: opts.eject
|
|
392
|
+
}, hooks, opts.cwd);
|
|
393
|
+
}
|
|
394
|
+
async function run(spec) {
|
|
395
|
+
const base = await runBase(spec);
|
|
396
|
+
if (base.kind !== "ready") return base;
|
|
397
|
+
let llmConfig = null;
|
|
398
|
+
if (!base.state.allSectionsCached && opts.resolveLlmConfig) llmConfig = await opts.resolveLlmConfig({ ready: [{
|
|
399
|
+
spec,
|
|
400
|
+
state: base.state
|
|
401
|
+
}] }) ?? null;
|
|
402
|
+
await runEnhance(base.state, llmConfig);
|
|
403
|
+
return {
|
|
404
|
+
kind: "enhanced",
|
|
405
|
+
spec,
|
|
406
|
+
state: base.state
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
async function runMany(specs, runOpts) {
|
|
410
|
+
const limit = pLimit(runOpts?.concurrency ?? 5);
|
|
411
|
+
return (await Promise.allSettled(specs.map((spec) => limit(() => runBase(spec))))).map((r, i) => r.status === "fulfilled" ? r.value : {
|
|
412
|
+
kind: "error",
|
|
413
|
+
spec: specs[i],
|
|
414
|
+
reason: r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
hooks,
|
|
419
|
+
runBase,
|
|
420
|
+
runEnhance,
|
|
421
|
+
run,
|
|
422
|
+
runMany
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
function bindClackUi(hooks, { cwd }) {
|
|
314
426
|
let spinner = null;
|
|
315
427
|
let resourceSpinner = null;
|
|
316
428
|
let indexSpinner = null;
|
|
317
429
|
let llmLog = null;
|
|
318
430
|
let currentSpec = "";
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
warn(
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
});
|
|
378
|
-
},
|
|
379
|
-
llmProgress(progress) {
|
|
380
|
-
if (!llmLog) return;
|
|
381
|
-
const sectionPrefix = progress.section ? `[${progress.section}] ` : "";
|
|
382
|
-
const line = progress.chunk.startsWith("[") ? `${sectionPrefix}${progress.chunk}` : `${sectionPrefix}${progress.chunk}`;
|
|
383
|
-
llmLog.message(line);
|
|
384
|
-
},
|
|
385
|
-
llmDone(info) {
|
|
386
|
-
if (!llmLog) return;
|
|
387
|
-
const parts = [];
|
|
388
|
-
if (info.usage) parts.push(`${Math.round(info.usage.totalTokens / 1e3)}k tokens`);
|
|
389
|
-
if (info.cost) parts.push(`$${info.cost.toFixed(2)}`);
|
|
390
|
-
const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
391
|
-
llmLog.success(`Generated best practices${suffix}`);
|
|
392
|
-
llmLog = null;
|
|
393
|
-
if (info.debugLogsDir) p.log.info(`Debug logs: ${relative(cwd, info.debugLogsDir)}`);
|
|
394
|
-
if (info.error) p.log.warn(`\x1B[33mPartial failure: ${info.error}\x1B[0m`);
|
|
395
|
-
if (info.warnings) for (const w of info.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
|
|
396
|
-
},
|
|
397
|
-
llmFailed(error, opts) {
|
|
398
|
-
if (!llmLog) return;
|
|
399
|
-
if (opts.rateLimited) llmLog.error(`Rate limited by LLM provider. Try again shortly or use a different model via \`skilld config\``);
|
|
400
|
-
else llmLog.error(`Enhancement failed${error ? `: ${error}` : ""}`);
|
|
401
|
-
llmLog = null;
|
|
402
|
-
},
|
|
403
|
-
shippedInstalled(skillName, relPath) {
|
|
404
|
-
p.log.success(`Using published SKILL.md: ${skillName} → ${relPath}`);
|
|
405
|
-
}
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
async function syncGitSkills(opts) {
|
|
409
|
-
const { source, agent, global: isGlobal, yes } = opts;
|
|
410
|
-
const cwd = process.cwd();
|
|
411
|
-
const agentConfig = targets[agent];
|
|
412
|
-
const baseDir = isGlobal ? join(CACHE_DIR, "skills") : join(cwd, agentConfig.skillsDir);
|
|
413
|
-
const label = source.type === "local" ? source.localPath : `${source.owner}/${source.repo}`;
|
|
414
|
-
const spin = timedSpinner();
|
|
415
|
-
spin.start(`Fetching skills from ${label}`);
|
|
416
|
-
const { skills } = await fetchGitSkills(source, (msg) => spin.message(msg));
|
|
417
|
-
if (skills.length === 0) {
|
|
418
|
-
if (source.type === "github" && source.owner && source.repo) {
|
|
419
|
-
spin.stop(`No pre-authored skills in ${label}, generating from repo docs...`);
|
|
420
|
-
return syncGitHubRepo(opts);
|
|
421
|
-
}
|
|
422
|
-
spin.stop(`No skills found in ${label}`);
|
|
423
|
-
return;
|
|
424
|
-
}
|
|
425
|
-
spin.stop(`Found ${skills.length} skill(s) in ${label}`);
|
|
426
|
-
let selected = skills;
|
|
427
|
-
if (opts.skillFilter?.length) {
|
|
428
|
-
const filterSet = new Set(opts.skillFilter.map((s) => s.toLowerCase().replace(/-skilld$/, "")));
|
|
429
|
-
selected = skills.filter((s) => filterSet.has(s.name.toLowerCase().replace(/-skilld$/, "")));
|
|
430
|
-
if (selected.length === 0) {
|
|
431
|
-
p.log.warn(`No skills matched: ${opts.skillFilter.join(", ")}`);
|
|
432
|
-
p.log.message(`Available: ${skills.map((s) => s.name).join(", ")}`);
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
} else if (source.skillPath) selected = skills;
|
|
436
|
-
else if (skills.length > 1 && !yes) {
|
|
437
|
-
const choices = await p.autocompleteMultiselect({
|
|
438
|
-
message: `Select skills to install from ${label}`,
|
|
439
|
-
options: skills.map((s) => ({
|
|
440
|
-
label: s.name.replace(/-skilld$/, ""),
|
|
441
|
-
value: s.name,
|
|
442
|
-
hint: s.description || s.path
|
|
443
|
-
})),
|
|
444
|
-
initialValues: []
|
|
445
|
-
});
|
|
446
|
-
if (p.isCancel(choices)) return;
|
|
447
|
-
const selectedNames = new Set(choices);
|
|
448
|
-
selected = skills.filter((s) => selectedNames.has(s.name));
|
|
449
|
-
if (selected.length === 0) return;
|
|
450
|
-
}
|
|
451
|
-
mkdirSync(baseDir, { recursive: true });
|
|
452
|
-
for (const skill of selected) {
|
|
453
|
-
const skillDir = join(baseDir, skill.name);
|
|
454
|
-
mkdirSync(skillDir, { recursive: true });
|
|
455
|
-
writeSkillMd(skillDir, sanitizeMarkdown(skill.content));
|
|
456
|
-
if (skill.files.length > 0) for (const f of skill.files) {
|
|
457
|
-
const filePath = join(skillDir, f.path);
|
|
458
|
-
mkdirSync(dirname(filePath), { recursive: true });
|
|
459
|
-
writeFileSync(filePath, f.content);
|
|
460
|
-
}
|
|
461
|
-
const sourceType = source.type === "local" ? "local" : source.type;
|
|
462
|
-
installSkill({
|
|
463
|
-
cwd,
|
|
464
|
-
agent,
|
|
465
|
-
global: isGlobal,
|
|
466
|
-
baseDir,
|
|
467
|
-
skillDirName: skill.name,
|
|
468
|
-
lock: {
|
|
469
|
-
source: sourceType,
|
|
470
|
-
repo: source.type === "local" ? source.localPath : `${source.owner}/${source.repo}`,
|
|
471
|
-
path: skill.path || void 0,
|
|
472
|
-
ref: source.ref || "main",
|
|
473
|
-
syncedAt: todayIsoDate(),
|
|
474
|
-
generator: "external"
|
|
475
|
-
},
|
|
476
|
-
skipLinkAgents: true
|
|
431
|
+
hooks.hook("resolve:start", ({ spec }) => {
|
|
432
|
+
currentSpec = spec;
|
|
433
|
+
spinner = timedSpinner();
|
|
434
|
+
spinner.start(`Resolving ${spec}`);
|
|
435
|
+
});
|
|
436
|
+
hooks.hook("resolve:progress", ({ message }) => {
|
|
437
|
+
spinner?.message(message);
|
|
438
|
+
});
|
|
439
|
+
hooks.hook("resolve:done", ({ version, cached, force }) => {
|
|
440
|
+
const suffix = force ? " (force)" : cached ? " (cached)" : "";
|
|
441
|
+
spinner?.stop(`Resolved ${currentSpec}@${version}${suffix}`);
|
|
442
|
+
spinner = null;
|
|
443
|
+
});
|
|
444
|
+
hooks.hook("resolve:failed", ({ identityName }) => {
|
|
445
|
+
spinner?.stop(`Could not find docs for: ${identityName}`);
|
|
446
|
+
spinner = null;
|
|
447
|
+
});
|
|
448
|
+
hooks.hook("dist:downloading", () => {
|
|
449
|
+
spinner?.message("Downloading dist");
|
|
450
|
+
});
|
|
451
|
+
hooks.hook("fetch:start", () => {
|
|
452
|
+
resourceSpinner = timedSpinner();
|
|
453
|
+
resourceSpinner.start("Finding resources");
|
|
454
|
+
});
|
|
455
|
+
hooks.hook("fetch:progress", ({ message }) => {
|
|
456
|
+
resourceSpinner?.message(message);
|
|
457
|
+
});
|
|
458
|
+
hooks.hook("fetch:done", ({ parts, cached }) => {
|
|
459
|
+
const summary = parts.length > 0 ? parts.join(", ") : "resources";
|
|
460
|
+
resourceSpinner?.stop(cached ? `Loaded ${summary} (cached)` : `Fetched ${summary}`);
|
|
461
|
+
resourceSpinner = null;
|
|
462
|
+
});
|
|
463
|
+
hooks.hook("index:start", () => {
|
|
464
|
+
indexSpinner = timedSpinner();
|
|
465
|
+
indexSpinner.start("Creating search index");
|
|
466
|
+
});
|
|
467
|
+
hooks.hook("index:progress", ({ message }) => {
|
|
468
|
+
indexSpinner?.message(message);
|
|
469
|
+
});
|
|
470
|
+
hooks.hook("index:done", () => {
|
|
471
|
+
indexSpinner?.stop("Search index ready");
|
|
472
|
+
indexSpinner = null;
|
|
473
|
+
});
|
|
474
|
+
hooks.hook("warn", ({ message }) => {
|
|
475
|
+
p.log.warn(styleText("yellow", message));
|
|
476
|
+
});
|
|
477
|
+
hooks.hook("base:done", ({ skillDir, mode }) => {
|
|
478
|
+
p.log.success(mode === "update" ? `Updated skill: ${skillDir}` : `Created base skill: ${skillDir}`);
|
|
479
|
+
});
|
|
480
|
+
hooks.hook("sections:cached", () => {
|
|
481
|
+
p.log.success("Applied cached SKILL.md sections");
|
|
482
|
+
});
|
|
483
|
+
hooks.hook("enhance:start", ({ spec, modelLabel }) => {
|
|
484
|
+
currentSpec = spec;
|
|
485
|
+
p.log.step(modelLabel);
|
|
486
|
+
llmLog = p.taskLog({
|
|
487
|
+
title: `Agent exploring ${spec}`,
|
|
488
|
+
limit: 3
|
|
477
489
|
});
|
|
478
|
-
}
|
|
479
|
-
if (source.type !== "local" && source.owner && source.repo) track({
|
|
480
|
-
event: "install",
|
|
481
|
-
source: `${source.owner}/${source.repo}`,
|
|
482
|
-
skills: selected.map((s) => s.name).join(","),
|
|
483
|
-
agents: agent,
|
|
484
|
-
...isGlobal && { global: "1" },
|
|
485
|
-
sourceType: source.type
|
|
486
490
|
});
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
const
|
|
490
|
-
|
|
491
|
-
}
|
|
492
|
-
}
|
|
493
|
-
async function syncGitHubRepo(opts) {
|
|
494
|
-
const { source, agent, global: isGlobal, yes } = opts;
|
|
495
|
-
const owner = source.owner;
|
|
496
|
-
const repo = source.repo;
|
|
497
|
-
const cwd = process.cwd();
|
|
498
|
-
const ui = createClackUi({ cwd });
|
|
499
|
-
const spec = `${owner}/${repo}`;
|
|
500
|
-
const result = await runBaseSync(spec, {
|
|
501
|
-
agent,
|
|
502
|
-
global: isGlobal,
|
|
503
|
-
force: opts.force,
|
|
504
|
-
from: opts.from
|
|
505
|
-
}, ui, createGithubResolver(owner, repo), cwd, DEFAULT_SECTIONS);
|
|
506
|
-
if (result.kind !== "ready") return;
|
|
507
|
-
const { state } = result;
|
|
508
|
-
const globalConfig = readConfig();
|
|
509
|
-
let llmConfig = null;
|
|
510
|
-
if (!state.allSectionsCached && !globalConfig.skipLlm && (!yes || opts.model)) llmConfig = await selectLlmConfig(opts.model);
|
|
511
|
-
await runEnhancePhase(state, llmConfig, {
|
|
512
|
-
agent,
|
|
513
|
-
global: isGlobal,
|
|
514
|
-
force: opts.force,
|
|
515
|
-
debug: opts.debug
|
|
516
|
-
}, ui, cwd);
|
|
517
|
-
await shutdownWorker();
|
|
518
|
-
track({
|
|
519
|
-
event: "install",
|
|
520
|
-
source: spec,
|
|
521
|
-
skills: state.skillDirName,
|
|
522
|
-
agents: agent,
|
|
523
|
-
...isGlobal && { global: "1" },
|
|
524
|
-
sourceType: "github-generated"
|
|
491
|
+
hooks.hook("enhance:progress", ({ progress }) => {
|
|
492
|
+
if (!llmLog) return;
|
|
493
|
+
const line = `${progress.section ? `[${progress.section}] ` : ""}${progress.chunk}`;
|
|
494
|
+
llmLog.message(line);
|
|
525
495
|
});
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
cwd,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
baseDir,
|
|
538
|
-
skillDirName,
|
|
539
|
-
lock: {
|
|
540
|
-
packageName: identityName,
|
|
541
|
-
version,
|
|
542
|
-
repo: repoSlug,
|
|
543
|
-
source: existingLock.source,
|
|
544
|
-
syncedAt: todayIsoDate(),
|
|
545
|
-
generator: "skilld"
|
|
546
|
-
},
|
|
547
|
-
skipLinkAgents: true
|
|
496
|
+
hooks.hook("enhance:done", (info) => {
|
|
497
|
+
if (!llmLog) return;
|
|
498
|
+
const parts = [];
|
|
499
|
+
if (info.usage) parts.push(`${Math.round(info.usage.totalTokens / 1e3)}k tokens`);
|
|
500
|
+
if (info.cost) parts.push(`$${info.cost.toFixed(2)}`);
|
|
501
|
+
const suffix = parts.length > 0 ? ` (${parts.join(", ")})` : "";
|
|
502
|
+
llmLog.success(`Generated best practices${suffix}`);
|
|
503
|
+
llmLog = null;
|
|
504
|
+
if (info.debugLogsDir) p.log.info(`Debug logs: ${relative(cwd, info.debugLogsDir)}`);
|
|
505
|
+
if (info.error) p.log.warn(styleText("yellow", `Partial failure: ${info.error}`));
|
|
506
|
+
if (info.warnings) for (const w of info.warnings) p.log.warn(styleText("yellow", w));
|
|
548
507
|
});
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
name: existingLock.packageName,
|
|
558
|
-
version: existingLock.version,
|
|
559
|
-
relatedSkills,
|
|
560
|
-
hasIssues: features.issues && existsSync(skillRefsSection(skillDir, "issues")),
|
|
561
|
-
hasDiscussions: features.discussions && existsSync(skillRefsSection(skillDir, "discussions")),
|
|
562
|
-
hasReleases: features.releases && existsSync(skillRefsSection(skillDir, "releases")),
|
|
563
|
-
docsType: existingLock.source?.includes("llms.txt") ? "llms.txt" : "docs",
|
|
564
|
-
hasShippedDocs: shippedDocs,
|
|
565
|
-
pkgFiles,
|
|
566
|
-
dirName: skillDirName,
|
|
567
|
-
packages: allPackages,
|
|
568
|
-
features
|
|
508
|
+
hooks.hook("enhance:failed", ({ error, rateLimited }) => {
|
|
509
|
+
if (!llmLog) return;
|
|
510
|
+
if (rateLimited) llmLog.error(`Rate limited by LLM provider. Try again shortly or use a different model via \`skilld config\``);
|
|
511
|
+
else llmLog.error(`Enhancement failed${error ? `: ${error}` : ""}`);
|
|
512
|
+
llmLog = null;
|
|
513
|
+
});
|
|
514
|
+
hooks.hook("shipped:installed", ({ skillName, skillDir }) => {
|
|
515
|
+
p.log.success(`Using published SKILL.md: ${skillName} → ${relative(cwd, skillDir)}`);
|
|
569
516
|
});
|
|
570
|
-
const sharedDir = !config.global && getSharedSkillsDir(cwd);
|
|
571
|
-
if (sharedDir) linkSkillToAgents(skillDirName, sharedDir, cwd, config.agent);
|
|
572
|
-
p.outro(`Merged ${identityName} into ${skillDirName}`);
|
|
573
517
|
}
|
|
574
518
|
const STATUS_ICONS = {
|
|
575
519
|
pending: "○",
|
|
@@ -583,37 +527,34 @@ const STATUS_ICONS = {
|
|
|
583
527
|
error: "✗"
|
|
584
528
|
};
|
|
585
529
|
const STATUS_COLORS = {
|
|
586
|
-
pending: "
|
|
587
|
-
resolving: "
|
|
588
|
-
downloading: "
|
|
589
|
-
embedding: "
|
|
590
|
-
exploring: "
|
|
591
|
-
thinking: "
|
|
592
|
-
generating: "
|
|
593
|
-
done: "
|
|
594
|
-
error: "
|
|
530
|
+
pending: "gray",
|
|
531
|
+
resolving: "cyan",
|
|
532
|
+
downloading: "cyan",
|
|
533
|
+
embedding: "cyan",
|
|
534
|
+
exploring: "blue",
|
|
535
|
+
thinking: "magenta",
|
|
536
|
+
generating: "yellow",
|
|
537
|
+
done: "green",
|
|
538
|
+
error: "red"
|
|
595
539
|
};
|
|
596
540
|
function renderParallel(r) {
|
|
597
541
|
const maxNameLen = Math.max(...[...r.states.keys()].map((n) => n.length), 20);
|
|
598
542
|
const lines = [...r.states.values()].map((s) => {
|
|
599
|
-
const icon = STATUS_ICONS[s.status];
|
|
600
|
-
const color = STATUS_COLORS[s.status];
|
|
601
|
-
const reset = "\x1B[0m";
|
|
602
|
-
const dim = "\x1B[90m";
|
|
543
|
+
const icon = styleText(STATUS_COLORS[s.status], STATUS_ICONS[s.status]);
|
|
603
544
|
const name = s.name.padEnd(maxNameLen);
|
|
604
|
-
const version = s.version ? `${
|
|
605
|
-
const elapsed = (s.status === "done" || s.status === "error") && s.startedAt && s.completedAt ? ` ${
|
|
606
|
-
const preview = s.streamPreview ? ` ${
|
|
607
|
-
return ` ${
|
|
545
|
+
const version = s.version ? `${styleText("gray", s.version)} ` : "";
|
|
546
|
+
const elapsed = (s.status === "done" || s.status === "error") && s.startedAt && s.completedAt ? ` ${styleText("gray", `(${formatDuration(s.completedAt - s.startedAt)})`)}` : "";
|
|
547
|
+
const preview = s.streamPreview ? ` ${styleText("gray", s.streamPreview)}` : "";
|
|
548
|
+
return ` ${icon} ${name} ${version}${s.message}${elapsed}${preview}`;
|
|
608
549
|
});
|
|
609
550
|
const doneCount = [...r.states.values()].filter((s) => s.status === "done").length;
|
|
610
551
|
const errorCount = [...r.states.values()].filter((s) => s.status === "error").length;
|
|
611
|
-
logUpdate(
|
|
552
|
+
logUpdate(`${styleText("bold", `${r.verb} ${r.total} packages`)} (${doneCount} done${errorCount > 0 ? `, ${errorCount} failed` : ""})\n` + lines.join("\n"));
|
|
612
553
|
}
|
|
613
|
-
function
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
554
|
+
function bindParallelUi(hooks, render) {
|
|
555
|
+
function update(spec, status, message, ver) {
|
|
556
|
+
const state = render.states.get(spec);
|
|
557
|
+
if (!state) return;
|
|
617
558
|
if (!state.startedAt && status !== "pending") state.startedAt = performance.now();
|
|
618
559
|
if ((status === "done" || status === "error") && !state.completedAt) state.completedAt = performance.now();
|
|
619
560
|
state.status = status;
|
|
@@ -622,58 +563,31 @@ function createParallelUi(name, render, version) {
|
|
|
622
563
|
if (ver) state.version = ver;
|
|
623
564
|
renderParallel(render);
|
|
624
565
|
}
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
indexProgress(msg) {
|
|
651
|
-
update("embedding", msg);
|
|
652
|
-
},
|
|
653
|
-
indexDone() {},
|
|
654
|
-
warn(_msg) {},
|
|
655
|
-
baseDone(_relPath, mode) {
|
|
656
|
-
update("done", mode === "update" ? "Skill updated" : "Base skill created");
|
|
657
|
-
},
|
|
658
|
-
sectionsCached() {},
|
|
659
|
-
llmStart(modelLabel) {
|
|
660
|
-
update("generating", modelLabel);
|
|
661
|
-
},
|
|
662
|
-
llmProgress(progress) {
|
|
663
|
-
const status = progress.type === "reasoning" ? "exploring" : "generating";
|
|
664
|
-
const sectionPrefix = progress.section ? `[${progress.section}] ` : "";
|
|
665
|
-
update(status, progress.chunk.startsWith("[") ? `${sectionPrefix}${progress.chunk}` : `${sectionPrefix}${progress.chunk}`);
|
|
666
|
-
},
|
|
667
|
-
llmDone(_info) {
|
|
668
|
-
update("done", "Skill optimized");
|
|
669
|
-
},
|
|
670
|
-
llmFailed(error, _opts) {
|
|
671
|
-
update("error", error);
|
|
672
|
-
},
|
|
673
|
-
shippedInstalled(_skillName, _relPath) {
|
|
674
|
-
update("done", "Published SKILL.md");
|
|
675
|
-
}
|
|
676
|
-
};
|
|
566
|
+
hooks.hook("resolve:start", ({ spec }) => update(spec, "resolving", "Resolving..."));
|
|
567
|
+
hooks.hook("resolve:progress", ({ spec, message }) => update(spec, "resolving", message));
|
|
568
|
+
hooks.hook("resolve:done", ({ spec, version, cached, force }) => {
|
|
569
|
+
update(spec, "downloading", cached ? "Using cache" : force ? "Re-fetching docs..." : "Fetching docs...", version);
|
|
570
|
+
});
|
|
571
|
+
hooks.hook("resolve:failed", () => {});
|
|
572
|
+
hooks.hook("dist:downloading", ({ spec }) => update(spec, "downloading", "Downloading dist..."));
|
|
573
|
+
hooks.hook("fetch:start", () => {});
|
|
574
|
+
hooks.hook("fetch:progress", ({ spec, message }) => update(spec, "downloading", message));
|
|
575
|
+
hooks.hook("fetch:done", ({ spec }) => update(spec, "downloading", "Linking references..."));
|
|
576
|
+
hooks.hook("index:start", ({ spec }) => update(spec, "embedding", "Indexing docs"));
|
|
577
|
+
hooks.hook("index:progress", ({ spec, message }) => update(spec, "embedding", message));
|
|
578
|
+
hooks.hook("index:done", () => {});
|
|
579
|
+
hooks.hook("warn", () => {});
|
|
580
|
+
hooks.hook("base:done", ({ spec, mode }) => {
|
|
581
|
+
update(spec, "done", mode === "update" ? "Skill updated" : "Base skill created");
|
|
582
|
+
});
|
|
583
|
+
hooks.hook("sections:cached", () => {});
|
|
584
|
+
hooks.hook("enhance:start", ({ spec, modelLabel }) => update(spec, "generating", modelLabel));
|
|
585
|
+
hooks.hook("enhance:progress", ({ spec, progress }) => {
|
|
586
|
+
update(spec, progress.type === "reasoning" ? "exploring" : "generating", `${progress.section ? `[${progress.section}] ` : ""}${progress.chunk}`);
|
|
587
|
+
});
|
|
588
|
+
hooks.hook("enhance:done", ({ spec }) => update(spec, "done", "Skill optimized"));
|
|
589
|
+
hooks.hook("enhance:failed", ({ spec, error }) => update(spec, "error", error));
|
|
590
|
+
hooks.hook("shipped:installed", ({ spec }) => update(spec, "done", "Published SKILL.md"));
|
|
677
591
|
}
|
|
678
592
|
const DIFF_RANK = {
|
|
679
593
|
major: 5,
|
|
@@ -688,11 +602,16 @@ async function syncPackagesParallel(config) {
|
|
|
688
602
|
const { packages, concurrency = 5 } = config;
|
|
689
603
|
const cwd = process.cwd();
|
|
690
604
|
const states = /* @__PURE__ */ new Map();
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
605
|
+
const specToName = /* @__PURE__ */ new Map();
|
|
606
|
+
for (const spec of packages) {
|
|
607
|
+
const { name } = parsePackageSpec(spec);
|
|
608
|
+
specToName.set(spec, name);
|
|
609
|
+
states.set(spec, {
|
|
610
|
+
name,
|
|
611
|
+
status: "pending",
|
|
612
|
+
message: "Waiting..."
|
|
613
|
+
});
|
|
614
|
+
}
|
|
696
615
|
const render = {
|
|
697
616
|
states,
|
|
698
617
|
verb: config.mode === "update" ? "Updating" : "Syncing",
|
|
@@ -700,17 +619,19 @@ async function syncPackagesParallel(config) {
|
|
|
700
619
|
};
|
|
701
620
|
ensureCacheDir();
|
|
702
621
|
renderParallel(render);
|
|
703
|
-
const
|
|
704
|
-
|
|
622
|
+
const run = createSyncRun({
|
|
623
|
+
cwd,
|
|
624
|
+
resolver: npmResolver,
|
|
705
625
|
agent: config.agent,
|
|
706
626
|
global: config.global,
|
|
707
627
|
mode: config.mode,
|
|
708
|
-
force: config.force
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
628
|
+
force: config.force,
|
|
629
|
+
debug: config.debug,
|
|
630
|
+
defaultSections: DEFAULT_SECTIONS
|
|
631
|
+
});
|
|
632
|
+
bindParallelUi(run.hooks, render);
|
|
633
|
+
const limit = pLimit(concurrency);
|
|
634
|
+
const baseResults = await Promise.allSettled(packages.map((spec) => limit(() => run.runBase(spec))));
|
|
714
635
|
logUpdate.done();
|
|
715
636
|
const ready = [];
|
|
716
637
|
const shippedCount = [];
|
|
@@ -736,13 +657,13 @@ async function syncPackagesParallel(config) {
|
|
|
736
657
|
continue;
|
|
737
658
|
}
|
|
738
659
|
if (result.kind === "unresolved") {
|
|
739
|
-
const npmAttempt = result.
|
|
660
|
+
const npmAttempt = result.attempts.find((a) => a.source === "npm");
|
|
740
661
|
let reason;
|
|
741
662
|
if (npmAttempt?.status === "not-found") {
|
|
742
|
-
const suggestions = await searchNpmPackages(result.
|
|
663
|
+
const suggestions = await searchNpmPackages(result.identityName, 3);
|
|
743
664
|
const hint = suggestions.length > 0 ? ` (try: ${suggestions.map((s) => s.name).join(", ")})` : "";
|
|
744
665
|
reason = (npmAttempt.message || "Not on npm") + hint;
|
|
745
|
-
} else reason = result.
|
|
666
|
+
} else reason = result.attempts.filter((a) => a.status !== "success").map((a) => a.message || a.source).join("; ") || "No docs found";
|
|
746
667
|
const slot = states.get(spec);
|
|
747
668
|
if (slot) {
|
|
748
669
|
slot.status = "error";
|
|
@@ -754,14 +675,14 @@ async function syncPackagesParallel(config) {
|
|
|
754
675
|
});
|
|
755
676
|
continue;
|
|
756
677
|
}
|
|
757
|
-
if (result.kind === "
|
|
678
|
+
if (result.kind === "error") {
|
|
758
679
|
errors.push({
|
|
759
680
|
spec,
|
|
760
|
-
reason:
|
|
681
|
+
reason: result.reason
|
|
761
682
|
});
|
|
762
683
|
continue;
|
|
763
684
|
}
|
|
764
|
-
ready.push({
|
|
685
|
+
if (result.kind === "ready") ready.push({
|
|
765
686
|
spec,
|
|
766
687
|
state: result.state
|
|
767
688
|
});
|
|
@@ -770,7 +691,7 @@ async function syncPackagesParallel(config) {
|
|
|
770
691
|
logUpdate.done();
|
|
771
692
|
const pastVerb = config.mode === "update" ? "Updated" : "Created";
|
|
772
693
|
p.log.success(`${pastVerb} ${ready.length} base skills${shippedCount.length > 0 ? ` (${shippedCount.length} shipped)` : ""}`);
|
|
773
|
-
for (const w of aggregatedWarnings) p.log.warn(
|
|
694
|
+
for (const w of aggregatedWarnings) p.log.warn(styleText("yellow", w));
|
|
774
695
|
for (const { spec, reason } of errors) p.log.error(` ${spec}: ${reason}`);
|
|
775
696
|
const cachedPkgs = [];
|
|
776
697
|
const uncached = [];
|
|
@@ -790,46 +711,25 @@ async function syncPackagesParallel(config) {
|
|
|
790
711
|
}
|
|
791
712
|
}
|
|
792
713
|
renderParallel(render);
|
|
793
|
-
for (const r of uncached)
|
|
794
|
-
const ui = createParallelUi(r.spec, render, getVersionKey(r.state.version));
|
|
795
|
-
await runEnhancePhase(r.state, llmConfig, {
|
|
796
|
-
agent: config.agent,
|
|
797
|
-
global: config.global,
|
|
798
|
-
force: config.force,
|
|
799
|
-
debug: config.debug
|
|
800
|
-
}, ui, cwd);
|
|
801
|
-
}
|
|
714
|
+
for (const r of uncached) await run.runEnhance(r.state, llmConfig);
|
|
802
715
|
} else if (llmConfig) {
|
|
803
716
|
p.log.step(getModelLabel(llmConfig.model));
|
|
804
|
-
for (const r of uncached)
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
717
|
+
for (const r of uncached) {
|
|
718
|
+
const displayName = specToName.get(r.spec) ?? r.spec;
|
|
719
|
+
states.set(r.spec, {
|
|
720
|
+
name: displayName,
|
|
721
|
+
status: "pending",
|
|
722
|
+
message: "Waiting...",
|
|
723
|
+
version: getVersionKey(r.state.version)
|
|
724
|
+
});
|
|
725
|
+
}
|
|
810
726
|
renderParallel(render);
|
|
811
|
-
const llmResults = await Promise.allSettled(uncached.map((r) => limit(
|
|
812
|
-
const ui = createParallelUi(r.spec, render, getVersionKey(r.state.version));
|
|
813
|
-
await runEnhancePhase(r.state, llmConfig, {
|
|
814
|
-
agent: config.agent,
|
|
815
|
-
global: config.global,
|
|
816
|
-
force: config.force,
|
|
817
|
-
debug: config.debug
|
|
818
|
-
}, ui, cwd);
|
|
819
|
-
})));
|
|
727
|
+
const llmResults = await Promise.allSettled(uncached.map((r) => limit(() => run.runEnhance(r.state, llmConfig))));
|
|
820
728
|
logUpdate.done();
|
|
821
729
|
const llmSucceeded = llmResults.filter((x) => x.status === "fulfilled").length;
|
|
822
730
|
p.log.success(`Enhanced ${llmSucceeded}/${uncached.length} skills with LLM`);
|
|
823
731
|
}
|
|
824
|
-
} else for (const r of ready)
|
|
825
|
-
const ui = createParallelUi(r.spec, render, getVersionKey(r.state.version));
|
|
826
|
-
await runEnhancePhase(r.state, null, {
|
|
827
|
-
agent: config.agent,
|
|
828
|
-
global: config.global,
|
|
829
|
-
force: config.force,
|
|
830
|
-
debug: config.debug
|
|
831
|
-
}, ui, cwd);
|
|
832
|
-
}
|
|
732
|
+
} else for (const r of ready) await run.runEnhance(r.state, null);
|
|
833
733
|
await ensureProjectFiles({
|
|
834
734
|
cwd,
|
|
835
735
|
agent: config.agent,
|
|
@@ -837,7 +737,7 @@ async function syncPackagesParallel(config) {
|
|
|
837
737
|
});
|
|
838
738
|
await shutdownWorker();
|
|
839
739
|
p.outro(`${pastVerb} ${ready.length}/${packages.length} packages`);
|
|
840
|
-
const { suggestPrepareHook } = await import("./
|
|
740
|
+
const { suggestPrepareHook } = await import("./prepare-hook.mjs");
|
|
841
741
|
try {
|
|
842
742
|
await suggestPrepareHook(cwd);
|
|
843
743
|
} catch (err) {
|
|
@@ -866,6 +766,52 @@ function aggregateUpdateCtx(ready) {
|
|
|
866
766
|
bumpType: maxDiff || void 0
|
|
867
767
|
};
|
|
868
768
|
}
|
|
769
|
+
async function handleMerge(state, config, cwd) {
|
|
770
|
+
const { identityName, storageName, version, resolved, baseDir, skillDir, skillDirName, existingLock } = state;
|
|
771
|
+
p.log.step(`Merging ${identityName} into ${skillDirName}`);
|
|
772
|
+
createReferenceCache(storageName, version).linkPkgNamed(skillDir, cwd);
|
|
773
|
+
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl);
|
|
774
|
+
installSkill({
|
|
775
|
+
cwd,
|
|
776
|
+
agent: config.agent,
|
|
777
|
+
global: config.global,
|
|
778
|
+
baseDir,
|
|
779
|
+
skillDirName,
|
|
780
|
+
lock: {
|
|
781
|
+
packageName: identityName,
|
|
782
|
+
version,
|
|
783
|
+
repo: repoSlug,
|
|
784
|
+
source: existingLock.source,
|
|
785
|
+
syncedAt: todayIsoDate(),
|
|
786
|
+
generator: "skilld"
|
|
787
|
+
},
|
|
788
|
+
skipLinkAgents: true
|
|
789
|
+
});
|
|
790
|
+
const updatedLock = readLock(baseDir)?.skills[skillDirName];
|
|
791
|
+
const allPackages = parsePackageNames(updatedLock?.packages);
|
|
792
|
+
const relatedSkills = await findRelatedSkills(storageName, baseDir);
|
|
793
|
+
const existingCache = createReferenceCache(toStoragePackageName(existingLock.packageName), existingLock.version);
|
|
794
|
+
const pkgFiles = existingCache.keyFiles(cwd);
|
|
795
|
+
const shippedDocs = existingCache.hasShipped(cwd);
|
|
796
|
+
const features = getActiveFeatures();
|
|
797
|
+
writeGeneratedSkillMd(skillDir, {
|
|
798
|
+
name: existingLock.packageName,
|
|
799
|
+
version: existingLock.version,
|
|
800
|
+
relatedSkills,
|
|
801
|
+
hasIssues: features.issues && existsSync(skillRefsSection(skillDir, "issues")),
|
|
802
|
+
hasDiscussions: features.discussions && existsSync(skillRefsSection(skillDir, "discussions")),
|
|
803
|
+
hasReleases: features.releases && existsSync(skillRefsSection(skillDir, "releases")),
|
|
804
|
+
docsType: existingLock.source?.includes("llms.txt") ? "llms.txt" : "docs",
|
|
805
|
+
hasShippedDocs: shippedDocs,
|
|
806
|
+
pkgFiles,
|
|
807
|
+
dirName: skillDirName,
|
|
808
|
+
packages: allPackages,
|
|
809
|
+
features
|
|
810
|
+
});
|
|
811
|
+
const sharedDir = !config.global && getSharedSkillsDir(cwd);
|
|
812
|
+
if (sharedDir) linkSkillToAgents(skillDirName, sharedDir, cwd, config.agent);
|
|
813
|
+
p.outro(`Merged ${identityName} into ${skillDirName}`);
|
|
814
|
+
}
|
|
869
815
|
const RESOLVE_SOURCE_LABELS = {
|
|
870
816
|
"npm": "npm registry",
|
|
871
817
|
"github-docs": "GitHub versioned docs",
|
|
@@ -878,11 +824,11 @@ const RESOLVE_SOURCE_LABELS = {
|
|
|
878
824
|
};
|
|
879
825
|
function showResolveAttempts(attempts) {
|
|
880
826
|
if (attempts.length === 0) return;
|
|
881
|
-
p.log.message("
|
|
827
|
+
p.log.message(styleText("gray", "Doc resolution:"));
|
|
882
828
|
for (const attempt of attempts) {
|
|
883
|
-
const icon = attempt.status === "success" ? "
|
|
884
|
-
const source =
|
|
885
|
-
const msg = attempt.message ? `
|
|
829
|
+
const icon = attempt.status === "success" ? styleText("green", "✓") : styleText("gray", "✗");
|
|
830
|
+
const source = styleText("gray", RESOLVE_SOURCE_LABELS[attempt.source] ?? attempt.source);
|
|
831
|
+
const msg = attempt.message ? ` ${styleText("gray", `— ${attempt.message}`)}` : "";
|
|
886
832
|
p.log.message(` ${icon} ${source}${msg}`);
|
|
887
833
|
}
|
|
888
834
|
}
|
|
@@ -979,9 +925,10 @@ async function pickFromList(packages, state) {
|
|
|
979
925
|
}
|
|
980
926
|
async function runSimpleSync(packageSpec, config) {
|
|
981
927
|
const cwd = process.cwd();
|
|
982
|
-
const ui = createClackUi({ cwd });
|
|
983
928
|
const isEject = !!config.eject;
|
|
984
|
-
const
|
|
929
|
+
const run = createSyncRun({
|
|
930
|
+
cwd,
|
|
931
|
+
resolver: npmResolver,
|
|
985
932
|
agent: config.agent,
|
|
986
933
|
global: config.global,
|
|
987
934
|
mode: config.mode,
|
|
@@ -989,18 +936,25 @@ async function runSimpleSync(packageSpec, config) {
|
|
|
989
936
|
noSearch: config.noSearch,
|
|
990
937
|
name: config.name,
|
|
991
938
|
from: config.from,
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
939
|
+
debug: config.debug,
|
|
940
|
+
eject: config.eject,
|
|
941
|
+
defaultSections: DEFAULT_SECTIONS,
|
|
942
|
+
onMergeNeeded: (state) => handleMerge(state, {
|
|
943
|
+
agent: config.agent,
|
|
944
|
+
global: config.global
|
|
945
|
+
}, cwd)
|
|
946
|
+
});
|
|
947
|
+
bindClackUi(run.hooks, { cwd });
|
|
948
|
+
const base = await run.runBase(packageSpec);
|
|
949
|
+
if (base.kind === "shipped") {
|
|
995
950
|
p.outro(`Synced ${packageSpec}`);
|
|
996
951
|
return;
|
|
997
952
|
}
|
|
998
|
-
if (
|
|
999
|
-
const { unresolved } = result;
|
|
953
|
+
if (base.kind === "unresolved") {
|
|
1000
954
|
if (!isCrateSpec(packageSpec)) {
|
|
1001
|
-
const suggestions = await searchNpmPackages(
|
|
955
|
+
const suggestions = await searchNpmPackages(base.identityName);
|
|
1002
956
|
if (suggestions.length > 0) {
|
|
1003
|
-
showResolveAttempts(
|
|
957
|
+
showResolveAttempts(base.attempts);
|
|
1004
958
|
const selected = await p.select({
|
|
1005
959
|
message: "Did you mean one of these?",
|
|
1006
960
|
options: [...suggestions.map((s) => ({
|
|
@@ -1016,28 +970,16 @@ async function runSimpleSync(packageSpec, config) {
|
|
|
1016
970
|
return;
|
|
1017
971
|
}
|
|
1018
972
|
}
|
|
1019
|
-
showResolveAttempts(
|
|
973
|
+
showResolveAttempts(base.attempts);
|
|
1020
974
|
return;
|
|
1021
975
|
}
|
|
1022
|
-
if (
|
|
1023
|
-
|
|
1024
|
-
agent: config.agent,
|
|
1025
|
-
global: config.global
|
|
1026
|
-
}, cwd);
|
|
1027
|
-
return;
|
|
1028
|
-
}
|
|
1029
|
-
const { state } = result;
|
|
976
|
+
if (base.kind === "merged" || base.kind === "error") return;
|
|
977
|
+
const { state } = base;
|
|
1030
978
|
const globalConfig = readConfig();
|
|
1031
979
|
const resolvedModel = await resolveAutoModel(config.model, config.yes);
|
|
1032
980
|
let llmConfig = null;
|
|
1033
981
|
if (!state.allSectionsCached && !globalConfig.skipLlm && !(config.yes && !resolvedModel)) llmConfig = await selectLlmConfig(resolvedModel, void 0, state.updateCtx);
|
|
1034
|
-
await
|
|
1035
|
-
agent: config.agent,
|
|
1036
|
-
global: config.global,
|
|
1037
|
-
force: config.force,
|
|
1038
|
-
debug: config.debug,
|
|
1039
|
-
eject: config.eject
|
|
1040
|
-
}, ui, cwd);
|
|
982
|
+
await run.runEnhance(state, llmConfig);
|
|
1041
983
|
await shutdownWorker();
|
|
1042
984
|
const ejectMsg = isEject ? " (ejected)" : "";
|
|
1043
985
|
const relDir = relative(cwd, state.skillDir);
|
|
@@ -1055,447 +997,6 @@ async function syncSinglePackage(packageSpec, config) {
|
|
|
1055
997
|
}
|
|
1056
998
|
return runSimpleSync(packageSpec, config);
|
|
1057
999
|
}
|
|
1058
|
-
|
|
1059
|
-
meta: {
|
|
1060
|
-
name: "add",
|
|
1061
|
-
description: "Install skills (npm:<pkg>, crate:<name>, gh:<owner/repo>, @<curator>)"
|
|
1062
|
-
},
|
|
1063
|
-
args: {
|
|
1064
|
-
package: {
|
|
1065
|
-
type: "positional",
|
|
1066
|
-
description: "Package(s) to sync (space/comma-separated; npm:<pkg>, crate:<name>, or owner/repo)",
|
|
1067
|
-
required: true
|
|
1068
|
-
},
|
|
1069
|
-
skill: {
|
|
1070
|
-
type: "string",
|
|
1071
|
-
alias: "s",
|
|
1072
|
-
description: "Select specific skills from a git repo (comma-separated)",
|
|
1073
|
-
valueHint: "name"
|
|
1074
|
-
},
|
|
1075
|
-
...sharedArgs
|
|
1076
|
-
},
|
|
1077
|
-
async run({ args }) {
|
|
1078
|
-
const cwd = process.cwd();
|
|
1079
|
-
let agent = resolveAgent(args.agent);
|
|
1080
|
-
if (!agent) {
|
|
1081
|
-
agent = await promptForAgent();
|
|
1082
|
-
if (!agent) return;
|
|
1083
|
-
}
|
|
1084
|
-
const rawInputs = [...new Set([args.package, ...args._ || []].map((s) => s.trim()).filter(Boolean))];
|
|
1085
|
-
if (agent === "none") {
|
|
1086
|
-
const packages = [...new Set(rawInputs.flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean))];
|
|
1087
|
-
for (const pkg of packages) await exportPortablePrompts(pkg, {
|
|
1088
|
-
force: args.force,
|
|
1089
|
-
agent: "none"
|
|
1090
|
-
});
|
|
1091
|
-
return;
|
|
1092
|
-
}
|
|
1093
|
-
if (!hasCompletedWizard()) await runWizard({ agent });
|
|
1094
|
-
const parsedSources = rawInputs.map(parseSkillInput);
|
|
1095
|
-
const gitSources = [];
|
|
1096
|
-
const npmEntries = [];
|
|
1097
|
-
const crateSpecs = [];
|
|
1098
|
-
const unsupported = [];
|
|
1099
|
-
for (const source of parsedSources) switch (source.type) {
|
|
1100
|
-
case "git":
|
|
1101
|
-
gitSources.push(source.source);
|
|
1102
|
-
break;
|
|
1103
|
-
case "npm":
|
|
1104
|
-
npmEntries.push({
|
|
1105
|
-
name: source.package,
|
|
1106
|
-
spec: source.tag ? `${source.package}@${source.tag}` : source.package
|
|
1107
|
-
});
|
|
1108
|
-
break;
|
|
1109
|
-
case "crate":
|
|
1110
|
-
crateSpecs.push(source.version ? `crate:${source.package}@${source.version}` : `crate:${source.package}`);
|
|
1111
|
-
break;
|
|
1112
|
-
case "bare":
|
|
1113
|
-
p.log.warn(`Bare names are deprecated. Use \x1B[36mnpm:${source.package}\x1B[0m instead.`);
|
|
1114
|
-
npmEntries.push({
|
|
1115
|
-
name: source.package,
|
|
1116
|
-
spec: source.tag ? `${source.package}@${source.tag}` : source.package
|
|
1117
|
-
});
|
|
1118
|
-
break;
|
|
1119
|
-
case "curator":
|
|
1120
|
-
unsupported.push(`@${source.handle} (curator)`);
|
|
1121
|
-
break;
|
|
1122
|
-
case "collection":
|
|
1123
|
-
unsupported.push(`@${source.handle}/${source.name} (collection)`);
|
|
1124
|
-
break;
|
|
1125
|
-
default: throw new Error(`Unhandled SkillSource type: ${JSON.stringify(source)}`);
|
|
1126
|
-
}
|
|
1127
|
-
if (unsupported.length > 0) {
|
|
1128
|
-
p.log.error(`Curator and collection installs are not yet available:\n ${unsupported.join("\n ")}\n\nFollow https://skilld.dev for launch updates.`);
|
|
1129
|
-
process.exitCode = 1;
|
|
1130
|
-
if (gitSources.length === 0 && npmEntries.length === 0 && crateSpecs.length === 0) return;
|
|
1131
|
-
}
|
|
1132
|
-
if (gitSources.length > 0) for (const source of gitSources) {
|
|
1133
|
-
const skillFilter = args.skill ? args.skill.split(/[,\s]+/).map((s) => s.trim()).filter(Boolean) : void 0;
|
|
1134
|
-
await syncGitSkills({
|
|
1135
|
-
source,
|
|
1136
|
-
global: args.global,
|
|
1137
|
-
agent,
|
|
1138
|
-
yes: args.yes,
|
|
1139
|
-
model: args.model,
|
|
1140
|
-
force: args.force,
|
|
1141
|
-
debug: args.debug,
|
|
1142
|
-
skillFilter
|
|
1143
|
-
});
|
|
1144
|
-
}
|
|
1145
|
-
if (npmEntries.length > 0) {
|
|
1146
|
-
const { syncRegistrySkill } = await import("./sync-registry.mjs");
|
|
1147
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1148
|
-
const dedupedEntries = npmEntries.filter((e) => {
|
|
1149
|
-
if (seen.has(e.name)) return false;
|
|
1150
|
-
seen.add(e.name);
|
|
1151
|
-
return true;
|
|
1152
|
-
});
|
|
1153
|
-
const fallbackPackages = [];
|
|
1154
|
-
for (const entry of dedupedEntries) {
|
|
1155
|
-
const result = await syncRegistrySkill({
|
|
1156
|
-
packageName: entry.name,
|
|
1157
|
-
agent,
|
|
1158
|
-
cwd
|
|
1159
|
-
});
|
|
1160
|
-
if (result) p.log.success(`Installed \x1B[36m${result.name}\x1B[0m from registry`);
|
|
1161
|
-
else fallbackPackages.push(entry.spec);
|
|
1162
|
-
}
|
|
1163
|
-
if (fallbackPackages.length > 0) {
|
|
1164
|
-
const state = await getProjectState(cwd);
|
|
1165
|
-
p.intro(introLine({
|
|
1166
|
-
state,
|
|
1167
|
-
agentId: agent || void 0
|
|
1168
|
-
}));
|
|
1169
|
-
await syncCommand(state, {
|
|
1170
|
-
packages: [...fallbackPackages, ...crateSpecs],
|
|
1171
|
-
global: args.global,
|
|
1172
|
-
agent,
|
|
1173
|
-
model: args.model,
|
|
1174
|
-
yes: args.yes,
|
|
1175
|
-
force: args.force,
|
|
1176
|
-
debug: args.debug
|
|
1177
|
-
});
|
|
1178
|
-
return;
|
|
1179
|
-
}
|
|
1180
|
-
}
|
|
1181
|
-
if (crateSpecs.length > 0) {
|
|
1182
|
-
const state = await getProjectState(cwd);
|
|
1183
|
-
p.intro(introLine({
|
|
1184
|
-
state,
|
|
1185
|
-
agentId: agent || void 0
|
|
1186
|
-
}));
|
|
1187
|
-
await syncCommand(state, {
|
|
1188
|
-
packages: crateSpecs,
|
|
1189
|
-
global: args.global,
|
|
1190
|
-
agent,
|
|
1191
|
-
model: args.model,
|
|
1192
|
-
yes: args.yes,
|
|
1193
|
-
force: args.force,
|
|
1194
|
-
debug: args.debug
|
|
1195
|
-
});
|
|
1196
|
-
}
|
|
1197
|
-
}
|
|
1198
|
-
});
|
|
1199
|
-
const ejectCommandDef = defineCommand({
|
|
1200
|
-
meta: {
|
|
1201
|
-
name: "eject",
|
|
1202
|
-
description: "Eject skill with references as real files (portable, no symlinks)"
|
|
1203
|
-
},
|
|
1204
|
-
args: {
|
|
1205
|
-
package: {
|
|
1206
|
-
type: "positional",
|
|
1207
|
-
description: "Package to eject",
|
|
1208
|
-
required: true
|
|
1209
|
-
},
|
|
1210
|
-
name: {
|
|
1211
|
-
type: "string",
|
|
1212
|
-
alias: "n",
|
|
1213
|
-
description: "Custom skill directory name (default: derived from package)"
|
|
1214
|
-
},
|
|
1215
|
-
out: {
|
|
1216
|
-
type: "string",
|
|
1217
|
-
alias: "o",
|
|
1218
|
-
description: "Output directory path override"
|
|
1219
|
-
},
|
|
1220
|
-
from: {
|
|
1221
|
-
type: "string",
|
|
1222
|
-
description: "Collect releases/issues/discussions from this date onward (YYYY-MM-DD)"
|
|
1223
|
-
},
|
|
1224
|
-
search: {
|
|
1225
|
-
type: "boolean",
|
|
1226
|
-
description: "Build search index / embeddings (use --no-search to skip)",
|
|
1227
|
-
default: true
|
|
1228
|
-
},
|
|
1229
|
-
...sharedArgs
|
|
1230
|
-
},
|
|
1231
|
-
async run({ args }) {
|
|
1232
|
-
const cwd = process.cwd();
|
|
1233
|
-
const resolved = resolveAgent(args.agent);
|
|
1234
|
-
const agent = resolved && resolved !== "none" ? resolved : "claude-code";
|
|
1235
|
-
if (!hasCompletedWizard()) await runWizard({ agent });
|
|
1236
|
-
const state = await getProjectState(cwd);
|
|
1237
|
-
p.intro(introLine({
|
|
1238
|
-
state,
|
|
1239
|
-
agentId: agent || void 0
|
|
1240
|
-
}));
|
|
1241
|
-
return syncCommand(state, {
|
|
1242
|
-
packages: [args.package],
|
|
1243
|
-
global: args.global,
|
|
1244
|
-
agent,
|
|
1245
|
-
model: args.model,
|
|
1246
|
-
yes: args.yes,
|
|
1247
|
-
force: args.force,
|
|
1248
|
-
debug: args.debug,
|
|
1249
|
-
eject: args.out || true,
|
|
1250
|
-
name: args.name,
|
|
1251
|
-
from: args.from,
|
|
1252
|
-
noSearch: !args.search
|
|
1253
|
-
});
|
|
1254
|
-
}
|
|
1255
|
-
});
|
|
1256
|
-
const updateCommandDef = defineCommand({
|
|
1257
|
-
meta: {
|
|
1258
|
-
name: "update",
|
|
1259
|
-
description: "Update outdated skills"
|
|
1260
|
-
},
|
|
1261
|
-
args: {
|
|
1262
|
-
package: {
|
|
1263
|
-
type: "positional",
|
|
1264
|
-
description: "Package(s) to update (space or comma-separated). Without args, syncs all outdated.",
|
|
1265
|
-
required: false
|
|
1266
|
-
},
|
|
1267
|
-
background: {
|
|
1268
|
-
type: "boolean",
|
|
1269
|
-
alias: "b",
|
|
1270
|
-
description: "Run in background (detached process, non-interactive)",
|
|
1271
|
-
default: false
|
|
1272
|
-
},
|
|
1273
|
-
...sharedArgs
|
|
1274
|
-
},
|
|
1275
|
-
async run({ args }) {
|
|
1276
|
-
const cwd = process.cwd();
|
|
1277
|
-
if (args.background) {
|
|
1278
|
-
const { spawn } = await import("node:child_process");
|
|
1279
|
-
const updateArgs = [
|
|
1280
|
-
"update",
|
|
1281
|
-
...args.package ? [args.package] : [],
|
|
1282
|
-
...args.agent ? ["--agent", args.agent] : [],
|
|
1283
|
-
...args.model ? ["--model", args.model] : []
|
|
1284
|
-
];
|
|
1285
|
-
spawn(process.execPath, [process.argv[1], ...updateArgs], {
|
|
1286
|
-
cwd,
|
|
1287
|
-
detached: true,
|
|
1288
|
-
stdio: "ignore"
|
|
1289
|
-
}).unref();
|
|
1290
|
-
return;
|
|
1291
|
-
}
|
|
1292
|
-
const silent = !isInteractive();
|
|
1293
|
-
let agent = resolveAgent(args.agent);
|
|
1294
|
-
if (!agent) {
|
|
1295
|
-
agent = await promptForAgent();
|
|
1296
|
-
if (!agent) return;
|
|
1297
|
-
}
|
|
1298
|
-
if (agent === "none") {
|
|
1299
|
-
const state = await getProjectState(cwd);
|
|
1300
|
-
const packages = args.package ? Array.from(new Set([args.package, ...args._ || []].flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean)), (s) => resolveSkillName(s)).filter((s) => s !== null) : state.outdated.map((s) => s.packageName || s.name);
|
|
1301
|
-
if (packages.length === 0) {
|
|
1302
|
-
if (!silent) p.log.success("All skills up to date");
|
|
1303
|
-
return;
|
|
1304
|
-
}
|
|
1305
|
-
for (const pkg of packages) await exportPortablePrompts(pkg, {
|
|
1306
|
-
force: args.force,
|
|
1307
|
-
agent: "none"
|
|
1308
|
-
});
|
|
1309
|
-
return;
|
|
1310
|
-
}
|
|
1311
|
-
const config = readConfig();
|
|
1312
|
-
const state = await getProjectState(cwd);
|
|
1313
|
-
if (!silent) {
|
|
1314
|
-
const generators = getInstalledGenerators();
|
|
1315
|
-
p.intro(introLine({
|
|
1316
|
-
state,
|
|
1317
|
-
generators,
|
|
1318
|
-
modelId: config.model,
|
|
1319
|
-
agentId: config.agent || agent || void 0
|
|
1320
|
-
}));
|
|
1321
|
-
}
|
|
1322
|
-
if (args.package) {
|
|
1323
|
-
const raw = [...new Set([args.package, ...args._ || []].flatMap((s) => s.split(/[,\s]+/)).map((s) => s.trim()).filter(Boolean))];
|
|
1324
|
-
const packages = [];
|
|
1325
|
-
for (const r of raw) {
|
|
1326
|
-
const name = resolveSkillName(r);
|
|
1327
|
-
if (!name) {
|
|
1328
|
-
p.log.warn(`Cannot update \x1B[36m${r}\x1B[0m: curator/collection inputs are not addressable here.`);
|
|
1329
|
-
continue;
|
|
1330
|
-
}
|
|
1331
|
-
packages.push(name);
|
|
1332
|
-
}
|
|
1333
|
-
if (packages.length === 0) return;
|
|
1334
|
-
return syncCommand(state, {
|
|
1335
|
-
packages,
|
|
1336
|
-
global: args.global,
|
|
1337
|
-
agent,
|
|
1338
|
-
model: args.model || (silent ? config.model : void 0),
|
|
1339
|
-
yes: args.yes || silent,
|
|
1340
|
-
force: args.force,
|
|
1341
|
-
debug: args.debug,
|
|
1342
|
-
mode: "update"
|
|
1343
|
-
});
|
|
1344
|
-
}
|
|
1345
|
-
const crateSpecs = state.skills.map((s) => s.info?.packageName).filter((name) => !!name && name.startsWith("crate:"));
|
|
1346
|
-
if (state.outdated.length === 0 && crateSpecs.length === 0) {
|
|
1347
|
-
p.log.success("All skills up to date");
|
|
1348
|
-
return;
|
|
1349
|
-
}
|
|
1350
|
-
return syncCommand(state, {
|
|
1351
|
-
packages: [...state.outdated.map((s) => s.packageName || s.name), ...crateSpecs],
|
|
1352
|
-
global: args.global,
|
|
1353
|
-
agent,
|
|
1354
|
-
model: args.model || (silent ? config.model : void 0),
|
|
1355
|
-
yes: args.yes || silent,
|
|
1356
|
-
force: args.force,
|
|
1357
|
-
debug: args.debug,
|
|
1358
|
-
mode: "update"
|
|
1359
|
-
});
|
|
1360
|
-
}
|
|
1361
|
-
});
|
|
1362
|
-
async function exportPortablePrompts(packageSpec, opts) {
|
|
1363
|
-
const sections = opts.sections ?? DEFAULT_SECTIONS;
|
|
1364
|
-
const spin = timedSpinner();
|
|
1365
|
-
spin.start(`Resolving ${packageSpec}`);
|
|
1366
|
-
const cwd = process.cwd();
|
|
1367
|
-
const { packageName, localVersion, resolved } = await resolvePackageOrCrate(packageSpec, {
|
|
1368
|
-
cwd,
|
|
1369
|
-
onProgress: (label) => spin.message(`${packageSpec}: ${label}`)
|
|
1370
|
-
});
|
|
1371
|
-
if (!resolved) {
|
|
1372
|
-
spin.stop(`Could not find docs for: ${packageSpec}`);
|
|
1373
|
-
return;
|
|
1374
|
-
}
|
|
1375
|
-
const version = localVersion || resolved.version || "latest";
|
|
1376
|
-
const cache = createReferenceCache(packageName, version);
|
|
1377
|
-
const useCache = !opts.force && cache.has();
|
|
1378
|
-
if (!existsSync(join(cwd, "node_modules", packageName))) {
|
|
1379
|
-
spin.message(`Downloading ${packageName}@${version} dist`);
|
|
1380
|
-
await fetchPkgDist(packageName, version);
|
|
1381
|
-
}
|
|
1382
|
-
spin.stop(`Resolved ${packageName}@${useCache ? cache.versionKey : version}`);
|
|
1383
|
-
cache.ensure();
|
|
1384
|
-
const skillDirName = computeSkillDirName(packageName);
|
|
1385
|
-
const features = getActiveFeatures();
|
|
1386
|
-
const agent = opts.agent === "none" ? null : opts.agent ?? await import("./detect2.mjs").then((m) => m.detectTargetAgent());
|
|
1387
|
-
const baseDir = agent ? resolveBaseDir(cwd, agent, false) : join(cwd, ".claude", "skills");
|
|
1388
|
-
const skillDir = opts.out ? resolve(cwd, opts.out) : join(baseDir, skillDirName);
|
|
1389
|
-
if (existsSync(skillDir) && !opts.force) {
|
|
1390
|
-
const existing = Object.values(SECTION_OUTPUT_FILES).filter((f) => existsSync(join(skillDir, f)));
|
|
1391
|
-
if (existing.length > 0) p.log.warn(`Overwriting existing output files in ${relative(cwd, skillDir)}: ${existing.join(", ")}`);
|
|
1392
|
-
}
|
|
1393
|
-
mkdirSync(skillDir, { recursive: true });
|
|
1394
|
-
const resSpin = timedSpinner();
|
|
1395
|
-
resSpin.start("Fetching resources");
|
|
1396
|
-
const resources = await fetchAndCacheResources({
|
|
1397
|
-
packageName,
|
|
1398
|
-
resolved,
|
|
1399
|
-
version,
|
|
1400
|
-
useCache,
|
|
1401
|
-
features,
|
|
1402
|
-
onProgress: (msg) => resSpin.message(msg)
|
|
1403
|
-
});
|
|
1404
|
-
resSpin.stop("Resources ready");
|
|
1405
|
-
for (const w of resources.warnings) p.log.warn(`\x1B[33m${w}\x1B[0m`);
|
|
1406
|
-
const { hasChangelog, shippedDocs, pkgFiles, relatedSkills } = await prepareSkillReferences({
|
|
1407
|
-
packageName,
|
|
1408
|
-
version,
|
|
1409
|
-
cwd,
|
|
1410
|
-
skillDir,
|
|
1411
|
-
resources,
|
|
1412
|
-
features,
|
|
1413
|
-
baseDir: join(skillDir, "..")
|
|
1414
|
-
});
|
|
1415
|
-
const docFiles = listReferenceFiles(skillDir);
|
|
1416
|
-
const prompts = buildAllSectionPrompts({
|
|
1417
|
-
packageName,
|
|
1418
|
-
skillDir,
|
|
1419
|
-
version,
|
|
1420
|
-
hasIssues: resources.hasIssues,
|
|
1421
|
-
hasDiscussions: resources.hasDiscussions,
|
|
1422
|
-
hasReleases: resources.hasReleases,
|
|
1423
|
-
hasChangelog,
|
|
1424
|
-
docFiles,
|
|
1425
|
-
docsType: resources.docsType,
|
|
1426
|
-
hasShippedDocs: shippedDocs,
|
|
1427
|
-
pkgFiles,
|
|
1428
|
-
features,
|
|
1429
|
-
sections
|
|
1430
|
-
});
|
|
1431
|
-
cache.eject(skillDir, cwd, resources.docsType, {
|
|
1432
|
-
features,
|
|
1433
|
-
repoInfo: resources.repoInfo
|
|
1434
|
-
});
|
|
1435
|
-
cache.clearSkillInternal(skillDir);
|
|
1436
|
-
for (const [section, prompt] of prompts) {
|
|
1437
|
-
const portable = portabilizePrompt(prompt, section);
|
|
1438
|
-
writeFileSync(join(skillDir, `PROMPT_${section}.md`), portable);
|
|
1439
|
-
}
|
|
1440
|
-
writeGeneratedSkillMd(skillDir, {
|
|
1441
|
-
name: packageName,
|
|
1442
|
-
version,
|
|
1443
|
-
releasedAt: resolved.releasedAt,
|
|
1444
|
-
description: resolved.description,
|
|
1445
|
-
distTags: resolved.distTags,
|
|
1446
|
-
relatedSkills,
|
|
1447
|
-
hasIssues: resources.hasIssues,
|
|
1448
|
-
hasDiscussions: resources.hasDiscussions,
|
|
1449
|
-
hasReleases: resources.hasReleases,
|
|
1450
|
-
hasChangelog,
|
|
1451
|
-
docsType: resources.docsType,
|
|
1452
|
-
hasShippedDocs: shippedDocs,
|
|
1453
|
-
pkgFiles,
|
|
1454
|
-
repoUrl: resolved.repoUrl,
|
|
1455
|
-
features,
|
|
1456
|
-
eject: true
|
|
1457
|
-
});
|
|
1458
|
-
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl);
|
|
1459
|
-
if (agent) {
|
|
1460
|
-
const { shared } = installSkill({
|
|
1461
|
-
cwd,
|
|
1462
|
-
agent,
|
|
1463
|
-
global: false,
|
|
1464
|
-
baseDir,
|
|
1465
|
-
skillDirName,
|
|
1466
|
-
lock: {
|
|
1467
|
-
packageName,
|
|
1468
|
-
version,
|
|
1469
|
-
repo: repoSlug,
|
|
1470
|
-
source: resources.docSource,
|
|
1471
|
-
syncedAt: todayIsoDate(),
|
|
1472
|
-
generator: "skilld"
|
|
1473
|
-
}
|
|
1474
|
-
});
|
|
1475
|
-
await ensureProjectFiles({
|
|
1476
|
-
cwd,
|
|
1477
|
-
agent,
|
|
1478
|
-
global: false,
|
|
1479
|
-
shared
|
|
1480
|
-
});
|
|
1481
|
-
} else {
|
|
1482
|
-
writeLock(baseDir, skillDirName, {
|
|
1483
|
-
packageName,
|
|
1484
|
-
version,
|
|
1485
|
-
repo: repoSlug,
|
|
1486
|
-
source: resources.docSource,
|
|
1487
|
-
syncedAt: todayIsoDate(),
|
|
1488
|
-
generator: "skilld"
|
|
1489
|
-
});
|
|
1490
|
-
await ensureGitignore(".claude/skills", cwd, false);
|
|
1491
|
-
}
|
|
1492
|
-
const relDir = relative(cwd, skillDir);
|
|
1493
|
-
const sectionList = [...prompts.keys()];
|
|
1494
|
-
p.log.success(`Skill installed to ${relDir}`);
|
|
1495
|
-
const promptFiles = sectionList.map((s) => `PROMPT_${s}.md`).join(", ");
|
|
1496
|
-
const outputFileList = sectionList.map((s) => SECTION_OUTPUT_FILES[s]).join(", ");
|
|
1497
|
-
p.log.info(`Have your agent enhance the skill. Give it this prompt:\n\x1B[2m\x1B[3m Read each prompt file (${promptFiles}) in ${relDir}/, read the\n referenced files, then write your output to the matching file (${outputFileList}).\n When done, run: skilld assemble\x1B[0m`);
|
|
1498
|
-
}
|
|
1499
|
-
export { updateCommandDef as a, syncCommand as i, ejectCommandDef as n, exportPortablePrompts as r, addCommandDef as t };
|
|
1000
|
+
export { createGithubResolver as i, bindClackUi as n, createSyncRun as r, syncCommand as t };
|
|
1500
1001
|
|
|
1501
1002
|
//# sourceMappingURL=sync.mjs.map
|