Skip to content

Commit 9f2b9b7

Browse files
authored
fix(sync): skip LLM prompt when all sections are cached (#40)
1 parent 14cf8d8 commit 9f2b9b7

2 files changed

Lines changed: 117 additions & 9 deletions

File tree

src/commands/sync-parallel.ts

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import {
1414
getModelLabel,
1515
linkSkillToAgents,
1616
optimizeDocs,
17+
SECTION_MERGE_ORDER,
18+
SECTION_OUTPUT_FILES,
19+
wrapSection,
1720

1821
} from '../agent/index.ts'
1922
import {
@@ -25,6 +28,7 @@ import {
2528
isCached,
2629
linkPkgNamed,
2730
listReferenceFiles,
31+
readCachedSection,
2832
resolvePkgDir,
2933
} from '../cache/index.ts'
3034
import { defaultFeatures, readConfig, registerProject } from '../core/config.ts'
@@ -52,7 +56,7 @@ import {
5256
resolveBaseDir,
5357
resolveLocalDep,
5458
} from './sync-shared.ts'
55-
import { ensureAgentInstructions, ensureGitignore, selectLlmConfig, writePromptFiles } from './sync.ts'
59+
import { DEFAULT_SECTIONS, ensureAgentInstructions, ensureGitignore, selectLlmConfig, writePromptFiles } from './sync.ts'
5660

5761
type PackageStatus = 'pending' | 'resolving' | 'downloading' | 'embedding' | 'exploring' | 'thinking' | 'generating' | 'done' | 'error'
5862

@@ -221,13 +225,68 @@ export async function syncPackagesParallel(config: ParallelSyncConfig): Promise<
221225
}
222226
}
223227

224-
// Phase 2: Ask about LLM enhancement (skip if -y without model, or skipLlm config)
228+
// Apply cached LLM sections for packages that have all sections cached
229+
const cachedPkgs: string[] = []
230+
if (!config.force) {
231+
for (const pkg of successfulPkgs) {
232+
const data = skillData.get(pkg)!
233+
const resolvedName = data.resolved.name
234+
const allCached = DEFAULT_SECTIONS.every((s) => {
235+
const outputFile = SECTION_OUTPUT_FILES[s]
236+
return readCachedSection(resolvedName, data.version, outputFile) !== null
237+
})
238+
if (allCached) {
239+
const baseDir = resolveBaseDir(cwd, config.agent, config.global)
240+
const skillDir = join(baseDir, data.skillDirName)
241+
const cachedParts: string[] = []
242+
for (const s of SECTION_MERGE_ORDER) {
243+
if (!DEFAULT_SECTIONS.includes(s))
244+
continue
245+
const outputFile = SECTION_OUTPUT_FILES[s]
246+
const content = readCachedSection(resolvedName, data.version, outputFile)
247+
if (content)
248+
cachedParts.push(wrapSection(s, content))
249+
}
250+
const cachedBody = cachedParts.join('\n\n')
251+
252+
const skillMd = generateSkillMd({
253+
name: resolvedName,
254+
version: data.version,
255+
releasedAt: data.resolved.releasedAt,
256+
dependencies: data.resolved.dependencies,
257+
distTags: data.resolved.distTags,
258+
body: cachedBody,
259+
relatedSkills: data.relatedSkills,
260+
hasIssues: data.hasIssues,
261+
hasDiscussions: data.hasDiscussions,
262+
hasReleases: data.hasReleases,
263+
hasChangelog: data.hasChangelog,
264+
docsType: data.docsType,
265+
hasShippedDocs: data.shippedDocs,
266+
pkgFiles: data.pkgFiles,
267+
generatedBy: 'cached',
268+
dirName: data.skillDirName,
269+
packages: data.packages,
270+
repoUrl: data.resolved.repoUrl,
271+
features: data.features,
272+
})
273+
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
274+
cachedPkgs.push(pkg)
275+
}
276+
}
277+
}
278+
279+
const uncachedPkgs = successfulPkgs.filter(pkg => !cachedPkgs.includes(pkg))
280+
if (cachedPkgs.length > 0)
281+
p.log.success(`Applied cached SKILL.md sections for ${cachedPkgs.join(', ')}`)
282+
283+
// Phase 2: Ask about LLM enhancement (skip if -y without model, skipLlm config, or all cached)
225284
const globalConfig = readConfig()
226-
if (successfulPkgs.length > 0 && !globalConfig.skipLlm && !(config.yes && !config.model)) {
285+
if (uncachedPkgs.length > 0 && !globalConfig.skipLlm && !(config.yes && !config.model)) {
227286
const llmConfig = await selectLlmConfig(config.model)
228287

229288
if (llmConfig?.promptOnly) {
230-
for (const pkg of successfulPkgs) {
289+
for (const pkg of uncachedPkgs) {
231290
const data = skillData.get(pkg)!
232291
const baseDir = resolveBaseDir(cwd, config.agent, config.global)
233292
const skillDir = join(baseDir, data.skillDirName)
@@ -251,21 +310,21 @@ export async function syncPackagesParallel(config: ParallelSyncConfig): Promise<
251310
else if (llmConfig) {
252311
p.log.step(getModelLabel(llmConfig.model))
253312
// Reset states for LLM phase
254-
for (const pkg of successfulPkgs) {
313+
for (const pkg of uncachedPkgs) {
255314
states.set(pkg, { name: pkg, status: 'pending', message: 'Waiting...' })
256315
}
257316
render()
258317

259318
const llmResults = await Promise.allSettled(
260-
successfulPkgs.map(pkg =>
319+
uncachedPkgs.map(pkg =>
261320
limit(() => enhanceWithLLM(pkg, skillData.get(pkg)!, { ...config, model: llmConfig.model }, cwd, update, llmConfig.sections, llmConfig.customPrompt)),
262321
),
263322
)
264323

265324
logUpdate.done()
266325

267326
const llmSucceeded = llmResults.filter(r => r.status === 'fulfilled').length
268-
p.log.success(`Enhanced ${llmSucceeded}/${successfulPkgs.length} skills with LLM`)
327+
p.log.success(`Enhanced ${llmSucceeded}/${uncachedPkgs.length} skills with LLM`)
269328
}
270329
}
271330

src/commands/sync.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import {
1616
linkSkillToAgents,
1717
portabilizePrompt,
1818
sanitizeName,
19+
SECTION_MERGE_ORDER,
1920
SECTION_OUTPUT_FILES,
21+
wrapSection,
2022
} from '../agent/index.ts'
2123
import {
2224
ensureCacheDir,
@@ -27,6 +29,7 @@ import {
2729
isCached,
2830
linkPkgNamed,
2931
listReferenceFiles,
32+
readCachedSection,
3033
resolvePkgDir,
3134
} from '../cache/index.ts'
3235
import { getInstalledGenerators, introLine, isInteractive, promptForAgent, resolveAgent, sharedArgs } from '../cli-helpers.ts'
@@ -519,9 +522,55 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
519522

520523
p.log.success(config.mode === 'update' ? `Updated skill: ${relative(cwd, skillDir)}` : `Created base skill: ${relative(cwd, skillDir)}`)
521524

522-
// Ask about LLM optimization (skip if -y flag, skipLlm config, or model already specified)
525+
// Check if all default sections are already cached (skip prompt entirely if so)
526+
const allSectionsCached = !config.force && DEFAULT_SECTIONS.every((s) => {
527+
const outputFile = SECTION_OUTPUT_FILES[s]
528+
return readCachedSection(packageName, version, outputFile) !== null
529+
})
530+
531+
if (allSectionsCached) {
532+
// Silently apply cached LLM content without prompting
533+
const cachedParts: string[] = []
534+
for (const s of SECTION_MERGE_ORDER) {
535+
if (!DEFAULT_SECTIONS.includes(s))
536+
continue
537+
const outputFile = SECTION_OUTPUT_FILES[s]
538+
const content = readCachedSection(packageName, version, outputFile)
539+
if (content)
540+
cachedParts.push(wrapSection(s, content))
541+
}
542+
const cachedBody = cachedParts.join('\n\n')
543+
544+
const skillMd = generateSkillMd({
545+
name: packageName,
546+
version,
547+
releasedAt: resolved.releasedAt,
548+
description: resolved.description,
549+
dependencies: resolved.dependencies,
550+
distTags: resolved.distTags,
551+
body: cachedBody,
552+
relatedSkills,
553+
hasIssues: resources.hasIssues,
554+
hasDiscussions: resources.hasDiscussions,
555+
hasReleases: resources.hasReleases,
556+
hasChangelog,
557+
docsType: resources.docsType,
558+
hasShippedDocs: shippedDocs,
559+
pkgFiles,
560+
generatedBy: 'cached',
561+
dirName: skillDirName,
562+
packages: allPackages.length > 1 ? allPackages : undefined,
563+
repoUrl: resolved.repoUrl,
564+
features,
565+
eject: isEject,
566+
})
567+
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
568+
p.log.success('Applied cached SKILL.md sections')
569+
}
570+
571+
// Ask about LLM optimization (skip if -y flag, skipLlm config, sections cached, or model already specified)
523572
const globalConfig = readConfig()
524-
if (!globalConfig.skipLlm && (!config.yes || config.model)) {
573+
if (!allSectionsCached && !globalConfig.skipLlm && (!config.yes || config.model)) {
525574
const llmConfig = await selectLlmConfig(config.model)
526575
if (llmConfig?.promptOnly) {
527576
writePromptFiles({

0 commit comments

Comments
 (0)