Merge pull request #709 from Momentum96/fix/skill-lazy-loading

fix(skill-loader): implement eager loading for skills
This commit is contained in:
Kenny
2026-01-12 22:50:31 -05:00
committed by GitHub

View File

@@ -63,7 +63,7 @@ async function loadSkillFromPath(
): Promise<LoadedSkill | null> {
try {
const content = await fs.readFile(skillPath, "utf-8")
const { data } = parseFrontmatter<SkillMetadata>(content)
const { data, body } = parseFrontmatter<SkillMetadata>(content)
const frontmatterMcp = parseSkillMcpConfigFromFrontmatter(content)
const mcpJsonMcp = await loadMcpJsonFromDir(resolvedPath)
const mcpConfig = mcpJsonMcp || frontmatterMcp
@@ -73,14 +73,7 @@ async function loadSkillFromPath(
const isOpencodeSource = scope === "opencode" || scope === "opencode-project"
const formattedDescription = `(${scope} - Skill) ${originalDescription}`
const lazyContent: LazyContentLoader = {
loaded: false,
content: undefined,
load: async () => {
if (!lazyContent.loaded) {
const fileContent = await fs.readFile(skillPath, "utf-8")
const { body } = parseFrontmatter<SkillMetadata>(fileContent)
lazyContent.content = `<skill-instruction>
const templateContent = `<skill-instruction>
Base directory for this skill: ${resolvedPath}/
File references (@path) in this skill are relative to this directory.
@@ -90,16 +83,20 @@ ${body.trim()}
<user-request>
$ARGUMENTS
</user-request>`
lazyContent.loaded = true
}
return lazyContent.content!
},
// RATIONALE: We read the file eagerly to ensure atomic consistency between
// metadata and body. We maintain the LazyContentLoader interface for
// compatibility, but the state is effectively eager.
const eagerLoader: LazyContentLoader = {
loaded: true,
content: templateContent,
load: async () => templateContent,
}
const definition: CommandDefinition = {
name: skillName,
description: formattedDescription,
template: "",
template: templateContent,
model: sanitizeModelField(data.model, isOpencodeSource ? "opencode" : "claude-code"),
agent: data.agent,
subtask: data.subtask,
@@ -117,7 +114,7 @@ $ARGUMENTS
metadata: data.metadata,
allowedTools: parseAllowedTools(data["allowed-tools"]),
mcpConfig,
lazyContent,
lazyContent: eagerLoader,
}
} catch {
return null