opencode-plugin-preload-skills 1.3.0 → 1.4.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/README.md CHANGED
@@ -86,6 +86,10 @@ A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads s
86
86
  { "skill": "react", "if": { "packageHasDependency": "react" } },
87
87
  { "skill": "prisma", "if": { "fileExists": "prisma/schema.prisma" } }
88
88
  ],
89
+ "skillSettings": {
90
+ "large-skill": { "useSummary": true },
91
+ "critical-skill": { "useSummary": false }
92
+ },
89
93
  "maxTokens": 10000,
90
94
  "useSummaries": false,
91
95
  "analytics": false,
@@ -105,8 +109,9 @@ A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads s
105
109
  | `contentTriggers` | `Record<string, string[]>` | `{}` | Map keywords to skills |
106
110
  | `groups` | `Record<string, string[]>` | `{}` | Define skill bundles |
107
111
  | `conditionalSkills` | `ConditionalSkill[]` | `[]` | Load if condition met |
112
+ | `skillSettings` | `Record<string, SkillSettings>` | `{}` | Per-skill settings |
108
113
  | `maxTokens` | `number` | `undefined` | Max tokens for all skills |
109
- | `useSummaries` | `boolean` | `false` | Use skill summaries |
114
+ | `useSummaries` | `boolean` | `false` | Use skill summaries (global) |
110
115
  | `analytics` | `boolean` | `false` | Track skill usage |
111
116
  | `persistAfterCompaction` | `boolean` | `true` | Keep skills after compaction |
112
117
  | `debug` | `boolean` | `false` | Enable debug logs |
@@ -252,6 +257,27 @@ Enable with:
252
257
 
253
258
  If no `summary` field, auto-generates from first paragraph.
254
259
 
260
+ ### Per-Skill Settings
261
+
262
+ Override global settings for specific skills:
263
+
264
+ ```json
265
+ {
266
+ "useSummaries": false,
267
+ "skillSettings": {
268
+ "large-reference": { "useSummary": true },
269
+ "critical-instructions": { "useSummary": false }
270
+ }
271
+ }
272
+ ```
273
+
274
+ **Available settings:**
275
+ - `useSummary` — Override global `useSummaries` for this skill
276
+
277
+ **Priority:** `skillSettings` > `useSummaries` (global)
278
+
279
+ This lets you use full content for critical skills while summarizing large reference materials.
280
+
255
281
  ### Usage Analytics
256
282
 
257
283
  Track which skills are loaded and how often:
package/dist/index.cjs CHANGED
@@ -126,12 +126,17 @@ function loadSkills(skillNames, projectDir) {
126
126
  }
127
127
  return skills;
128
128
  }
129
- function formatSkillsForInjection(skills, useSummaries = false) {
129
+ function formatSkillsForInjection(skills, options = false) {
130
130
  if (!Array.isArray(skills) || skills.length === 0) {
131
131
  return "";
132
132
  }
133
+ const opts = typeof options === "boolean" ? { useSummaries: options } : options;
134
+ const globalUseSummaries = opts.useSummaries ?? false;
135
+ const skillSettings = opts.skillSettings ?? {};
133
136
  const parts = skills.map((skill) => {
134
- const content = useSummaries && skill.summary ? skill.summary : skill.content;
137
+ const perSkillSetting = skillSettings[skill.name]?.useSummary;
138
+ const shouldUseSummary = perSkillSetting ?? globalUseSummaries;
139
+ const content = shouldUseSummary && skill.summary ? skill.summary : skill.content;
135
140
  return `<preloaded-skill name="${skill.name}">
136
141
  ${content}
137
142
  </preloaded-skill>`;
@@ -169,6 +174,7 @@ var DEFAULT_CONFIG = {
169
174
  contentTriggers: {},
170
175
  groups: {},
171
176
  conditionalSkills: [],
177
+ skillSettings: {},
172
178
  maxTokens: void 0,
173
179
  useSummaries: false,
174
180
  analytics: false,
@@ -204,6 +210,22 @@ function parseConditionalSkills(raw) {
204
210
  (item) => typeof item === "object" && item !== null && typeof item.skill === "string" && typeof item.if === "object"
205
211
  );
206
212
  }
213
+ function parseSkillSettings(raw) {
214
+ if (!raw || typeof raw !== "object") return {};
215
+ const result = {};
216
+ for (const [skillName, settings] of Object.entries(raw)) {
217
+ if (typeof settings === "object" && settings !== null) {
218
+ const parsed = {};
219
+ if ("useSummary" in settings && typeof settings.useSummary === "boolean") {
220
+ parsed.useSummary = settings.useSummary;
221
+ }
222
+ if (Object.keys(parsed).length > 0) {
223
+ result[skillName] = parsed;
224
+ }
225
+ }
226
+ }
227
+ return result;
228
+ }
207
229
  function loadConfigFile(projectDir) {
208
230
  const configPath = findConfigFile(projectDir);
209
231
  if (!configPath) {
@@ -220,6 +242,7 @@ function loadConfigFile(projectDir) {
220
242
  contentTriggers: parseStringArrayRecord(parsed.contentTriggers),
221
243
  groups: parseStringArrayRecord(parsed.groups),
222
244
  conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),
245
+ skillSettings: parseSkillSettings(parsed.skillSettings),
223
246
  maxTokens: typeof parsed.maxTokens === "number" ? parsed.maxTokens : void 0,
224
247
  useSummaries: typeof parsed.useSummaries === "boolean" ? parsed.useSummaries : void 0,
225
248
  analytics: typeof parsed.analytics === "boolean" ? parsed.analytics : void 0,
@@ -376,7 +399,7 @@ var PreloadSkillsPlugin = async (ctx) => {
376
399
  initialTokensUsed = result.tokensUsed;
377
400
  initialFormattedContent = formatSkillsForInjection(
378
401
  initialSkills,
379
- config.useSummaries
402
+ { useSummaries: config.useSummaries, skillSettings: config.skillSettings }
380
403
  );
381
404
  const loadedNames = initialSkills.map((s) => s.name);
382
405
  const missingNames = allInitialSkillNames.filter(
@@ -466,7 +489,7 @@ var PreloadSkillsPlugin = async (ctx) => {
466
489
  }
467
490
  const pending = pendingSkillInjections.get(input.sessionID);
468
491
  if (pending && pending.length > 0) {
469
- const formatted = formatSkillsForInjection(pending, config.useSummaries);
492
+ const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings });
470
493
  if (formatted) {
471
494
  contentToInject.push(formatted);
472
495
  log("info", "Injected triggered skills", {
@@ -518,7 +541,7 @@ ${firstTextPart.text}`;
518
541
  if (allLoadedSkills.length === 0) return;
519
542
  const formatted = formatSkillsForInjection(
520
543
  allLoadedSkills,
521
- config.useSummaries
544
+ { useSummaries: config.useSummaries, skillSettings: config.skillSettings }
522
545
  );
523
546
  output.context.push(
524
547
  `## Preloaded Skills
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/skill-loader.ts","../src/index.ts"],"names":["join","existsSync","readFileSync","homedir","dirname","mkdirSync","writeFileSync","extname"],"mappings":"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","file":"index.cjs","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\nexport function matchGlobPattern(filePath: string, pattern: string): boolean {\n let regexPattern = pattern\n .replace(/\\*\\*\\//g, \"\\x00DOUBLESTARSLASH\\x00\")\n .replace(/\\*\\*/g, \"\\x00DOUBLESTAR\\x00\")\n .replace(/\\*/g, \"\\x00SINGLESTAR\\x00\")\n .replace(/\\?/g, \"\\x00QUESTION\\x00\")\n \n regexPattern = regexPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n \n regexPattern = regexPattern\n .replace(/\\x00DOUBLESTARSLASH\\x00/g, \"(?:[^/]+/)*\")\n .replace(/\\x00DOUBLESTAR\\x00/g, \".*\")\n .replace(/\\x00SINGLESTAR\\x00/g, \"[^/]*\")\n .replace(/\\x00QUESTION\\x00/g, \"[^/]\")\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(filePath)\n}\n\nexport function matchesAnyPattern(\n filePath: string,\n patterns: string[]\n): boolean {\n return patterns.some((pattern) => matchGlobPattern(filePath, pattern))\n}\n\nexport function checkCondition(\n condition: { fileExists?: string; packageHasDependency?: string; envVar?: string },\n projectDir: string\n): boolean {\n if (condition.fileExists) {\n const fullPath = join(projectDir, condition.fileExists)\n if (!existsSync(fullPath)) return false\n }\n\n if (condition.packageHasDependency) {\n const packageJsonPath = join(projectDir, \"package.json\")\n if (!existsSync(packageJsonPath)) return false\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"))\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n }\n if (!deps[condition.packageHasDependency]) return false\n } catch {\n return false\n }\n }\n\n if (condition.envVar) {\n if (!process.env[condition.envVar]) return false\n }\n\n return true\n}\n\nexport function extractKeywords(text: string): string[] {\n const words = text.toLowerCase().match(/\\b[a-z]{3,}\\b/g) ?? []\n return [...new Set(words)]\n}\n\nexport function textContainsKeyword(text: string, keywords: string[]): boolean {\n const lowerText = text.toLowerCase()\n return keywords.some((kw) => lowerText.includes(kw.toLowerCase()))\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { ParsedSkill } from \"./types.js\"\nimport { estimateTokens } from \"./utils.js\"\n\nconst SKILL_FILENAME = \"SKILL.md\"\n\nconst SKILL_SEARCH_PATHS = [\n (dir: string) => join(dir, \".opencode\", \"skills\"),\n (dir: string) => join(dir, \".claude\", \"skills\"),\n () => join(homedir(), \".config\", \"opencode\", \"skills\"),\n () => join(homedir(), \".claude\", \"skills\"),\n]\n\nfunction findSkillFile(skillName: string, projectDir: string): string | null {\n for (const getPath of SKILL_SEARCH_PATHS) {\n const skillDir = getPath(projectDir)\n const skillPath = join(skillDir, skillName, SKILL_FILENAME)\n\n if (existsSync(skillPath)) {\n return skillPath\n }\n }\n return null\n}\n\ninterface FrontmatterData {\n name?: string\n description?: string\n summary?: string\n}\n\nfunction parseFrontmatter(content: string): FrontmatterData {\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)\n if (!frontmatterMatch?.[1]) {\n return {}\n }\n\n const frontmatter = frontmatterMatch[1]\n const result: FrontmatterData = {}\n\n const nameMatch = frontmatter.match(/^name:\\s*(.+)$/m)\n if (nameMatch?.[1]) {\n result.name = nameMatch[1].trim()\n }\n\n const descMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (descMatch?.[1]) {\n result.description = descMatch[1].trim()\n }\n\n const summaryMatch = frontmatter.match(/^summary:\\s*(.+)$/m)\n if (summaryMatch?.[1]) {\n result.summary = summaryMatch[1].trim()\n }\n\n return result\n}\n\nfunction extractAutoSummary(content: string, maxLength: number = 500): string {\n const withoutFrontmatter = content.replace(/^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n?/, \"\")\n \n const firstSection = withoutFrontmatter.split(/\\n##\\s/)[0] ?? \"\"\n const cleaned = firstSection\n .replace(/^#\\s+.+\\n?/, \"\")\n .replace(/\\n+/g, \" \")\n .trim()\n\n if (cleaned.length <= maxLength) return cleaned\n return cleaned.slice(0, maxLength).replace(/\\s+\\S*$/, \"\") + \"...\"\n}\n\nexport function loadSkill(skillName: string, projectDir: string): ParsedSkill | null {\n const filePath = findSkillFile(skillName, projectDir)\n\n if (!filePath) {\n return null\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\")\n const { name, description, summary } = parseFrontmatter(content)\n\n return {\n name: name ?? skillName,\n description: description ?? \"\",\n summary: summary ?? extractAutoSummary(content),\n content,\n filePath,\n tokenCount: estimateTokens(content),\n }\n } catch {\n return null\n }\n}\n\nexport function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[] {\n if (!Array.isArray(skillNames)) {\n return []\n }\n\n const skills: ParsedSkill[] = []\n\n for (const name of skillNames) {\n const skill = loadSkill(name, projectDir)\n if (skill) {\n skills.push(skill)\n }\n }\n\n return skills\n}\n\nexport function formatSkillsForInjection(\n skills: ParsedSkill[],\n useSummaries: boolean = false\n): string {\n if (!Array.isArray(skills) || skills.length === 0) {\n return \"\"\n }\n\n const parts = skills.map((skill) => {\n const content = useSummaries && skill.summary ? skill.summary : skill.content\n return `<preloaded-skill name=\"${skill.name}\">\\n${content}\\n</preloaded-skill>`\n })\n\n return `<preloaded-skills>\nThe following skills have been automatically loaded for this session:\n\n${parts.join(\"\\n\\n\")}\n</preloaded-skills>`\n}\n\nexport function calculateTotalTokens(skills: ParsedSkill[]): number {\n return skills.reduce((sum, skill) => sum + skill.tokenCount, 0)\n}\n\nexport function filterSkillsByTokenBudget(\n skills: ParsedSkill[],\n maxTokens: number\n): ParsedSkill[] {\n const result: ParsedSkill[] = []\n let totalTokens = 0\n\n for (const skill of skills) {\n if (totalTokens + skill.tokenCount <= maxTokens) {\n result.push(skill)\n totalTokens += skill.tokenCount\n }\n }\n\n return result\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\"\nimport { join, extname, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { Plugin, PluginInput } from \"@opencode-ai/plugin\"\nimport type { Event, UserMessage, Part } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillUsageStats,\n AnalyticsData,\n} from \"./types.js\"\nimport {\n loadSkills,\n formatSkillsForInjection,\n filterSkillsByTokenBudget,\n calculateTotalTokens,\n} from \"./skill-loader.js\"\nimport {\n checkCondition,\n matchGlobPattern,\n textContainsKeyword,\n} from \"./utils.js\"\n\nexport type { PreloadSkillsConfig, ParsedSkill }\nexport { loadSkills, formatSkillsForInjection }\n\nconst CONFIG_FILENAME = \"preload-skills.json\"\nconst ANALYTICS_FILENAME = \"preload-skills-analytics.json\"\nconst FILE_TOOLS = [\"read\", \"edit\", \"write\", \"glob\", \"grep\"]\n\nconst DEFAULT_CONFIG: PreloadSkillsConfig = {\n skills: [],\n fileTypeSkills: {},\n agentSkills: {},\n pathPatterns: {},\n contentTriggers: {},\n groups: {},\n conditionalSkills: [],\n maxTokens: undefined,\n useSummaries: false,\n analytics: false,\n persistAfterCompaction: true,\n debug: false,\n}\n\nfunction findConfigFile(projectDir: string): string | null {\n const locations = [\n join(projectDir, \".opencode\", CONFIG_FILENAME),\n join(projectDir, CONFIG_FILENAME),\n join(homedir(), \".config\", \"opencode\", CONFIG_FILENAME),\n ]\n\n for (const path of locations) {\n if (existsSync(path)) {\n return path\n }\n }\n return null\n}\n\nfunction parseStringArrayRecord(raw: unknown): Record<string, string[]> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, string[]> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (Array.isArray(value)) {\n result[key] = value.filter((v) => typeof v === \"string\")\n }\n }\n return result\n}\n\nfunction parseConditionalSkills(raw: unknown): ConditionalSkill[] {\n if (!Array.isArray(raw)) return []\n\n return raw.filter(\n (item): item is ConditionalSkill =>\n typeof item === \"object\" &&\n item !== null &&\n typeof item.skill === \"string\" &&\n typeof item.if === \"object\"\n )\n}\n\nfunction loadConfigFile(projectDir: string): Partial<PreloadSkillsConfig> {\n const configPath = findConfigFile(projectDir)\n if (!configPath) {\n return {}\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\")\n const parsed = JSON.parse(content) as Record<string, unknown>\n\n return {\n skills: Array.isArray(parsed.skills) ? parsed.skills : [],\n fileTypeSkills: parseStringArrayRecord(parsed.fileTypeSkills),\n agentSkills: parseStringArrayRecord(parsed.agentSkills),\n pathPatterns: parseStringArrayRecord(parsed.pathPatterns),\n contentTriggers: parseStringArrayRecord(parsed.contentTriggers),\n groups: parseStringArrayRecord(parsed.groups),\n conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),\n maxTokens:\n typeof parsed.maxTokens === \"number\" ? parsed.maxTokens : undefined,\n useSummaries:\n typeof parsed.useSummaries === \"boolean\"\n ? parsed.useSummaries\n : undefined,\n analytics:\n typeof parsed.analytics === \"boolean\" ? parsed.analytics : undefined,\n persistAfterCompaction:\n typeof parsed.persistAfterCompaction === \"boolean\"\n ? parsed.persistAfterCompaction\n : undefined,\n debug: typeof parsed.debug === \"boolean\" ? parsed.debug : undefined,\n }\n } catch {\n return {}\n }\n}\n\nfunction getFilePathFromArgs(args: Record<string, unknown>): string | null {\n if (typeof args.filePath === \"string\") return args.filePath\n if (typeof args.path === \"string\") return args.path\n if (typeof args.file === \"string\") return args.file\n return null\n}\n\nfunction getSkillsForExtension(\n ext: string,\n fileTypeSkills: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(fileTypeSkills)) {\n const extensions = pattern.split(\",\").map((e) => e.trim().toLowerCase())\n if (extensions.includes(ext.toLowerCase())) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction getSkillsForPath(\n filePath: string,\n pathPatterns: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(pathPatterns)) {\n if (matchGlobPattern(filePath, pattern)) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction resolveSkillGroups(\n skillNames: string[],\n groups: Record<string, string[]>\n): string[] {\n const resolved: string[] = []\n\n for (const name of skillNames) {\n if (name.startsWith(\"@\") && groups[name.slice(1)]) {\n resolved.push(...groups[name.slice(1)]!)\n } else {\n resolved.push(name)\n }\n }\n\n return [...new Set(resolved)]\n}\n\nexport const PreloadSkillsPlugin: Plugin = async (ctx: PluginInput) => {\n const sessionStates = new Map<string, SessionState>()\n const analyticsData = new Map<string, AnalyticsData>()\n\n const fileConfig = loadConfigFile(ctx.directory)\n const config: PreloadSkillsConfig = {\n ...DEFAULT_CONFIG,\n ...fileConfig,\n }\n\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: Record<string, unknown>\n ) => {\n if (level === \"debug\" && !config.debug) return\n\n ctx.client.app.log({\n body: {\n service: \"preload-skills\",\n level,\n message,\n extra,\n },\n })\n }\n\n const trackSkillUsage = (\n sessionID: string,\n skillName: string,\n triggerType: SkillUsageStats[\"triggerType\"]\n ) => {\n if (!config.analytics) return\n\n if (!analyticsData.has(sessionID)) {\n analyticsData.set(sessionID, {\n sessionId: sessionID,\n skillUsage: new Map(),\n })\n }\n\n const data = analyticsData.get(sessionID)!\n const now = Date.now()\n\n if (data.skillUsage.has(skillName)) {\n const stats = data.skillUsage.get(skillName)!\n stats.loadCount++\n stats.lastLoaded = now\n } else {\n data.skillUsage.set(skillName, {\n skillName,\n loadCount: 1,\n triggerType,\n firstLoaded: now,\n lastLoaded: now,\n })\n }\n }\n\n const saveAnalytics = () => {\n if (!config.analytics) return\n\n try {\n const analyticsPath = join(ctx.directory, \".opencode\", ANALYTICS_FILENAME)\n const dir = dirname(analyticsPath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n const serializable: Record<string, unknown> = {}\n for (const [sessionId, data] of analyticsData) {\n serializable[sessionId] = {\n sessionId: data.sessionId,\n skillUsage: Object.fromEntries(data.skillUsage),\n }\n }\n\n writeFileSync(analyticsPath, JSON.stringify(serializable, null, 2))\n } catch {\n log(\"warn\", \"Failed to save analytics\")\n }\n }\n\n const skillCache = new Map<string, ParsedSkill>()\n\n const loadSkillsWithBudget = (\n skillNames: string[],\n currentTokens: number,\n triggerType: SkillUsageStats[\"triggerType\"],\n sessionID: string\n ): { skills: ParsedSkill[]; tokensUsed: number } => {\n const resolved = resolveSkillGroups(skillNames, config.groups ?? {})\n let skills = loadSkills(resolved, ctx.directory)\n\n for (const skill of skills) {\n skillCache.set(skill.name, skill)\n }\n\n if (config.maxTokens) {\n const remainingBudget = config.maxTokens - currentTokens\n skills = filterSkillsByTokenBudget(skills, remainingBudget)\n }\n\n for (const skill of skills) {\n trackSkillUsage(sessionID, skill.name, triggerType)\n }\n\n return {\n skills,\n tokensUsed: calculateTotalTokens(skills),\n }\n }\n\n const resolveConditionalSkills = (): string[] => {\n if (!config.conditionalSkills?.length) return []\n\n const resolved: string[] = []\n for (const { skill, if: condition } of config.conditionalSkills) {\n if (checkCondition(condition, ctx.directory)) {\n resolved.push(skill)\n }\n }\n\n return resolved\n }\n\n let initialSkills: ParsedSkill[] = []\n let initialFormattedContent = \"\"\n let initialTokensUsed = 0\n\n const allInitialSkillNames = [\n ...config.skills,\n ...resolveConditionalSkills(),\n ]\n\n if (allInitialSkillNames.length > 0) {\n const result = loadSkillsWithBudget(\n allInitialSkillNames,\n 0,\n \"initial\",\n \"__init__\"\n )\n initialSkills = result.skills\n initialTokensUsed = result.tokensUsed\n initialFormattedContent = formatSkillsForInjection(\n initialSkills,\n config.useSummaries\n )\n\n const loadedNames = initialSkills.map((s) => s.name)\n const missingNames = allInitialSkillNames.filter(\n (s) => !loadedNames.includes(s) && !s.startsWith(\"@\")\n )\n\n log(\"info\", `Loaded ${initialSkills.length} initial skills`, {\n loaded: loadedNames,\n tokens: initialTokensUsed,\n missing: missingNames.length > 0 ? missingNames : undefined,\n })\n }\n\n const hasTriggeredSkills =\n Object.keys(config.fileTypeSkills ?? {}).length > 0 ||\n Object.keys(config.agentSkills ?? {}).length > 0 ||\n Object.keys(config.pathPatterns ?? {}).length > 0 ||\n Object.keys(config.contentTriggers ?? {}).length > 0\n\n if (allInitialSkillNames.length === 0 && !hasTriggeredSkills) {\n log(\"warn\", \"No skills configured. Create .opencode/preload-skills.json\")\n }\n\n const getSessionState = (sessionID: string): SessionState => {\n if (!sessionStates.has(sessionID)) {\n sessionStates.set(sessionID, {\n initialSkillsInjected: false,\n loadedSkills: new Set(initialSkills.map((s) => s.name)),\n totalTokensUsed: initialTokensUsed,\n })\n }\n return sessionStates.get(sessionID)!\n }\n\n const pendingSkillInjections = new Map<string, ParsedSkill[]>()\n\n const queueSkillsForInjection = (\n sessionID: string,\n skillNames: string[],\n triggerType: SkillUsageStats[\"triggerType\"],\n state: SessionState\n ) => {\n const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name))\n if (newSkillNames.length === 0) return\n\n const result = loadSkillsWithBudget(\n newSkillNames,\n state.totalTokensUsed,\n triggerType,\n sessionID\n )\n\n if (result.skills.length > 0) {\n for (const skill of result.skills) {\n state.loadedSkills.add(skill.name)\n }\n state.totalTokensUsed += result.tokensUsed\n\n const existing = pendingSkillInjections.get(sessionID) ?? []\n pendingSkillInjections.set(sessionID, [...existing, ...result.skills])\n\n log(\"debug\", `Queued ${triggerType} skills for injection`, {\n sessionID,\n skills: result.skills.map((s) => s.name),\n tokens: result.tokensUsed,\n })\n }\n }\n\n return {\n \"chat.message\": async (\n input: {\n sessionID: string\n agent?: string\n model?: { providerID: string; modelID: string }\n messageID?: string\n variant?: string\n },\n output: { message: UserMessage; parts: Part[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const firstTextPart = output.parts.find((p) => p.type === \"text\")\n if (!firstTextPart || !(\"text\" in firstTextPart)) return\n\n const messageText = firstTextPart.text\n\n if (input.agent && config.agentSkills?.[input.agent]) {\n queueSkillsForInjection(\n input.sessionID,\n config.agentSkills[input.agent]!,\n \"agent\",\n state\n )\n }\n\n if (config.contentTriggers) {\n for (const [keyword, skillNames] of Object.entries(\n config.contentTriggers\n )) {\n if (textContainsKeyword(messageText, [keyword])) {\n queueSkillsForInjection(\n input.sessionID,\n skillNames,\n \"content\",\n state\n )\n }\n }\n }\n\n const contentToInject: string[] = []\n\n if (!state.initialSkillsInjected && initialFormattedContent) {\n contentToInject.push(initialFormattedContent)\n state.initialSkillsInjected = true\n log(\"info\", \"Injected initial preloaded skills\", {\n sessionID: input.sessionID,\n skills: initialSkills.map((s) => s.name),\n })\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n const formatted = formatSkillsForInjection(pending, config.useSummaries)\n if (formatted) {\n contentToInject.push(formatted)\n log(\"info\", \"Injected triggered skills\", {\n sessionID: input.sessionID,\n skills: pending.map((s) => s.name),\n })\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (contentToInject.length > 0) {\n firstTextPart.text = `${contentToInject.join(\"\\n\\n\")}\\n\\n---\\n\\n${firstTextPart.text}`\n }\n },\n\n \"tool.execute.after\": async (\n input: {\n tool: string\n sessionID: string\n callID: string\n },\n _output: {\n title: string\n output: string\n metadata: unknown\n }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n\n const toolArgs = (_output.metadata as { args?: Record<string, unknown> })\n ?.args\n if (!toolArgs) return\n\n const filePath = getFilePathFromArgs(toolArgs)\n if (!filePath) return\n\n const ext = extname(filePath)\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, extSkills, \"fileType\", state)\n }\n }\n\n if (config.pathPatterns) {\n const pathSkills = getSkillsForPath(filePath, config.pathPatterns)\n if (pathSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, pathSkills, \"path\", state)\n }\n }\n },\n\n \"experimental.session.compacting\": async (\n input: { sessionID: string },\n output: { context: string[]; prompt?: string }\n ): Promise<void> => {\n if (!config.persistAfterCompaction) return\n\n const state = sessionStates.get(input.sessionID)\n if (!state || state.loadedSkills.size === 0) return\n\n const allLoadedSkills: ParsedSkill[] = []\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill) allLoadedSkills.push(skill)\n }\n\n if (allLoadedSkills.length === 0) return\n\n const formatted = formatSkillsForInjection(\n allLoadedSkills,\n config.useSummaries\n )\n output.context.push(\n `## Preloaded Skills\\n\\nThe following skills were loaded during this session and should persist:\\n\\n${formatted}`\n )\n\n state.initialSkillsInjected = false\n\n log(\"info\", \"Added all loaded skills to compaction context\", {\n sessionID: input.sessionID,\n skillCount: allLoadedSkills.length,\n })\n\n saveAnalytics()\n },\n\n event: async ({ event }: { event: Event }): Promise<void> => {\n if (\n event.type === \"session.deleted\" &&\n \"sessionID\" in event.properties\n ) {\n const sessionID = event.properties.sessionID as string\n sessionStates.delete(sessionID)\n pendingSkillInjections.delete(sessionID)\n analyticsData.delete(sessionID)\n log(\"debug\", \"Cleaned up session state\", { sessionID })\n saveAnalytics()\n }\n },\n }\n}\n\nexport default PreloadSkillsPlugin\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/skill-loader.ts","../src/index.ts"],"names":["join","existsSync","readFileSync","homedir","dirname","mkdirSync","writeFileSync","extname"],"mappings":"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","file":"index.cjs","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\nexport function matchGlobPattern(filePath: string, pattern: string): boolean {\n let regexPattern = pattern\n .replace(/\\*\\*\\//g, \"\\x00DOUBLESTARSLASH\\x00\")\n .replace(/\\*\\*/g, \"\\x00DOUBLESTAR\\x00\")\n .replace(/\\*/g, \"\\x00SINGLESTAR\\x00\")\n .replace(/\\?/g, \"\\x00QUESTION\\x00\")\n \n regexPattern = regexPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n \n regexPattern = regexPattern\n .replace(/\\x00DOUBLESTARSLASH\\x00/g, \"(?:[^/]+/)*\")\n .replace(/\\x00DOUBLESTAR\\x00/g, \".*\")\n .replace(/\\x00SINGLESTAR\\x00/g, \"[^/]*\")\n .replace(/\\x00QUESTION\\x00/g, \"[^/]\")\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(filePath)\n}\n\nexport function matchesAnyPattern(\n filePath: string,\n patterns: string[]\n): boolean {\n return patterns.some((pattern) => matchGlobPattern(filePath, pattern))\n}\n\nexport function checkCondition(\n condition: { fileExists?: string; packageHasDependency?: string; envVar?: string },\n projectDir: string\n): boolean {\n if (condition.fileExists) {\n const fullPath = join(projectDir, condition.fileExists)\n if (!existsSync(fullPath)) return false\n }\n\n if (condition.packageHasDependency) {\n const packageJsonPath = join(projectDir, \"package.json\")\n if (!existsSync(packageJsonPath)) return false\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"))\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n }\n if (!deps[condition.packageHasDependency]) return false\n } catch {\n return false\n }\n }\n\n if (condition.envVar) {\n if (!process.env[condition.envVar]) return false\n }\n\n return true\n}\n\nexport function extractKeywords(text: string): string[] {\n const words = text.toLowerCase().match(/\\b[a-z]{3,}\\b/g) ?? []\n return [...new Set(words)]\n}\n\nexport function textContainsKeyword(text: string, keywords: string[]): boolean {\n const lowerText = text.toLowerCase()\n return keywords.some((kw) => lowerText.includes(kw.toLowerCase()))\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { ParsedSkill, SkillSettings } from \"./types.js\"\nimport { estimateTokens } from \"./utils.js\"\n\nconst SKILL_FILENAME = \"SKILL.md\"\n\nconst SKILL_SEARCH_PATHS = [\n (dir: string) => join(dir, \".opencode\", \"skills\"),\n (dir: string) => join(dir, \".claude\", \"skills\"),\n () => join(homedir(), \".config\", \"opencode\", \"skills\"),\n () => join(homedir(), \".claude\", \"skills\"),\n]\n\nfunction findSkillFile(skillName: string, projectDir: string): string | null {\n for (const getPath of SKILL_SEARCH_PATHS) {\n const skillDir = getPath(projectDir)\n const skillPath = join(skillDir, skillName, SKILL_FILENAME)\n\n if (existsSync(skillPath)) {\n return skillPath\n }\n }\n return null\n}\n\ninterface FrontmatterData {\n name?: string\n description?: string\n summary?: string\n}\n\nfunction parseFrontmatter(content: string): FrontmatterData {\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)\n if (!frontmatterMatch?.[1]) {\n return {}\n }\n\n const frontmatter = frontmatterMatch[1]\n const result: FrontmatterData = {}\n\n const nameMatch = frontmatter.match(/^name:\\s*(.+)$/m)\n if (nameMatch?.[1]) {\n result.name = nameMatch[1].trim()\n }\n\n const descMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (descMatch?.[1]) {\n result.description = descMatch[1].trim()\n }\n\n const summaryMatch = frontmatter.match(/^summary:\\s*(.+)$/m)\n if (summaryMatch?.[1]) {\n result.summary = summaryMatch[1].trim()\n }\n\n return result\n}\n\nfunction extractAutoSummary(content: string, maxLength: number = 500): string {\n const withoutFrontmatter = content.replace(/^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n?/, \"\")\n \n const firstSection = withoutFrontmatter.split(/\\n##\\s/)[0] ?? \"\"\n const cleaned = firstSection\n .replace(/^#\\s+.+\\n?/, \"\")\n .replace(/\\n+/g, \" \")\n .trim()\n\n if (cleaned.length <= maxLength) return cleaned\n return cleaned.slice(0, maxLength).replace(/\\s+\\S*$/, \"\") + \"...\"\n}\n\nexport function loadSkill(skillName: string, projectDir: string): ParsedSkill | null {\n const filePath = findSkillFile(skillName, projectDir)\n\n if (!filePath) {\n return null\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\")\n const { name, description, summary } = parseFrontmatter(content)\n\n return {\n name: name ?? skillName,\n description: description ?? \"\",\n summary: summary ?? extractAutoSummary(content),\n content,\n filePath,\n tokenCount: estimateTokens(content),\n }\n } catch {\n return null\n }\n}\n\nexport function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[] {\n if (!Array.isArray(skillNames)) {\n return []\n }\n\n const skills: ParsedSkill[] = []\n\n for (const name of skillNames) {\n const skill = loadSkill(name, projectDir)\n if (skill) {\n skills.push(skill)\n }\n }\n\n return skills\n}\n\nexport interface FormatOptions {\n useSummaries?: boolean\n skillSettings?: Record<string, SkillSettings>\n}\n\nexport function formatSkillsForInjection(\n skills: ParsedSkill[],\n options: boolean | FormatOptions = false\n): string {\n if (!Array.isArray(skills) || skills.length === 0) {\n return \"\"\n }\n\n const opts: FormatOptions = typeof options === \"boolean\" \n ? { useSummaries: options } \n : options\n \n const globalUseSummaries = opts.useSummaries ?? false\n const skillSettings = opts.skillSettings ?? {}\n\n const parts = skills.map((skill) => {\n const perSkillSetting = skillSettings[skill.name]?.useSummary\n const shouldUseSummary = perSkillSetting ?? globalUseSummaries\n const content = shouldUseSummary && skill.summary ? skill.summary : skill.content\n return `<preloaded-skill name=\"${skill.name}\">\\n${content}\\n</preloaded-skill>`\n })\n\n return `<preloaded-skills>\nThe following skills have been automatically loaded for this session:\n\n${parts.join(\"\\n\\n\")}\n</preloaded-skills>`\n}\n\nexport function calculateTotalTokens(skills: ParsedSkill[]): number {\n return skills.reduce((sum, skill) => sum + skill.tokenCount, 0)\n}\n\nexport function filterSkillsByTokenBudget(\n skills: ParsedSkill[],\n maxTokens: number\n): ParsedSkill[] {\n const result: ParsedSkill[] = []\n let totalTokens = 0\n\n for (const skill of skills) {\n if (totalTokens + skill.tokenCount <= maxTokens) {\n result.push(skill)\n totalTokens += skill.tokenCount\n }\n }\n\n return result\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\"\nimport { join, extname, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { Plugin, PluginInput } from \"@opencode-ai/plugin\"\nimport type { Event, UserMessage, Part } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillSettings,\n SkillUsageStats,\n AnalyticsData,\n} from \"./types.js\"\nimport {\n loadSkills,\n formatSkillsForInjection,\n filterSkillsByTokenBudget,\n calculateTotalTokens,\n} from \"./skill-loader.js\"\nimport {\n checkCondition,\n matchGlobPattern,\n textContainsKeyword,\n} from \"./utils.js\"\n\nexport type { PreloadSkillsConfig, ParsedSkill }\nexport { loadSkills, formatSkillsForInjection }\n\nconst CONFIG_FILENAME = \"preload-skills.json\"\nconst ANALYTICS_FILENAME = \"preload-skills-analytics.json\"\nconst FILE_TOOLS = [\"read\", \"edit\", \"write\", \"glob\", \"grep\"]\n\nconst DEFAULT_CONFIG: PreloadSkillsConfig = {\n skills: [],\n fileTypeSkills: {},\n agentSkills: {},\n pathPatterns: {},\n contentTriggers: {},\n groups: {},\n conditionalSkills: [],\n skillSettings: {},\n maxTokens: undefined,\n useSummaries: false,\n analytics: false,\n persistAfterCompaction: true,\n debug: false,\n}\n\nfunction findConfigFile(projectDir: string): string | null {\n const locations = [\n join(projectDir, \".opencode\", CONFIG_FILENAME),\n join(projectDir, CONFIG_FILENAME),\n join(homedir(), \".config\", \"opencode\", CONFIG_FILENAME),\n ]\n\n for (const path of locations) {\n if (existsSync(path)) {\n return path\n }\n }\n return null\n}\n\nfunction parseStringArrayRecord(raw: unknown): Record<string, string[]> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, string[]> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (Array.isArray(value)) {\n result[key] = value.filter((v) => typeof v === \"string\")\n }\n }\n return result\n}\n\nfunction parseConditionalSkills(raw: unknown): ConditionalSkill[] {\n if (!Array.isArray(raw)) return []\n\n return raw.filter(\n (item): item is ConditionalSkill =>\n typeof item === \"object\" &&\n item !== null &&\n typeof item.skill === \"string\" &&\n typeof item.if === \"object\"\n )\n}\n\nfunction parseSkillSettings(raw: unknown): Record<string, SkillSettings> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, SkillSettings> = {}\n for (const [skillName, settings] of Object.entries(raw)) {\n if (typeof settings === \"object\" && settings !== null) {\n const parsed: SkillSettings = {}\n if (\"useSummary\" in settings && typeof settings.useSummary === \"boolean\") {\n parsed.useSummary = settings.useSummary\n }\n if (Object.keys(parsed).length > 0) {\n result[skillName] = parsed\n }\n }\n }\n return result\n}\n\nfunction loadConfigFile(projectDir: string): Partial<PreloadSkillsConfig> {\n const configPath = findConfigFile(projectDir)\n if (!configPath) {\n return {}\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\")\n const parsed = JSON.parse(content) as Record<string, unknown>\n\n return {\n skills: Array.isArray(parsed.skills) ? parsed.skills : [],\n fileTypeSkills: parseStringArrayRecord(parsed.fileTypeSkills),\n agentSkills: parseStringArrayRecord(parsed.agentSkills),\n pathPatterns: parseStringArrayRecord(parsed.pathPatterns),\n contentTriggers: parseStringArrayRecord(parsed.contentTriggers),\n groups: parseStringArrayRecord(parsed.groups),\n conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),\n skillSettings: parseSkillSettings(parsed.skillSettings),\n maxTokens:\n typeof parsed.maxTokens === \"number\" ? parsed.maxTokens : undefined,\n useSummaries:\n typeof parsed.useSummaries === \"boolean\"\n ? parsed.useSummaries\n : undefined,\n analytics:\n typeof parsed.analytics === \"boolean\" ? parsed.analytics : undefined,\n persistAfterCompaction:\n typeof parsed.persistAfterCompaction === \"boolean\"\n ? parsed.persistAfterCompaction\n : undefined,\n debug: typeof parsed.debug === \"boolean\" ? parsed.debug : undefined,\n }\n } catch {\n return {}\n }\n}\n\nfunction getFilePathFromArgs(args: Record<string, unknown>): string | null {\n if (typeof args.filePath === \"string\") return args.filePath\n if (typeof args.path === \"string\") return args.path\n if (typeof args.file === \"string\") return args.file\n return null\n}\n\nfunction getSkillsForExtension(\n ext: string,\n fileTypeSkills: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(fileTypeSkills)) {\n const extensions = pattern.split(\",\").map((e) => e.trim().toLowerCase())\n if (extensions.includes(ext.toLowerCase())) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction getSkillsForPath(\n filePath: string,\n pathPatterns: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(pathPatterns)) {\n if (matchGlobPattern(filePath, pattern)) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction resolveSkillGroups(\n skillNames: string[],\n groups: Record<string, string[]>\n): string[] {\n const resolved: string[] = []\n\n for (const name of skillNames) {\n if (name.startsWith(\"@\") && groups[name.slice(1)]) {\n resolved.push(...groups[name.slice(1)]!)\n } else {\n resolved.push(name)\n }\n }\n\n return [...new Set(resolved)]\n}\n\nexport const PreloadSkillsPlugin: Plugin = async (ctx: PluginInput) => {\n const sessionStates = new Map<string, SessionState>()\n const analyticsData = new Map<string, AnalyticsData>()\n\n const fileConfig = loadConfigFile(ctx.directory)\n const config: PreloadSkillsConfig = {\n ...DEFAULT_CONFIG,\n ...fileConfig,\n }\n\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: Record<string, unknown>\n ) => {\n if (level === \"debug\" && !config.debug) return\n\n ctx.client.app.log({\n body: {\n service: \"preload-skills\",\n level,\n message,\n extra,\n },\n })\n }\n\n const trackSkillUsage = (\n sessionID: string,\n skillName: string,\n triggerType: SkillUsageStats[\"triggerType\"]\n ) => {\n if (!config.analytics) return\n\n if (!analyticsData.has(sessionID)) {\n analyticsData.set(sessionID, {\n sessionId: sessionID,\n skillUsage: new Map(),\n })\n }\n\n const data = analyticsData.get(sessionID)!\n const now = Date.now()\n\n if (data.skillUsage.has(skillName)) {\n const stats = data.skillUsage.get(skillName)!\n stats.loadCount++\n stats.lastLoaded = now\n } else {\n data.skillUsage.set(skillName, {\n skillName,\n loadCount: 1,\n triggerType,\n firstLoaded: now,\n lastLoaded: now,\n })\n }\n }\n\n const saveAnalytics = () => {\n if (!config.analytics) return\n\n try {\n const analyticsPath = join(ctx.directory, \".opencode\", ANALYTICS_FILENAME)\n const dir = dirname(analyticsPath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n const serializable: Record<string, unknown> = {}\n for (const [sessionId, data] of analyticsData) {\n serializable[sessionId] = {\n sessionId: data.sessionId,\n skillUsage: Object.fromEntries(data.skillUsage),\n }\n }\n\n writeFileSync(analyticsPath, JSON.stringify(serializable, null, 2))\n } catch {\n log(\"warn\", \"Failed to save analytics\")\n }\n }\n\n const skillCache = new Map<string, ParsedSkill>()\n\n const loadSkillsWithBudget = (\n skillNames: string[],\n currentTokens: number,\n triggerType: SkillUsageStats[\"triggerType\"],\n sessionID: string\n ): { skills: ParsedSkill[]; tokensUsed: number } => {\n const resolved = resolveSkillGroups(skillNames, config.groups ?? {})\n let skills = loadSkills(resolved, ctx.directory)\n\n for (const skill of skills) {\n skillCache.set(skill.name, skill)\n }\n\n if (config.maxTokens) {\n const remainingBudget = config.maxTokens - currentTokens\n skills = filterSkillsByTokenBudget(skills, remainingBudget)\n }\n\n for (const skill of skills) {\n trackSkillUsage(sessionID, skill.name, triggerType)\n }\n\n return {\n skills,\n tokensUsed: calculateTotalTokens(skills),\n }\n }\n\n const resolveConditionalSkills = (): string[] => {\n if (!config.conditionalSkills?.length) return []\n\n const resolved: string[] = []\n for (const { skill, if: condition } of config.conditionalSkills) {\n if (checkCondition(condition, ctx.directory)) {\n resolved.push(skill)\n }\n }\n\n return resolved\n }\n\n let initialSkills: ParsedSkill[] = []\n let initialFormattedContent = \"\"\n let initialTokensUsed = 0\n\n const allInitialSkillNames = [\n ...config.skills,\n ...resolveConditionalSkills(),\n ]\n\n if (allInitialSkillNames.length > 0) {\n const result = loadSkillsWithBudget(\n allInitialSkillNames,\n 0,\n \"initial\",\n \"__init__\"\n )\n initialSkills = result.skills\n initialTokensUsed = result.tokensUsed\n initialFormattedContent = formatSkillsForInjection(\n initialSkills,\n { useSummaries: config.useSummaries, skillSettings: config.skillSettings }\n )\n\n const loadedNames = initialSkills.map((s) => s.name)\n const missingNames = allInitialSkillNames.filter(\n (s) => !loadedNames.includes(s) && !s.startsWith(\"@\")\n )\n\n log(\"info\", `Loaded ${initialSkills.length} initial skills`, {\n loaded: loadedNames,\n tokens: initialTokensUsed,\n missing: missingNames.length > 0 ? missingNames : undefined,\n })\n }\n\n const hasTriggeredSkills =\n Object.keys(config.fileTypeSkills ?? {}).length > 0 ||\n Object.keys(config.agentSkills ?? {}).length > 0 ||\n Object.keys(config.pathPatterns ?? {}).length > 0 ||\n Object.keys(config.contentTriggers ?? {}).length > 0\n\n if (allInitialSkillNames.length === 0 && !hasTriggeredSkills) {\n log(\"warn\", \"No skills configured. Create .opencode/preload-skills.json\")\n }\n\n const getSessionState = (sessionID: string): SessionState => {\n if (!sessionStates.has(sessionID)) {\n sessionStates.set(sessionID, {\n initialSkillsInjected: false,\n loadedSkills: new Set(initialSkills.map((s) => s.name)),\n totalTokensUsed: initialTokensUsed,\n })\n }\n return sessionStates.get(sessionID)!\n }\n\n const pendingSkillInjections = new Map<string, ParsedSkill[]>()\n\n const queueSkillsForInjection = (\n sessionID: string,\n skillNames: string[],\n triggerType: SkillUsageStats[\"triggerType\"],\n state: SessionState\n ) => {\n const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name))\n if (newSkillNames.length === 0) return\n\n const result = loadSkillsWithBudget(\n newSkillNames,\n state.totalTokensUsed,\n triggerType,\n sessionID\n )\n\n if (result.skills.length > 0) {\n for (const skill of result.skills) {\n state.loadedSkills.add(skill.name)\n }\n state.totalTokensUsed += result.tokensUsed\n\n const existing = pendingSkillInjections.get(sessionID) ?? []\n pendingSkillInjections.set(sessionID, [...existing, ...result.skills])\n\n log(\"debug\", `Queued ${triggerType} skills for injection`, {\n sessionID,\n skills: result.skills.map((s) => s.name),\n tokens: result.tokensUsed,\n })\n }\n }\n\n return {\n \"chat.message\": async (\n input: {\n sessionID: string\n agent?: string\n model?: { providerID: string; modelID: string }\n messageID?: string\n variant?: string\n },\n output: { message: UserMessage; parts: Part[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const firstTextPart = output.parts.find((p) => p.type === \"text\")\n if (!firstTextPart || !(\"text\" in firstTextPart)) return\n\n const messageText = firstTextPart.text\n\n if (input.agent && config.agentSkills?.[input.agent]) {\n queueSkillsForInjection(\n input.sessionID,\n config.agentSkills[input.agent]!,\n \"agent\",\n state\n )\n }\n\n if (config.contentTriggers) {\n for (const [keyword, skillNames] of Object.entries(\n config.contentTriggers\n )) {\n if (textContainsKeyword(messageText, [keyword])) {\n queueSkillsForInjection(\n input.sessionID,\n skillNames,\n \"content\",\n state\n )\n }\n }\n }\n\n const contentToInject: string[] = []\n\n if (!state.initialSkillsInjected && initialFormattedContent) {\n contentToInject.push(initialFormattedContent)\n state.initialSkillsInjected = true\n log(\"info\", \"Injected initial preloaded skills\", {\n sessionID: input.sessionID,\n skills: initialSkills.map((s) => s.name),\n })\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings })\n if (formatted) {\n contentToInject.push(formatted)\n log(\"info\", \"Injected triggered skills\", {\n sessionID: input.sessionID,\n skills: pending.map((s) => s.name),\n })\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (contentToInject.length > 0) {\n firstTextPart.text = `${contentToInject.join(\"\\n\\n\")}\\n\\n---\\n\\n${firstTextPart.text}`\n }\n },\n\n \"tool.execute.after\": async (\n input: {\n tool: string\n sessionID: string\n callID: string\n },\n _output: {\n title: string\n output: string\n metadata: unknown\n }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n\n const toolArgs = (_output.metadata as { args?: Record<string, unknown> })\n ?.args\n if (!toolArgs) return\n\n const filePath = getFilePathFromArgs(toolArgs)\n if (!filePath) return\n\n const ext = extname(filePath)\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, extSkills, \"fileType\", state)\n }\n }\n\n if (config.pathPatterns) {\n const pathSkills = getSkillsForPath(filePath, config.pathPatterns)\n if (pathSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, pathSkills, \"path\", state)\n }\n }\n },\n\n \"experimental.session.compacting\": async (\n input: { sessionID: string },\n output: { context: string[]; prompt?: string }\n ): Promise<void> => {\n if (!config.persistAfterCompaction) return\n\n const state = sessionStates.get(input.sessionID)\n if (!state || state.loadedSkills.size === 0) return\n\n const allLoadedSkills: ParsedSkill[] = []\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill) allLoadedSkills.push(skill)\n }\n\n if (allLoadedSkills.length === 0) return\n\n const formatted = formatSkillsForInjection(\n allLoadedSkills,\n { useSummaries: config.useSummaries, skillSettings: config.skillSettings }\n )\n output.context.push(\n `## Preloaded Skills\\n\\nThe following skills were loaded during this session and should persist:\\n\\n${formatted}`\n )\n\n state.initialSkillsInjected = false\n\n log(\"info\", \"Added all loaded skills to compaction context\", {\n sessionID: input.sessionID,\n skillCount: allLoadedSkills.length,\n })\n\n saveAnalytics()\n },\n\n event: async ({ event }: { event: Event }): Promise<void> => {\n if (\n event.type === \"session.deleted\" &&\n \"sessionID\" in event.properties\n ) {\n const sessionID = event.properties.sessionID as string\n sessionStates.delete(sessionID)\n pendingSkillInjections.delete(sessionID)\n analyticsData.delete(sessionID)\n log(\"debug\", \"Cleaned up session state\", { sessionID })\n saveAnalytics()\n }\n },\n }\n}\n\nexport default PreloadSkillsPlugin\n"]}
package/dist/index.d.cts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { Plugin } from '@opencode-ai/plugin';
2
2
 
3
+ interface SkillSettings {
4
+ useSummary?: boolean;
5
+ }
3
6
  interface PreloadSkillsConfig {
4
7
  skills: string[];
5
8
  fileTypeSkills?: Record<string, string[]>;
@@ -8,6 +11,7 @@ interface PreloadSkillsConfig {
8
11
  contentTriggers?: Record<string, string[]>;
9
12
  groups?: Record<string, string[]>;
10
13
  conditionalSkills?: ConditionalSkill[];
14
+ skillSettings?: Record<string, SkillSettings>;
11
15
  maxTokens?: number;
12
16
  useSummaries?: boolean;
13
17
  analytics?: boolean;
@@ -33,7 +37,11 @@ interface ParsedSkill {
33
37
  }
34
38
 
35
39
  declare function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[];
36
- declare function formatSkillsForInjection(skills: ParsedSkill[], useSummaries?: boolean): string;
40
+ interface FormatOptions {
41
+ useSummaries?: boolean;
42
+ skillSettings?: Record<string, SkillSettings>;
43
+ }
44
+ declare function formatSkillsForInjection(skills: ParsedSkill[], options?: boolean | FormatOptions): string;
37
45
 
38
46
  declare const PreloadSkillsPlugin: Plugin;
39
47
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,8 @@
1
1
  import { Plugin } from '@opencode-ai/plugin';
2
2
 
3
+ interface SkillSettings {
4
+ useSummary?: boolean;
5
+ }
3
6
  interface PreloadSkillsConfig {
4
7
  skills: string[];
5
8
  fileTypeSkills?: Record<string, string[]>;
@@ -8,6 +11,7 @@ interface PreloadSkillsConfig {
8
11
  contentTriggers?: Record<string, string[]>;
9
12
  groups?: Record<string, string[]>;
10
13
  conditionalSkills?: ConditionalSkill[];
14
+ skillSettings?: Record<string, SkillSettings>;
11
15
  maxTokens?: number;
12
16
  useSummaries?: boolean;
13
17
  analytics?: boolean;
@@ -33,7 +37,11 @@ interface ParsedSkill {
33
37
  }
34
38
 
35
39
  declare function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[];
36
- declare function formatSkillsForInjection(skills: ParsedSkill[], useSummaries?: boolean): string;
40
+ interface FormatOptions {
41
+ useSummaries?: boolean;
42
+ skillSettings?: Record<string, SkillSettings>;
43
+ }
44
+ declare function formatSkillsForInjection(skills: ParsedSkill[], options?: boolean | FormatOptions): string;
37
45
 
38
46
  declare const PreloadSkillsPlugin: Plugin;
39
47
 
package/dist/index.js CHANGED
@@ -122,12 +122,17 @@ function loadSkills(skillNames, projectDir) {
122
122
  }
123
123
  return skills;
124
124
  }
125
- function formatSkillsForInjection(skills, useSummaries = false) {
125
+ function formatSkillsForInjection(skills, options = false) {
126
126
  if (!Array.isArray(skills) || skills.length === 0) {
127
127
  return "";
128
128
  }
129
+ const opts = typeof options === "boolean" ? { useSummaries: options } : options;
130
+ const globalUseSummaries = opts.useSummaries ?? false;
131
+ const skillSettings = opts.skillSettings ?? {};
129
132
  const parts = skills.map((skill) => {
130
- const content = useSummaries && skill.summary ? skill.summary : skill.content;
133
+ const perSkillSetting = skillSettings[skill.name]?.useSummary;
134
+ const shouldUseSummary = perSkillSetting ?? globalUseSummaries;
135
+ const content = shouldUseSummary && skill.summary ? skill.summary : skill.content;
131
136
  return `<preloaded-skill name="${skill.name}">
132
137
  ${content}
133
138
  </preloaded-skill>`;
@@ -165,6 +170,7 @@ var DEFAULT_CONFIG = {
165
170
  contentTriggers: {},
166
171
  groups: {},
167
172
  conditionalSkills: [],
173
+ skillSettings: {},
168
174
  maxTokens: void 0,
169
175
  useSummaries: false,
170
176
  analytics: false,
@@ -200,6 +206,22 @@ function parseConditionalSkills(raw) {
200
206
  (item) => typeof item === "object" && item !== null && typeof item.skill === "string" && typeof item.if === "object"
201
207
  );
202
208
  }
209
+ function parseSkillSettings(raw) {
210
+ if (!raw || typeof raw !== "object") return {};
211
+ const result = {};
212
+ for (const [skillName, settings] of Object.entries(raw)) {
213
+ if (typeof settings === "object" && settings !== null) {
214
+ const parsed = {};
215
+ if ("useSummary" in settings && typeof settings.useSummary === "boolean") {
216
+ parsed.useSummary = settings.useSummary;
217
+ }
218
+ if (Object.keys(parsed).length > 0) {
219
+ result[skillName] = parsed;
220
+ }
221
+ }
222
+ }
223
+ return result;
224
+ }
203
225
  function loadConfigFile(projectDir) {
204
226
  const configPath = findConfigFile(projectDir);
205
227
  if (!configPath) {
@@ -216,6 +238,7 @@ function loadConfigFile(projectDir) {
216
238
  contentTriggers: parseStringArrayRecord(parsed.contentTriggers),
217
239
  groups: parseStringArrayRecord(parsed.groups),
218
240
  conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),
241
+ skillSettings: parseSkillSettings(parsed.skillSettings),
219
242
  maxTokens: typeof parsed.maxTokens === "number" ? parsed.maxTokens : void 0,
220
243
  useSummaries: typeof parsed.useSummaries === "boolean" ? parsed.useSummaries : void 0,
221
244
  analytics: typeof parsed.analytics === "boolean" ? parsed.analytics : void 0,
@@ -372,7 +395,7 @@ var PreloadSkillsPlugin = async (ctx) => {
372
395
  initialTokensUsed = result.tokensUsed;
373
396
  initialFormattedContent = formatSkillsForInjection(
374
397
  initialSkills,
375
- config.useSummaries
398
+ { useSummaries: config.useSummaries, skillSettings: config.skillSettings }
376
399
  );
377
400
  const loadedNames = initialSkills.map((s) => s.name);
378
401
  const missingNames = allInitialSkillNames.filter(
@@ -462,7 +485,7 @@ var PreloadSkillsPlugin = async (ctx) => {
462
485
  }
463
486
  const pending = pendingSkillInjections.get(input.sessionID);
464
487
  if (pending && pending.length > 0) {
465
- const formatted = formatSkillsForInjection(pending, config.useSummaries);
488
+ const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings });
466
489
  if (formatted) {
467
490
  contentToInject.push(formatted);
468
491
  log("info", "Injected triggered skills", {
@@ -514,7 +537,7 @@ ${firstTextPart.text}`;
514
537
  if (allLoadedSkills.length === 0) return;
515
538
  const formatted = formatSkillsForInjection(
516
539
  allLoadedSkills,
517
- config.useSummaries
540
+ { useSummaries: config.useSummaries, skillSettings: config.skillSettings }
518
541
  );
519
542
  output.context.push(
520
543
  `## Preloaded Skills
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils.ts","../src/skill-loader.ts","../src/index.ts"],"names":["join","existsSync","readFileSync","homedir"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\nexport function matchGlobPattern(filePath: string, pattern: string): boolean {\n let regexPattern = pattern\n .replace(/\\*\\*\\//g, \"\\x00DOUBLESTARSLASH\\x00\")\n .replace(/\\*\\*/g, \"\\x00DOUBLESTAR\\x00\")\n .replace(/\\*/g, \"\\x00SINGLESTAR\\x00\")\n .replace(/\\?/g, \"\\x00QUESTION\\x00\")\n \n regexPattern = regexPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n \n regexPattern = regexPattern\n .replace(/\\x00DOUBLESTARSLASH\\x00/g, \"(?:[^/]+/)*\")\n .replace(/\\x00DOUBLESTAR\\x00/g, \".*\")\n .replace(/\\x00SINGLESTAR\\x00/g, \"[^/]*\")\n .replace(/\\x00QUESTION\\x00/g, \"[^/]\")\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(filePath)\n}\n\nexport function matchesAnyPattern(\n filePath: string,\n patterns: string[]\n): boolean {\n return patterns.some((pattern) => matchGlobPattern(filePath, pattern))\n}\n\nexport function checkCondition(\n condition: { fileExists?: string; packageHasDependency?: string; envVar?: string },\n projectDir: string\n): boolean {\n if (condition.fileExists) {\n const fullPath = join(projectDir, condition.fileExists)\n if (!existsSync(fullPath)) return false\n }\n\n if (condition.packageHasDependency) {\n const packageJsonPath = join(projectDir, \"package.json\")\n if (!existsSync(packageJsonPath)) return false\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"))\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n }\n if (!deps[condition.packageHasDependency]) return false\n } catch {\n return false\n }\n }\n\n if (condition.envVar) {\n if (!process.env[condition.envVar]) return false\n }\n\n return true\n}\n\nexport function extractKeywords(text: string): string[] {\n const words = text.toLowerCase().match(/\\b[a-z]{3,}\\b/g) ?? []\n return [...new Set(words)]\n}\n\nexport function textContainsKeyword(text: string, keywords: string[]): boolean {\n const lowerText = text.toLowerCase()\n return keywords.some((kw) => lowerText.includes(kw.toLowerCase()))\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { ParsedSkill } from \"./types.js\"\nimport { estimateTokens } from \"./utils.js\"\n\nconst SKILL_FILENAME = \"SKILL.md\"\n\nconst SKILL_SEARCH_PATHS = [\n (dir: string) => join(dir, \".opencode\", \"skills\"),\n (dir: string) => join(dir, \".claude\", \"skills\"),\n () => join(homedir(), \".config\", \"opencode\", \"skills\"),\n () => join(homedir(), \".claude\", \"skills\"),\n]\n\nfunction findSkillFile(skillName: string, projectDir: string): string | null {\n for (const getPath of SKILL_SEARCH_PATHS) {\n const skillDir = getPath(projectDir)\n const skillPath = join(skillDir, skillName, SKILL_FILENAME)\n\n if (existsSync(skillPath)) {\n return skillPath\n }\n }\n return null\n}\n\ninterface FrontmatterData {\n name?: string\n description?: string\n summary?: string\n}\n\nfunction parseFrontmatter(content: string): FrontmatterData {\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)\n if (!frontmatterMatch?.[1]) {\n return {}\n }\n\n const frontmatter = frontmatterMatch[1]\n const result: FrontmatterData = {}\n\n const nameMatch = frontmatter.match(/^name:\\s*(.+)$/m)\n if (nameMatch?.[1]) {\n result.name = nameMatch[1].trim()\n }\n\n const descMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (descMatch?.[1]) {\n result.description = descMatch[1].trim()\n }\n\n const summaryMatch = frontmatter.match(/^summary:\\s*(.+)$/m)\n if (summaryMatch?.[1]) {\n result.summary = summaryMatch[1].trim()\n }\n\n return result\n}\n\nfunction extractAutoSummary(content: string, maxLength: number = 500): string {\n const withoutFrontmatter = content.replace(/^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n?/, \"\")\n \n const firstSection = withoutFrontmatter.split(/\\n##\\s/)[0] ?? \"\"\n const cleaned = firstSection\n .replace(/^#\\s+.+\\n?/, \"\")\n .replace(/\\n+/g, \" \")\n .trim()\n\n if (cleaned.length <= maxLength) return cleaned\n return cleaned.slice(0, maxLength).replace(/\\s+\\S*$/, \"\") + \"...\"\n}\n\nexport function loadSkill(skillName: string, projectDir: string): ParsedSkill | null {\n const filePath = findSkillFile(skillName, projectDir)\n\n if (!filePath) {\n return null\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\")\n const { name, description, summary } = parseFrontmatter(content)\n\n return {\n name: name ?? skillName,\n description: description ?? \"\",\n summary: summary ?? extractAutoSummary(content),\n content,\n filePath,\n tokenCount: estimateTokens(content),\n }\n } catch {\n return null\n }\n}\n\nexport function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[] {\n if (!Array.isArray(skillNames)) {\n return []\n }\n\n const skills: ParsedSkill[] = []\n\n for (const name of skillNames) {\n const skill = loadSkill(name, projectDir)\n if (skill) {\n skills.push(skill)\n }\n }\n\n return skills\n}\n\nexport function formatSkillsForInjection(\n skills: ParsedSkill[],\n useSummaries: boolean = false\n): string {\n if (!Array.isArray(skills) || skills.length === 0) {\n return \"\"\n }\n\n const parts = skills.map((skill) => {\n const content = useSummaries && skill.summary ? skill.summary : skill.content\n return `<preloaded-skill name=\"${skill.name}\">\\n${content}\\n</preloaded-skill>`\n })\n\n return `<preloaded-skills>\nThe following skills have been automatically loaded for this session:\n\n${parts.join(\"\\n\\n\")}\n</preloaded-skills>`\n}\n\nexport function calculateTotalTokens(skills: ParsedSkill[]): number {\n return skills.reduce((sum, skill) => sum + skill.tokenCount, 0)\n}\n\nexport function filterSkillsByTokenBudget(\n skills: ParsedSkill[],\n maxTokens: number\n): ParsedSkill[] {\n const result: ParsedSkill[] = []\n let totalTokens = 0\n\n for (const skill of skills) {\n if (totalTokens + skill.tokenCount <= maxTokens) {\n result.push(skill)\n totalTokens += skill.tokenCount\n }\n }\n\n return result\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\"\nimport { join, extname, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { Plugin, PluginInput } from \"@opencode-ai/plugin\"\nimport type { Event, UserMessage, Part } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillUsageStats,\n AnalyticsData,\n} from \"./types.js\"\nimport {\n loadSkills,\n formatSkillsForInjection,\n filterSkillsByTokenBudget,\n calculateTotalTokens,\n} from \"./skill-loader.js\"\nimport {\n checkCondition,\n matchGlobPattern,\n textContainsKeyword,\n} from \"./utils.js\"\n\nexport type { PreloadSkillsConfig, ParsedSkill }\nexport { loadSkills, formatSkillsForInjection }\n\nconst CONFIG_FILENAME = \"preload-skills.json\"\nconst ANALYTICS_FILENAME = \"preload-skills-analytics.json\"\nconst FILE_TOOLS = [\"read\", \"edit\", \"write\", \"glob\", \"grep\"]\n\nconst DEFAULT_CONFIG: PreloadSkillsConfig = {\n skills: [],\n fileTypeSkills: {},\n agentSkills: {},\n pathPatterns: {},\n contentTriggers: {},\n groups: {},\n conditionalSkills: [],\n maxTokens: undefined,\n useSummaries: false,\n analytics: false,\n persistAfterCompaction: true,\n debug: false,\n}\n\nfunction findConfigFile(projectDir: string): string | null {\n const locations = [\n join(projectDir, \".opencode\", CONFIG_FILENAME),\n join(projectDir, CONFIG_FILENAME),\n join(homedir(), \".config\", \"opencode\", CONFIG_FILENAME),\n ]\n\n for (const path of locations) {\n if (existsSync(path)) {\n return path\n }\n }\n return null\n}\n\nfunction parseStringArrayRecord(raw: unknown): Record<string, string[]> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, string[]> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (Array.isArray(value)) {\n result[key] = value.filter((v) => typeof v === \"string\")\n }\n }\n return result\n}\n\nfunction parseConditionalSkills(raw: unknown): ConditionalSkill[] {\n if (!Array.isArray(raw)) return []\n\n return raw.filter(\n (item): item is ConditionalSkill =>\n typeof item === \"object\" &&\n item !== null &&\n typeof item.skill === \"string\" &&\n typeof item.if === \"object\"\n )\n}\n\nfunction loadConfigFile(projectDir: string): Partial<PreloadSkillsConfig> {\n const configPath = findConfigFile(projectDir)\n if (!configPath) {\n return {}\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\")\n const parsed = JSON.parse(content) as Record<string, unknown>\n\n return {\n skills: Array.isArray(parsed.skills) ? parsed.skills : [],\n fileTypeSkills: parseStringArrayRecord(parsed.fileTypeSkills),\n agentSkills: parseStringArrayRecord(parsed.agentSkills),\n pathPatterns: parseStringArrayRecord(parsed.pathPatterns),\n contentTriggers: parseStringArrayRecord(parsed.contentTriggers),\n groups: parseStringArrayRecord(parsed.groups),\n conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),\n maxTokens:\n typeof parsed.maxTokens === \"number\" ? parsed.maxTokens : undefined,\n useSummaries:\n typeof parsed.useSummaries === \"boolean\"\n ? parsed.useSummaries\n : undefined,\n analytics:\n typeof parsed.analytics === \"boolean\" ? parsed.analytics : undefined,\n persistAfterCompaction:\n typeof parsed.persistAfterCompaction === \"boolean\"\n ? parsed.persistAfterCompaction\n : undefined,\n debug: typeof parsed.debug === \"boolean\" ? parsed.debug : undefined,\n }\n } catch {\n return {}\n }\n}\n\nfunction getFilePathFromArgs(args: Record<string, unknown>): string | null {\n if (typeof args.filePath === \"string\") return args.filePath\n if (typeof args.path === \"string\") return args.path\n if (typeof args.file === \"string\") return args.file\n return null\n}\n\nfunction getSkillsForExtension(\n ext: string,\n fileTypeSkills: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(fileTypeSkills)) {\n const extensions = pattern.split(\",\").map((e) => e.trim().toLowerCase())\n if (extensions.includes(ext.toLowerCase())) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction getSkillsForPath(\n filePath: string,\n pathPatterns: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(pathPatterns)) {\n if (matchGlobPattern(filePath, pattern)) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction resolveSkillGroups(\n skillNames: string[],\n groups: Record<string, string[]>\n): string[] {\n const resolved: string[] = []\n\n for (const name of skillNames) {\n if (name.startsWith(\"@\") && groups[name.slice(1)]) {\n resolved.push(...groups[name.slice(1)]!)\n } else {\n resolved.push(name)\n }\n }\n\n return [...new Set(resolved)]\n}\n\nexport const PreloadSkillsPlugin: Plugin = async (ctx: PluginInput) => {\n const sessionStates = new Map<string, SessionState>()\n const analyticsData = new Map<string, AnalyticsData>()\n\n const fileConfig = loadConfigFile(ctx.directory)\n const config: PreloadSkillsConfig = {\n ...DEFAULT_CONFIG,\n ...fileConfig,\n }\n\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: Record<string, unknown>\n ) => {\n if (level === \"debug\" && !config.debug) return\n\n ctx.client.app.log({\n body: {\n service: \"preload-skills\",\n level,\n message,\n extra,\n },\n })\n }\n\n const trackSkillUsage = (\n sessionID: string,\n skillName: string,\n triggerType: SkillUsageStats[\"triggerType\"]\n ) => {\n if (!config.analytics) return\n\n if (!analyticsData.has(sessionID)) {\n analyticsData.set(sessionID, {\n sessionId: sessionID,\n skillUsage: new Map(),\n })\n }\n\n const data = analyticsData.get(sessionID)!\n const now = Date.now()\n\n if (data.skillUsage.has(skillName)) {\n const stats = data.skillUsage.get(skillName)!\n stats.loadCount++\n stats.lastLoaded = now\n } else {\n data.skillUsage.set(skillName, {\n skillName,\n loadCount: 1,\n triggerType,\n firstLoaded: now,\n lastLoaded: now,\n })\n }\n }\n\n const saveAnalytics = () => {\n if (!config.analytics) return\n\n try {\n const analyticsPath = join(ctx.directory, \".opencode\", ANALYTICS_FILENAME)\n const dir = dirname(analyticsPath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n const serializable: Record<string, unknown> = {}\n for (const [sessionId, data] of analyticsData) {\n serializable[sessionId] = {\n sessionId: data.sessionId,\n skillUsage: Object.fromEntries(data.skillUsage),\n }\n }\n\n writeFileSync(analyticsPath, JSON.stringify(serializable, null, 2))\n } catch {\n log(\"warn\", \"Failed to save analytics\")\n }\n }\n\n const skillCache = new Map<string, ParsedSkill>()\n\n const loadSkillsWithBudget = (\n skillNames: string[],\n currentTokens: number,\n triggerType: SkillUsageStats[\"triggerType\"],\n sessionID: string\n ): { skills: ParsedSkill[]; tokensUsed: number } => {\n const resolved = resolveSkillGroups(skillNames, config.groups ?? {})\n let skills = loadSkills(resolved, ctx.directory)\n\n for (const skill of skills) {\n skillCache.set(skill.name, skill)\n }\n\n if (config.maxTokens) {\n const remainingBudget = config.maxTokens - currentTokens\n skills = filterSkillsByTokenBudget(skills, remainingBudget)\n }\n\n for (const skill of skills) {\n trackSkillUsage(sessionID, skill.name, triggerType)\n }\n\n return {\n skills,\n tokensUsed: calculateTotalTokens(skills),\n }\n }\n\n const resolveConditionalSkills = (): string[] => {\n if (!config.conditionalSkills?.length) return []\n\n const resolved: string[] = []\n for (const { skill, if: condition } of config.conditionalSkills) {\n if (checkCondition(condition, ctx.directory)) {\n resolved.push(skill)\n }\n }\n\n return resolved\n }\n\n let initialSkills: ParsedSkill[] = []\n let initialFormattedContent = \"\"\n let initialTokensUsed = 0\n\n const allInitialSkillNames = [\n ...config.skills,\n ...resolveConditionalSkills(),\n ]\n\n if (allInitialSkillNames.length > 0) {\n const result = loadSkillsWithBudget(\n allInitialSkillNames,\n 0,\n \"initial\",\n \"__init__\"\n )\n initialSkills = result.skills\n initialTokensUsed = result.tokensUsed\n initialFormattedContent = formatSkillsForInjection(\n initialSkills,\n config.useSummaries\n )\n\n const loadedNames = initialSkills.map((s) => s.name)\n const missingNames = allInitialSkillNames.filter(\n (s) => !loadedNames.includes(s) && !s.startsWith(\"@\")\n )\n\n log(\"info\", `Loaded ${initialSkills.length} initial skills`, {\n loaded: loadedNames,\n tokens: initialTokensUsed,\n missing: missingNames.length > 0 ? missingNames : undefined,\n })\n }\n\n const hasTriggeredSkills =\n Object.keys(config.fileTypeSkills ?? {}).length > 0 ||\n Object.keys(config.agentSkills ?? {}).length > 0 ||\n Object.keys(config.pathPatterns ?? {}).length > 0 ||\n Object.keys(config.contentTriggers ?? {}).length > 0\n\n if (allInitialSkillNames.length === 0 && !hasTriggeredSkills) {\n log(\"warn\", \"No skills configured. Create .opencode/preload-skills.json\")\n }\n\n const getSessionState = (sessionID: string): SessionState => {\n if (!sessionStates.has(sessionID)) {\n sessionStates.set(sessionID, {\n initialSkillsInjected: false,\n loadedSkills: new Set(initialSkills.map((s) => s.name)),\n totalTokensUsed: initialTokensUsed,\n })\n }\n return sessionStates.get(sessionID)!\n }\n\n const pendingSkillInjections = new Map<string, ParsedSkill[]>()\n\n const queueSkillsForInjection = (\n sessionID: string,\n skillNames: string[],\n triggerType: SkillUsageStats[\"triggerType\"],\n state: SessionState\n ) => {\n const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name))\n if (newSkillNames.length === 0) return\n\n const result = loadSkillsWithBudget(\n newSkillNames,\n state.totalTokensUsed,\n triggerType,\n sessionID\n )\n\n if (result.skills.length > 0) {\n for (const skill of result.skills) {\n state.loadedSkills.add(skill.name)\n }\n state.totalTokensUsed += result.tokensUsed\n\n const existing = pendingSkillInjections.get(sessionID) ?? []\n pendingSkillInjections.set(sessionID, [...existing, ...result.skills])\n\n log(\"debug\", `Queued ${triggerType} skills for injection`, {\n sessionID,\n skills: result.skills.map((s) => s.name),\n tokens: result.tokensUsed,\n })\n }\n }\n\n return {\n \"chat.message\": async (\n input: {\n sessionID: string\n agent?: string\n model?: { providerID: string; modelID: string }\n messageID?: string\n variant?: string\n },\n output: { message: UserMessage; parts: Part[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const firstTextPart = output.parts.find((p) => p.type === \"text\")\n if (!firstTextPart || !(\"text\" in firstTextPart)) return\n\n const messageText = firstTextPart.text\n\n if (input.agent && config.agentSkills?.[input.agent]) {\n queueSkillsForInjection(\n input.sessionID,\n config.agentSkills[input.agent]!,\n \"agent\",\n state\n )\n }\n\n if (config.contentTriggers) {\n for (const [keyword, skillNames] of Object.entries(\n config.contentTriggers\n )) {\n if (textContainsKeyword(messageText, [keyword])) {\n queueSkillsForInjection(\n input.sessionID,\n skillNames,\n \"content\",\n state\n )\n }\n }\n }\n\n const contentToInject: string[] = []\n\n if (!state.initialSkillsInjected && initialFormattedContent) {\n contentToInject.push(initialFormattedContent)\n state.initialSkillsInjected = true\n log(\"info\", \"Injected initial preloaded skills\", {\n sessionID: input.sessionID,\n skills: initialSkills.map((s) => s.name),\n })\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n const formatted = formatSkillsForInjection(pending, config.useSummaries)\n if (formatted) {\n contentToInject.push(formatted)\n log(\"info\", \"Injected triggered skills\", {\n sessionID: input.sessionID,\n skills: pending.map((s) => s.name),\n })\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (contentToInject.length > 0) {\n firstTextPart.text = `${contentToInject.join(\"\\n\\n\")}\\n\\n---\\n\\n${firstTextPart.text}`\n }\n },\n\n \"tool.execute.after\": async (\n input: {\n tool: string\n sessionID: string\n callID: string\n },\n _output: {\n title: string\n output: string\n metadata: unknown\n }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n\n const toolArgs = (_output.metadata as { args?: Record<string, unknown> })\n ?.args\n if (!toolArgs) return\n\n const filePath = getFilePathFromArgs(toolArgs)\n if (!filePath) return\n\n const ext = extname(filePath)\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, extSkills, \"fileType\", state)\n }\n }\n\n if (config.pathPatterns) {\n const pathSkills = getSkillsForPath(filePath, config.pathPatterns)\n if (pathSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, pathSkills, \"path\", state)\n }\n }\n },\n\n \"experimental.session.compacting\": async (\n input: { sessionID: string },\n output: { context: string[]; prompt?: string }\n ): Promise<void> => {\n if (!config.persistAfterCompaction) return\n\n const state = sessionStates.get(input.sessionID)\n if (!state || state.loadedSkills.size === 0) return\n\n const allLoadedSkills: ParsedSkill[] = []\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill) allLoadedSkills.push(skill)\n }\n\n if (allLoadedSkills.length === 0) return\n\n const formatted = formatSkillsForInjection(\n allLoadedSkills,\n config.useSummaries\n )\n output.context.push(\n `## Preloaded Skills\\n\\nThe following skills were loaded during this session and should persist:\\n\\n${formatted}`\n )\n\n state.initialSkillsInjected = false\n\n log(\"info\", \"Added all loaded skills to compaction context\", {\n sessionID: input.sessionID,\n skillCount: allLoadedSkills.length,\n })\n\n saveAnalytics()\n },\n\n event: async ({ event }: { event: Event }): Promise<void> => {\n if (\n event.type === \"session.deleted\" &&\n \"sessionID\" in event.properties\n ) {\n const sessionID = event.properties.sessionID as string\n sessionStates.delete(sessionID)\n pendingSkillInjections.delete(sessionID)\n analyticsData.delete(sessionID)\n log(\"debug\", \"Cleaned up session state\", { sessionID })\n saveAnalytics()\n }\n },\n }\n}\n\nexport default PreloadSkillsPlugin\n"]}
1
+ {"version":3,"sources":["../src/utils.ts","../src/skill-loader.ts","../src/index.ts"],"names":["join","existsSync","readFileSync","homedir"],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\n\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4)\n}\n\nexport function matchGlobPattern(filePath: string, pattern: string): boolean {\n let regexPattern = pattern\n .replace(/\\*\\*\\//g, \"\\x00DOUBLESTARSLASH\\x00\")\n .replace(/\\*\\*/g, \"\\x00DOUBLESTAR\\x00\")\n .replace(/\\*/g, \"\\x00SINGLESTAR\\x00\")\n .replace(/\\?/g, \"\\x00QUESTION\\x00\")\n \n regexPattern = regexPattern.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n \n regexPattern = regexPattern\n .replace(/\\x00DOUBLESTARSLASH\\x00/g, \"(?:[^/]+/)*\")\n .replace(/\\x00DOUBLESTAR\\x00/g, \".*\")\n .replace(/\\x00SINGLESTAR\\x00/g, \"[^/]*\")\n .replace(/\\x00QUESTION\\x00/g, \"[^/]\")\n\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(filePath)\n}\n\nexport function matchesAnyPattern(\n filePath: string,\n patterns: string[]\n): boolean {\n return patterns.some((pattern) => matchGlobPattern(filePath, pattern))\n}\n\nexport function checkCondition(\n condition: { fileExists?: string; packageHasDependency?: string; envVar?: string },\n projectDir: string\n): boolean {\n if (condition.fileExists) {\n const fullPath = join(projectDir, condition.fileExists)\n if (!existsSync(fullPath)) return false\n }\n\n if (condition.packageHasDependency) {\n const packageJsonPath = join(projectDir, \"package.json\")\n if (!existsSync(packageJsonPath)) return false\n\n try {\n const packageJson = JSON.parse(readFileSync(packageJsonPath, \"utf-8\"))\n const deps = {\n ...packageJson.dependencies,\n ...packageJson.devDependencies,\n ...packageJson.peerDependencies,\n }\n if (!deps[condition.packageHasDependency]) return false\n } catch {\n return false\n }\n }\n\n if (condition.envVar) {\n if (!process.env[condition.envVar]) return false\n }\n\n return true\n}\n\nexport function extractKeywords(text: string): string[] {\n const words = text.toLowerCase().match(/\\b[a-z]{3,}\\b/g) ?? []\n return [...new Set(words)]\n}\n\nexport function textContainsKeyword(text: string, keywords: string[]): boolean {\n const lowerText = text.toLowerCase()\n return keywords.some((kw) => lowerText.includes(kw.toLowerCase()))\n}\n","import { existsSync, readFileSync } from \"node:fs\"\nimport { join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { ParsedSkill, SkillSettings } from \"./types.js\"\nimport { estimateTokens } from \"./utils.js\"\n\nconst SKILL_FILENAME = \"SKILL.md\"\n\nconst SKILL_SEARCH_PATHS = [\n (dir: string) => join(dir, \".opencode\", \"skills\"),\n (dir: string) => join(dir, \".claude\", \"skills\"),\n () => join(homedir(), \".config\", \"opencode\", \"skills\"),\n () => join(homedir(), \".claude\", \"skills\"),\n]\n\nfunction findSkillFile(skillName: string, projectDir: string): string | null {\n for (const getPath of SKILL_SEARCH_PATHS) {\n const skillDir = getPath(projectDir)\n const skillPath = join(skillDir, skillName, SKILL_FILENAME)\n\n if (existsSync(skillPath)) {\n return skillPath\n }\n }\n return null\n}\n\ninterface FrontmatterData {\n name?: string\n description?: string\n summary?: string\n}\n\nfunction parseFrontmatter(content: string): FrontmatterData {\n const frontmatterMatch = content.match(/^---\\s*\\n([\\s\\S]*?)\\n---/)\n if (!frontmatterMatch?.[1]) {\n return {}\n }\n\n const frontmatter = frontmatterMatch[1]\n const result: FrontmatterData = {}\n\n const nameMatch = frontmatter.match(/^name:\\s*(.+)$/m)\n if (nameMatch?.[1]) {\n result.name = nameMatch[1].trim()\n }\n\n const descMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n if (descMatch?.[1]) {\n result.description = descMatch[1].trim()\n }\n\n const summaryMatch = frontmatter.match(/^summary:\\s*(.+)$/m)\n if (summaryMatch?.[1]) {\n result.summary = summaryMatch[1].trim()\n }\n\n return result\n}\n\nfunction extractAutoSummary(content: string, maxLength: number = 500): string {\n const withoutFrontmatter = content.replace(/^---\\s*\\n[\\s\\S]*?\\n---\\s*\\n?/, \"\")\n \n const firstSection = withoutFrontmatter.split(/\\n##\\s/)[0] ?? \"\"\n const cleaned = firstSection\n .replace(/^#\\s+.+\\n?/, \"\")\n .replace(/\\n+/g, \" \")\n .trim()\n\n if (cleaned.length <= maxLength) return cleaned\n return cleaned.slice(0, maxLength).replace(/\\s+\\S*$/, \"\") + \"...\"\n}\n\nexport function loadSkill(skillName: string, projectDir: string): ParsedSkill | null {\n const filePath = findSkillFile(skillName, projectDir)\n\n if (!filePath) {\n return null\n }\n\n try {\n const content = readFileSync(filePath, \"utf-8\")\n const { name, description, summary } = parseFrontmatter(content)\n\n return {\n name: name ?? skillName,\n description: description ?? \"\",\n summary: summary ?? extractAutoSummary(content),\n content,\n filePath,\n tokenCount: estimateTokens(content),\n }\n } catch {\n return null\n }\n}\n\nexport function loadSkills(skillNames: string[], projectDir: string): ParsedSkill[] {\n if (!Array.isArray(skillNames)) {\n return []\n }\n\n const skills: ParsedSkill[] = []\n\n for (const name of skillNames) {\n const skill = loadSkill(name, projectDir)\n if (skill) {\n skills.push(skill)\n }\n }\n\n return skills\n}\n\nexport interface FormatOptions {\n useSummaries?: boolean\n skillSettings?: Record<string, SkillSettings>\n}\n\nexport function formatSkillsForInjection(\n skills: ParsedSkill[],\n options: boolean | FormatOptions = false\n): string {\n if (!Array.isArray(skills) || skills.length === 0) {\n return \"\"\n }\n\n const opts: FormatOptions = typeof options === \"boolean\" \n ? { useSummaries: options } \n : options\n \n const globalUseSummaries = opts.useSummaries ?? false\n const skillSettings = opts.skillSettings ?? {}\n\n const parts = skills.map((skill) => {\n const perSkillSetting = skillSettings[skill.name]?.useSummary\n const shouldUseSummary = perSkillSetting ?? globalUseSummaries\n const content = shouldUseSummary && skill.summary ? skill.summary : skill.content\n return `<preloaded-skill name=\"${skill.name}\">\\n${content}\\n</preloaded-skill>`\n })\n\n return `<preloaded-skills>\nThe following skills have been automatically loaded for this session:\n\n${parts.join(\"\\n\\n\")}\n</preloaded-skills>`\n}\n\nexport function calculateTotalTokens(skills: ParsedSkill[]): number {\n return skills.reduce((sum, skill) => sum + skill.tokenCount, 0)\n}\n\nexport function filterSkillsByTokenBudget(\n skills: ParsedSkill[],\n maxTokens: number\n): ParsedSkill[] {\n const result: ParsedSkill[] = []\n let totalTokens = 0\n\n for (const skill of skills) {\n if (totalTokens + skill.tokenCount <= maxTokens) {\n result.push(skill)\n totalTokens += skill.tokenCount\n }\n }\n\n return result\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\"\nimport { join, extname, dirname } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport type { Plugin, PluginInput } from \"@opencode-ai/plugin\"\nimport type { Event, UserMessage, Part } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillSettings,\n SkillUsageStats,\n AnalyticsData,\n} from \"./types.js\"\nimport {\n loadSkills,\n formatSkillsForInjection,\n filterSkillsByTokenBudget,\n calculateTotalTokens,\n} from \"./skill-loader.js\"\nimport {\n checkCondition,\n matchGlobPattern,\n textContainsKeyword,\n} from \"./utils.js\"\n\nexport type { PreloadSkillsConfig, ParsedSkill }\nexport { loadSkills, formatSkillsForInjection }\n\nconst CONFIG_FILENAME = \"preload-skills.json\"\nconst ANALYTICS_FILENAME = \"preload-skills-analytics.json\"\nconst FILE_TOOLS = [\"read\", \"edit\", \"write\", \"glob\", \"grep\"]\n\nconst DEFAULT_CONFIG: PreloadSkillsConfig = {\n skills: [],\n fileTypeSkills: {},\n agentSkills: {},\n pathPatterns: {},\n contentTriggers: {},\n groups: {},\n conditionalSkills: [],\n skillSettings: {},\n maxTokens: undefined,\n useSummaries: false,\n analytics: false,\n persistAfterCompaction: true,\n debug: false,\n}\n\nfunction findConfigFile(projectDir: string): string | null {\n const locations = [\n join(projectDir, \".opencode\", CONFIG_FILENAME),\n join(projectDir, CONFIG_FILENAME),\n join(homedir(), \".config\", \"opencode\", CONFIG_FILENAME),\n ]\n\n for (const path of locations) {\n if (existsSync(path)) {\n return path\n }\n }\n return null\n}\n\nfunction parseStringArrayRecord(raw: unknown): Record<string, string[]> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, string[]> = {}\n for (const [key, value] of Object.entries(raw)) {\n if (Array.isArray(value)) {\n result[key] = value.filter((v) => typeof v === \"string\")\n }\n }\n return result\n}\n\nfunction parseConditionalSkills(raw: unknown): ConditionalSkill[] {\n if (!Array.isArray(raw)) return []\n\n return raw.filter(\n (item): item is ConditionalSkill =>\n typeof item === \"object\" &&\n item !== null &&\n typeof item.skill === \"string\" &&\n typeof item.if === \"object\"\n )\n}\n\nfunction parseSkillSettings(raw: unknown): Record<string, SkillSettings> {\n if (!raw || typeof raw !== \"object\") return {}\n\n const result: Record<string, SkillSettings> = {}\n for (const [skillName, settings] of Object.entries(raw)) {\n if (typeof settings === \"object\" && settings !== null) {\n const parsed: SkillSettings = {}\n if (\"useSummary\" in settings && typeof settings.useSummary === \"boolean\") {\n parsed.useSummary = settings.useSummary\n }\n if (Object.keys(parsed).length > 0) {\n result[skillName] = parsed\n }\n }\n }\n return result\n}\n\nfunction loadConfigFile(projectDir: string): Partial<PreloadSkillsConfig> {\n const configPath = findConfigFile(projectDir)\n if (!configPath) {\n return {}\n }\n\n try {\n const content = readFileSync(configPath, \"utf-8\")\n const parsed = JSON.parse(content) as Record<string, unknown>\n\n return {\n skills: Array.isArray(parsed.skills) ? parsed.skills : [],\n fileTypeSkills: parseStringArrayRecord(parsed.fileTypeSkills),\n agentSkills: parseStringArrayRecord(parsed.agentSkills),\n pathPatterns: parseStringArrayRecord(parsed.pathPatterns),\n contentTriggers: parseStringArrayRecord(parsed.contentTriggers),\n groups: parseStringArrayRecord(parsed.groups),\n conditionalSkills: parseConditionalSkills(parsed.conditionalSkills),\n skillSettings: parseSkillSettings(parsed.skillSettings),\n maxTokens:\n typeof parsed.maxTokens === \"number\" ? parsed.maxTokens : undefined,\n useSummaries:\n typeof parsed.useSummaries === \"boolean\"\n ? parsed.useSummaries\n : undefined,\n analytics:\n typeof parsed.analytics === \"boolean\" ? parsed.analytics : undefined,\n persistAfterCompaction:\n typeof parsed.persistAfterCompaction === \"boolean\"\n ? parsed.persistAfterCompaction\n : undefined,\n debug: typeof parsed.debug === \"boolean\" ? parsed.debug : undefined,\n }\n } catch {\n return {}\n }\n}\n\nfunction getFilePathFromArgs(args: Record<string, unknown>): string | null {\n if (typeof args.filePath === \"string\") return args.filePath\n if (typeof args.path === \"string\") return args.path\n if (typeof args.file === \"string\") return args.file\n return null\n}\n\nfunction getSkillsForExtension(\n ext: string,\n fileTypeSkills: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(fileTypeSkills)) {\n const extensions = pattern.split(\",\").map((e) => e.trim().toLowerCase())\n if (extensions.includes(ext.toLowerCase())) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction getSkillsForPath(\n filePath: string,\n pathPatterns: Record<string, string[]>\n): string[] {\n const skills: string[] = []\n\n for (const [pattern, skillNames] of Object.entries(pathPatterns)) {\n if (matchGlobPattern(filePath, pattern)) {\n skills.push(...skillNames)\n }\n }\n\n return [...new Set(skills)]\n}\n\nfunction resolveSkillGroups(\n skillNames: string[],\n groups: Record<string, string[]>\n): string[] {\n const resolved: string[] = []\n\n for (const name of skillNames) {\n if (name.startsWith(\"@\") && groups[name.slice(1)]) {\n resolved.push(...groups[name.slice(1)]!)\n } else {\n resolved.push(name)\n }\n }\n\n return [...new Set(resolved)]\n}\n\nexport const PreloadSkillsPlugin: Plugin = async (ctx: PluginInput) => {\n const sessionStates = new Map<string, SessionState>()\n const analyticsData = new Map<string, AnalyticsData>()\n\n const fileConfig = loadConfigFile(ctx.directory)\n const config: PreloadSkillsConfig = {\n ...DEFAULT_CONFIG,\n ...fileConfig,\n }\n\n const log = (\n level: \"debug\" | \"info\" | \"warn\" | \"error\",\n message: string,\n extra?: Record<string, unknown>\n ) => {\n if (level === \"debug\" && !config.debug) return\n\n ctx.client.app.log({\n body: {\n service: \"preload-skills\",\n level,\n message,\n extra,\n },\n })\n }\n\n const trackSkillUsage = (\n sessionID: string,\n skillName: string,\n triggerType: SkillUsageStats[\"triggerType\"]\n ) => {\n if (!config.analytics) return\n\n if (!analyticsData.has(sessionID)) {\n analyticsData.set(sessionID, {\n sessionId: sessionID,\n skillUsage: new Map(),\n })\n }\n\n const data = analyticsData.get(sessionID)!\n const now = Date.now()\n\n if (data.skillUsage.has(skillName)) {\n const stats = data.skillUsage.get(skillName)!\n stats.loadCount++\n stats.lastLoaded = now\n } else {\n data.skillUsage.set(skillName, {\n skillName,\n loadCount: 1,\n triggerType,\n firstLoaded: now,\n lastLoaded: now,\n })\n }\n }\n\n const saveAnalytics = () => {\n if (!config.analytics) return\n\n try {\n const analyticsPath = join(ctx.directory, \".opencode\", ANALYTICS_FILENAME)\n const dir = dirname(analyticsPath)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n\n const serializable: Record<string, unknown> = {}\n for (const [sessionId, data] of analyticsData) {\n serializable[sessionId] = {\n sessionId: data.sessionId,\n skillUsage: Object.fromEntries(data.skillUsage),\n }\n }\n\n writeFileSync(analyticsPath, JSON.stringify(serializable, null, 2))\n } catch {\n log(\"warn\", \"Failed to save analytics\")\n }\n }\n\n const skillCache = new Map<string, ParsedSkill>()\n\n const loadSkillsWithBudget = (\n skillNames: string[],\n currentTokens: number,\n triggerType: SkillUsageStats[\"triggerType\"],\n sessionID: string\n ): { skills: ParsedSkill[]; tokensUsed: number } => {\n const resolved = resolveSkillGroups(skillNames, config.groups ?? {})\n let skills = loadSkills(resolved, ctx.directory)\n\n for (const skill of skills) {\n skillCache.set(skill.name, skill)\n }\n\n if (config.maxTokens) {\n const remainingBudget = config.maxTokens - currentTokens\n skills = filterSkillsByTokenBudget(skills, remainingBudget)\n }\n\n for (const skill of skills) {\n trackSkillUsage(sessionID, skill.name, triggerType)\n }\n\n return {\n skills,\n tokensUsed: calculateTotalTokens(skills),\n }\n }\n\n const resolveConditionalSkills = (): string[] => {\n if (!config.conditionalSkills?.length) return []\n\n const resolved: string[] = []\n for (const { skill, if: condition } of config.conditionalSkills) {\n if (checkCondition(condition, ctx.directory)) {\n resolved.push(skill)\n }\n }\n\n return resolved\n }\n\n let initialSkills: ParsedSkill[] = []\n let initialFormattedContent = \"\"\n let initialTokensUsed = 0\n\n const allInitialSkillNames = [\n ...config.skills,\n ...resolveConditionalSkills(),\n ]\n\n if (allInitialSkillNames.length > 0) {\n const result = loadSkillsWithBudget(\n allInitialSkillNames,\n 0,\n \"initial\",\n \"__init__\"\n )\n initialSkills = result.skills\n initialTokensUsed = result.tokensUsed\n initialFormattedContent = formatSkillsForInjection(\n initialSkills,\n { useSummaries: config.useSummaries, skillSettings: config.skillSettings }\n )\n\n const loadedNames = initialSkills.map((s) => s.name)\n const missingNames = allInitialSkillNames.filter(\n (s) => !loadedNames.includes(s) && !s.startsWith(\"@\")\n )\n\n log(\"info\", `Loaded ${initialSkills.length} initial skills`, {\n loaded: loadedNames,\n tokens: initialTokensUsed,\n missing: missingNames.length > 0 ? missingNames : undefined,\n })\n }\n\n const hasTriggeredSkills =\n Object.keys(config.fileTypeSkills ?? {}).length > 0 ||\n Object.keys(config.agentSkills ?? {}).length > 0 ||\n Object.keys(config.pathPatterns ?? {}).length > 0 ||\n Object.keys(config.contentTriggers ?? {}).length > 0\n\n if (allInitialSkillNames.length === 0 && !hasTriggeredSkills) {\n log(\"warn\", \"No skills configured. Create .opencode/preload-skills.json\")\n }\n\n const getSessionState = (sessionID: string): SessionState => {\n if (!sessionStates.has(sessionID)) {\n sessionStates.set(sessionID, {\n initialSkillsInjected: false,\n loadedSkills: new Set(initialSkills.map((s) => s.name)),\n totalTokensUsed: initialTokensUsed,\n })\n }\n return sessionStates.get(sessionID)!\n }\n\n const pendingSkillInjections = new Map<string, ParsedSkill[]>()\n\n const queueSkillsForInjection = (\n sessionID: string,\n skillNames: string[],\n triggerType: SkillUsageStats[\"triggerType\"],\n state: SessionState\n ) => {\n const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name))\n if (newSkillNames.length === 0) return\n\n const result = loadSkillsWithBudget(\n newSkillNames,\n state.totalTokensUsed,\n triggerType,\n sessionID\n )\n\n if (result.skills.length > 0) {\n for (const skill of result.skills) {\n state.loadedSkills.add(skill.name)\n }\n state.totalTokensUsed += result.tokensUsed\n\n const existing = pendingSkillInjections.get(sessionID) ?? []\n pendingSkillInjections.set(sessionID, [...existing, ...result.skills])\n\n log(\"debug\", `Queued ${triggerType} skills for injection`, {\n sessionID,\n skills: result.skills.map((s) => s.name),\n tokens: result.tokensUsed,\n })\n }\n }\n\n return {\n \"chat.message\": async (\n input: {\n sessionID: string\n agent?: string\n model?: { providerID: string; modelID: string }\n messageID?: string\n variant?: string\n },\n output: { message: UserMessage; parts: Part[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const firstTextPart = output.parts.find((p) => p.type === \"text\")\n if (!firstTextPart || !(\"text\" in firstTextPart)) return\n\n const messageText = firstTextPart.text\n\n if (input.agent && config.agentSkills?.[input.agent]) {\n queueSkillsForInjection(\n input.sessionID,\n config.agentSkills[input.agent]!,\n \"agent\",\n state\n )\n }\n\n if (config.contentTriggers) {\n for (const [keyword, skillNames] of Object.entries(\n config.contentTriggers\n )) {\n if (textContainsKeyword(messageText, [keyword])) {\n queueSkillsForInjection(\n input.sessionID,\n skillNames,\n \"content\",\n state\n )\n }\n }\n }\n\n const contentToInject: string[] = []\n\n if (!state.initialSkillsInjected && initialFormattedContent) {\n contentToInject.push(initialFormattedContent)\n state.initialSkillsInjected = true\n log(\"info\", \"Injected initial preloaded skills\", {\n sessionID: input.sessionID,\n skills: initialSkills.map((s) => s.name),\n })\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings })\n if (formatted) {\n contentToInject.push(formatted)\n log(\"info\", \"Injected triggered skills\", {\n sessionID: input.sessionID,\n skills: pending.map((s) => s.name),\n })\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (contentToInject.length > 0) {\n firstTextPart.text = `${contentToInject.join(\"\\n\\n\")}\\n\\n---\\n\\n${firstTextPart.text}`\n }\n },\n\n \"tool.execute.after\": async (\n input: {\n tool: string\n sessionID: string\n callID: string\n },\n _output: {\n title: string\n output: string\n metadata: unknown\n }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n\n const toolArgs = (_output.metadata as { args?: Record<string, unknown> })\n ?.args\n if (!toolArgs) return\n\n const filePath = getFilePathFromArgs(toolArgs)\n if (!filePath) return\n\n const ext = extname(filePath)\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, extSkills, \"fileType\", state)\n }\n }\n\n if (config.pathPatterns) {\n const pathSkills = getSkillsForPath(filePath, config.pathPatterns)\n if (pathSkills.length > 0) {\n queueSkillsForInjection(input.sessionID, pathSkills, \"path\", state)\n }\n }\n },\n\n \"experimental.session.compacting\": async (\n input: { sessionID: string },\n output: { context: string[]; prompt?: string }\n ): Promise<void> => {\n if (!config.persistAfterCompaction) return\n\n const state = sessionStates.get(input.sessionID)\n if (!state || state.loadedSkills.size === 0) return\n\n const allLoadedSkills: ParsedSkill[] = []\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill) allLoadedSkills.push(skill)\n }\n\n if (allLoadedSkills.length === 0) return\n\n const formatted = formatSkillsForInjection(\n allLoadedSkills,\n { useSummaries: config.useSummaries, skillSettings: config.skillSettings }\n )\n output.context.push(\n `## Preloaded Skills\\n\\nThe following skills were loaded during this session and should persist:\\n\\n${formatted}`\n )\n\n state.initialSkillsInjected = false\n\n log(\"info\", \"Added all loaded skills to compaction context\", {\n sessionID: input.sessionID,\n skillCount: allLoadedSkills.length,\n })\n\n saveAnalytics()\n },\n\n event: async ({ event }: { event: Event }): Promise<void> => {\n if (\n event.type === \"session.deleted\" &&\n \"sessionID\" in event.properties\n ) {\n const sessionID = event.properties.sessionID as string\n sessionStates.delete(sessionID)\n pendingSkillInjections.delete(sessionID)\n analyticsData.delete(sessionID)\n log(\"debug\", \"Cleaned up session state\", { sessionID })\n saveAnalytics()\n }\n },\n }\n}\n\nexport default PreloadSkillsPlugin\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-plugin-preload-skills",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Smart skill loading for OpenCode — automatic, contextual, and budget-aware",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -56,6 +56,7 @@
56
56
  "devDependencies": {
57
57
  "@opencode-ai/plugin": "^1.0.85",
58
58
  "@types/node": "^22.0.0",
59
+ "@vitest/coverage-v8": "^4.0.18",
59
60
  "tsup": "^8.0.0",
60
61
  "typescript": "^5.7.0",
61
62
  "vitest": "^4.0.18"