From 6f0be4a1cb794faf4e06d0cff8da179e9fce8919 Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Mon, 2 Feb 2026 16:00:38 +0800 Subject: [PATCH] feat(skills): implement progressive loading for reduced token usage Changed buildModelSkillsPrompt() to only output skill metadata (name + description) instead of full instructions. Full instructions are now loaded on-demand when a skill is triggered via the new buildSkillPromptForInjection() method. This reduces initial system prompt size significantly for projects with many skills. Co-Authored-By: Claude --- src/agent/skills/index.ts | 45 +++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/agent/skills/index.ts b/src/agent/skills/index.ts index 186f4790..73104f48 100644 --- a/src/agent/skills/index.ts +++ b/src/agent/skills/index.ts @@ -479,11 +479,13 @@ export class SkillManager { } /** - * Build skills prompt excluding user-only skills + * Build skills prompt excluding user-only skills (metadata only) * * Only includes skills that are model-invocable (disableModelInvocation !== true) + * Uses progressive loading: only outputs name + description, not full instructions + * Full instructions are loaded on-demand via getSkillInstructions() when a skill is triggered * - * @returns Formatted skill documentation for AI system prompt + * @returns Formatted skill metadata for AI system prompt */ buildModelSkillsPrompt(): string { this.ensureLoaded(); @@ -501,20 +503,45 @@ export class SkillManager { const parts: string[] = []; parts.push("# Available Skills\n"); - parts.push("You have access to the following skills:\n"); + parts.push("You have access to the following skills. When you need to use a skill, the full instructions will be provided.\n"); for (const [id, skill] of modelSkills) { const emoji = skill.frontmatter.metadata?.emoji ?? "🔧"; const name = skill.frontmatter.name; const desc = skill.frontmatter.description ?? "No description provided"; - parts.push(`## ${emoji} ${name} (${id})`); - parts.push(`${desc}\n`); + // Progressive loading: only output metadata, not full instructions + parts.push(`- ${emoji} **${name}** (\`${id}\`): ${desc}`); + } - if (skill.instructions) { - parts.push(skill.instructions); - parts.push(""); - } + parts.push(""); + return parts.join("\n"); + } + + /** + * Build full skill prompt for injection when a skill is triggered + * + * This is used for on-demand loading - when a skill is invoked, + * this method provides the complete instructions to inject into context + * + * @param skillId - Skill identifier + * @returns Formatted skill prompt with full instructions, or undefined if not found + */ + buildSkillPromptForInjection(skillId: string): string | undefined { + const skill = this.getSkill(skillId); + if (!skill) return undefined; + + const emoji = skill.frontmatter.metadata?.emoji ?? "🔧"; + const name = skill.frontmatter.name; + const desc = skill.frontmatter.description ?? "No description provided"; + + const parts: string[] = []; + parts.push(`# Skill: ${emoji} ${name}\n`); + parts.push(`${desc}\n`); + + if (skill.instructions) { + parts.push("## Instructions\n"); + parts.push(skill.instructions); } return parts.join("\n");