opencode-plugin-preload-skills 1.4.0 → 1.5.1

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
@@ -23,6 +23,7 @@ A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads s
23
23
  | **Conditional Loading** | Load only if dependency exists |
24
24
  | **Token Budget** | Cap total skill tokens to protect context |
25
25
  | **Summaries Mode** | Load compact summaries instead of full content |
26
+ | **System Prompt Injection** | Inject skills into system prompt instead of messages |
26
27
  | **Usage Analytics** | Track which skills are actually used |
27
28
 
28
29
  > **⚠️ Warning:** Preloaded skills consume context window tokens. Use `maxTokens` to set a budget and `useSummaries` for large skills.
@@ -90,6 +91,7 @@ A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads s
90
91
  "large-skill": { "useSummary": true },
91
92
  "critical-skill": { "useSummary": false }
92
93
  },
94
+ "injectionMethod": "chatMessage",
93
95
  "maxTokens": 10000,
94
96
  "useSummaries": false,
95
97
  "analytics": false,
@@ -110,6 +112,7 @@ A powerful plugin for [OpenCode](https://opencode.ai) that intelligently loads s
110
112
  | `groups` | `Record<string, string[]>` | `{}` | Define skill bundles |
111
113
  | `conditionalSkills` | `ConditionalSkill[]` | `[]` | Load if condition met |
112
114
  | `skillSettings` | `Record<string, SkillSettings>` | `{}` | Per-skill settings |
115
+ | `injectionMethod` | `"chatMessage" \| "systemPrompt"` | `"chatMessage"` | Where to inject skills |
113
116
  | `maxTokens` | `number` | `undefined` | Max tokens for all skills |
114
117
  | `useSummaries` | `boolean` | `false` | Use skill summaries (global) |
115
118
  | `analytics` | `boolean` | `false` | Track skill usage |
@@ -278,6 +281,33 @@ Override global settings for specific skills:
278
281
 
279
282
  This lets you use full content for critical skills while summarizing large reference materials.
280
283
 
284
+ ### Injection Method
285
+
286
+ Choose where skills are injected:
287
+
288
+ ```json
289
+ {
290
+ "injectionMethod": "systemPrompt"
291
+ }
292
+ ```
293
+
294
+ **Methods:**
295
+
296
+ | Method | Description | Use Case |
297
+ |--------|-------------|----------|
298
+ | `chatMessage` (default) | Injects skills into user messages | One-time injection, visible in conversation |
299
+ | `systemPrompt` | Injects into system prompt via `experimental.chat.system.transform` hook | Persistent across all LLM calls, invisible to user |
300
+
301
+ **System prompt injection benefits:**
302
+ - Skills persist automatically (no need for `persistAfterCompaction`)
303
+ - Cleaner conversation history (skills not visible in messages)
304
+ - Skills included in every LLM call automatically
305
+
306
+ **Chat message injection benefits:**
307
+ - Skills visible in conversation for debugging
308
+ - Works with all OpenCode versions
309
+ - More control over when skills appear
310
+
281
311
  ### Usage Analytics
282
312
 
283
313
  Track which skills are loaded and how often:
package/dist/index.cjs CHANGED
@@ -175,6 +175,7 @@ var DEFAULT_CONFIG = {
175
175
  groups: {},
176
176
  conditionalSkills: [],
177
177
  skillSettings: {},
178
+ injectionMethod: "chatMessage",
178
179
  maxTokens: void 0,
179
180
  useSummaries: false,
180
181
  analytics: false,
@@ -247,7 +248,8 @@ function loadConfigFile(projectDir) {
247
248
  useSummaries: typeof parsed.useSummaries === "boolean" ? parsed.useSummaries : void 0,
248
249
  analytics: typeof parsed.analytics === "boolean" ? parsed.analytics : void 0,
249
250
  persistAfterCompaction: typeof parsed.persistAfterCompaction === "boolean" ? parsed.persistAfterCompaction : void 0,
250
- debug: typeof parsed.debug === "boolean" ? parsed.debug : void 0
251
+ debug: typeof parsed.debug === "boolean" ? parsed.debug : void 0,
252
+ injectionMethod: parsed.injectionMethod === "systemPrompt" || parsed.injectionMethod === "chatMessage" ? parsed.injectionMethod : void 0
251
253
  };
252
254
  } catch {
253
255
  return {};
@@ -331,6 +333,7 @@ var PreloadSkillsPlugin = async (ctx) => {
331
333
  lastLoaded: now
332
334
  });
333
335
  }
336
+ saveAnalytics();
334
337
  };
335
338
  const saveAnalytics = () => {
336
339
  if (!config.analytics) return;
@@ -426,6 +429,7 @@ var PreloadSkillsPlugin = async (ctx) => {
426
429
  return sessionStates.get(sessionID);
427
430
  };
428
431
  const pendingSkillInjections = /* @__PURE__ */ new Map();
432
+ const pendingToolFilePaths = /* @__PURE__ */ new Map();
429
433
  const queueSkillsForInjection = (sessionID, skillNames, triggerType, state) => {
430
434
  const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name));
431
435
  if (newSkillNames.length === 0) return;
@@ -449,7 +453,45 @@ var PreloadSkillsPlugin = async (ctx) => {
449
453
  });
450
454
  }
451
455
  };
456
+ const useSystemPromptInjection = config.injectionMethod === "systemPrompt";
452
457
  return {
458
+ "experimental.chat.system.transform": useSystemPromptInjection ? async (input, output) => {
459
+ if (!input.sessionID) return;
460
+ const state = getSessionState(input.sessionID);
461
+ const skillsToInject = [];
462
+ if (initialSkills.length > 0) {
463
+ skillsToInject.push(...initialSkills);
464
+ }
465
+ for (const name of state.loadedSkills) {
466
+ const skill = skillCache.get(name);
467
+ if (skill && !skillsToInject.find((s) => s.name === name)) {
468
+ skillsToInject.push(skill);
469
+ }
470
+ }
471
+ const pending = pendingSkillInjections.get(input.sessionID);
472
+ if (pending && pending.length > 0) {
473
+ for (const skill of pending) {
474
+ if (!skillsToInject.find((s) => s.name === skill.name)) {
475
+ skillsToInject.push(skill);
476
+ }
477
+ }
478
+ pendingSkillInjections.delete(input.sessionID);
479
+ }
480
+ if (skillsToInject.length > 0) {
481
+ const formatted = formatSkillsForInjection(skillsToInject, {
482
+ useSummaries: config.useSummaries,
483
+ skillSettings: config.skillSettings
484
+ });
485
+ output.system.push(formatted);
486
+ if (!state.initialSkillsInjected && initialSkills.length > 0) {
487
+ state.initialSkillsInjected = true;
488
+ log("info", "Injected skills into system prompt", {
489
+ sessionID: input.sessionID,
490
+ skills: skillsToInject.map((s) => s.name)
491
+ });
492
+ }
493
+ }
494
+ } : void 0,
453
495
  "chat.message": async (input, output) => {
454
496
  if (!input.sessionID) return;
455
497
  const state = getSessionState(input.sessionID);
@@ -478,53 +520,82 @@ var PreloadSkillsPlugin = async (ctx) => {
478
520
  }
479
521
  }
480
522
  }
481
- const contentToInject = [];
482
- if (!state.initialSkillsInjected && initialFormattedContent) {
483
- contentToInject.push(initialFormattedContent);
484
- state.initialSkillsInjected = true;
485
- log("info", "Injected initial preloaded skills", {
486
- sessionID: input.sessionID,
487
- skills: initialSkills.map((s) => s.name)
488
- });
489
- }
490
- const pending = pendingSkillInjections.get(input.sessionID);
491
- if (pending && pending.length > 0) {
492
- const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings });
493
- if (formatted) {
494
- contentToInject.push(formatted);
495
- log("info", "Injected triggered skills", {
523
+ if (!useSystemPromptInjection) {
524
+ const contentToInject = [];
525
+ if (!state.initialSkillsInjected && initialFormattedContent) {
526
+ contentToInject.push(initialFormattedContent);
527
+ state.initialSkillsInjected = true;
528
+ log("info", "Injected initial preloaded skills", {
496
529
  sessionID: input.sessionID,
497
- skills: pending.map((s) => s.name)
530
+ skills: initialSkills.map((s) => s.name)
498
531
  });
499
532
  }
500
- pendingSkillInjections.delete(input.sessionID);
501
- }
502
- if (contentToInject.length > 0) {
503
- firstTextPart.text = `${contentToInject.join("\n\n")}
533
+ const pending = pendingSkillInjections.get(input.sessionID);
534
+ if (pending && pending.length > 0) {
535
+ const formatted = formatSkillsForInjection(pending, {
536
+ useSummaries: config.useSummaries,
537
+ skillSettings: config.skillSettings
538
+ });
539
+ if (formatted) {
540
+ contentToInject.push(formatted);
541
+ log("info", "Injected triggered skills", {
542
+ sessionID: input.sessionID,
543
+ skills: pending.map((s) => s.name)
544
+ });
545
+ }
546
+ pendingSkillInjections.delete(input.sessionID);
547
+ }
548
+ if (contentToInject.length > 0) {
549
+ firstTextPart.text = `${contentToInject.join("\n\n")}
504
550
 
505
551
  ---
506
552
 
507
553
  ${firstTextPart.text}`;
554
+ }
555
+ }
556
+ },
557
+ "tool.execute.before": async (input, output) => {
558
+ if (!FILE_TOOLS.includes(input.tool)) return;
559
+ const filePath = getFilePathFromArgs(output.args);
560
+ if (filePath) {
561
+ pendingToolFilePaths.set(input.callID, filePath);
562
+ log("debug", "Captured file path from tool", {
563
+ tool: input.tool,
564
+ callID: input.callID,
565
+ filePath
566
+ });
508
567
  }
509
568
  },
510
569
  "tool.execute.after": async (input, _output) => {
511
570
  if (!FILE_TOOLS.includes(input.tool)) return;
512
571
  if (!input.sessionID) return;
572
+ const filePath = pendingToolFilePaths.get(input.callID);
573
+ pendingToolFilePaths.delete(input.callID);
574
+ if (!filePath) {
575
+ log("debug", "No file path found for tool call", {
576
+ tool: input.tool,
577
+ callID: input.callID
578
+ });
579
+ return;
580
+ }
513
581
  const state = getSessionState(input.sessionID);
514
- const toolArgs = _output.metadata?.args;
515
- if (!toolArgs) return;
516
- const filePath = getFilePathFromArgs(toolArgs);
517
- if (!filePath) return;
518
582
  const ext = path.extname(filePath);
583
+ log("debug", "Processing file access", {
584
+ tool: input.tool,
585
+ filePath,
586
+ extension: ext
587
+ });
519
588
  if (ext && config.fileTypeSkills) {
520
589
  const extSkills = getSkillsForExtension(ext, config.fileTypeSkills);
521
590
  if (extSkills.length > 0) {
591
+ log("debug", "Found skills for extension", { ext, skills: extSkills });
522
592
  queueSkillsForInjection(input.sessionID, extSkills, "fileType", state);
523
593
  }
524
594
  }
525
595
  if (config.pathPatterns) {
526
596
  const pathSkills = getSkillsForPath(filePath, config.pathPatterns);
527
597
  if (pathSkills.length > 0) {
598
+ log("debug", "Found skills for path pattern", { filePath, skills: pathSkills });
528
599
  queueSkillsForInjection(input.sessionID, pathSkills, "path", state);
529
600
  }
530
601
  }
@@ -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, 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"]}
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, Model } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillSettings,\n SkillUsageStats,\n AnalyticsData,\n InjectionMethod,\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 injectionMethod: \"chatMessage\",\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 injectionMethod:\n parsed.injectionMethod === \"systemPrompt\" ||\n parsed.injectionMethod === \"chatMessage\"\n ? (parsed.injectionMethod as InjectionMethod)\n : 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 saveAnalytics()\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 const pendingToolFilePaths = new Map<string, string>()\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 const useSystemPromptInjection = config.injectionMethod === \"systemPrompt\"\n\n return {\n \"experimental.chat.system.transform\": useSystemPromptInjection\n ? async (\n input: { sessionID?: string; model: Model },\n output: { system: string[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const skillsToInject: ParsedSkill[] = []\n\n if (initialSkills.length > 0) {\n skillsToInject.push(...initialSkills)\n }\n\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill && !skillsToInject.find((s) => s.name === name)) {\n skillsToInject.push(skill)\n }\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n for (const skill of pending) {\n if (!skillsToInject.find((s) => s.name === skill.name)) {\n skillsToInject.push(skill)\n }\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (skillsToInject.length > 0) {\n const formatted = formatSkillsForInjection(skillsToInject, {\n useSummaries: config.useSummaries,\n skillSettings: config.skillSettings,\n })\n output.system.push(formatted)\n\n if (!state.initialSkillsInjected && initialSkills.length > 0) {\n state.initialSkillsInjected = true\n log(\"info\", \"Injected skills into system prompt\", {\n sessionID: input.sessionID,\n skills: skillsToInject.map((s) => s.name),\n })\n }\n }\n }\n : undefined,\n\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 if (!useSystemPromptInjection) {\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, {\n useSummaries: config.useSummaries,\n skillSettings: config.skillSettings,\n })\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\n \"tool.execute.before\": async (\n input: { tool: string; sessionID: string; callID: string },\n output: { args: Record<string, unknown> }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n\n const filePath = getFilePathFromArgs(output.args)\n if (filePath) {\n pendingToolFilePaths.set(input.callID, filePath)\n log(\"debug\", \"Captured file path from tool\", {\n tool: input.tool,\n callID: input.callID,\n filePath,\n })\n }\n },\n\n \"tool.execute.after\": async (\n input: { tool: string; sessionID: string; callID: string },\n _output: { title: string; output: string; metadata: unknown }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const filePath = pendingToolFilePaths.get(input.callID)\n pendingToolFilePaths.delete(input.callID)\n\n if (!filePath) {\n log(\"debug\", \"No file path found for tool call\", {\n tool: input.tool,\n callID: input.callID,\n })\n return\n }\n\n const state = getSessionState(input.sessionID)\n const ext = extname(filePath)\n\n log(\"debug\", \"Processing file access\", {\n tool: input.tool,\n filePath,\n extension: ext,\n })\n\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n log(\"debug\", \"Found skills for extension\", { ext, skills: extSkills })\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 log(\"debug\", \"Found skills for path pattern\", { filePath, skills: pathSkills })\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
@@ -3,6 +3,7 @@ import { Plugin } from '@opencode-ai/plugin';
3
3
  interface SkillSettings {
4
4
  useSummary?: boolean;
5
5
  }
6
+ type InjectionMethod = "systemPrompt" | "chatMessage";
6
7
  interface PreloadSkillsConfig {
7
8
  skills: string[];
8
9
  fileTypeSkills?: Record<string, string[]>;
@@ -12,6 +13,7 @@ interface PreloadSkillsConfig {
12
13
  groups?: Record<string, string[]>;
13
14
  conditionalSkills?: ConditionalSkill[];
14
15
  skillSettings?: Record<string, SkillSettings>;
16
+ injectionMethod?: InjectionMethod;
15
17
  maxTokens?: number;
16
18
  useSummaries?: boolean;
17
19
  analytics?: boolean;
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ import { Plugin } from '@opencode-ai/plugin';
3
3
  interface SkillSettings {
4
4
  useSummary?: boolean;
5
5
  }
6
+ type InjectionMethod = "systemPrompt" | "chatMessage";
6
7
  interface PreloadSkillsConfig {
7
8
  skills: string[];
8
9
  fileTypeSkills?: Record<string, string[]>;
@@ -12,6 +13,7 @@ interface PreloadSkillsConfig {
12
13
  groups?: Record<string, string[]>;
13
14
  conditionalSkills?: ConditionalSkill[];
14
15
  skillSettings?: Record<string, SkillSettings>;
16
+ injectionMethod?: InjectionMethod;
15
17
  maxTokens?: number;
16
18
  useSummaries?: boolean;
17
19
  analytics?: boolean;
package/dist/index.js CHANGED
@@ -171,6 +171,7 @@ var DEFAULT_CONFIG = {
171
171
  groups: {},
172
172
  conditionalSkills: [],
173
173
  skillSettings: {},
174
+ injectionMethod: "chatMessage",
174
175
  maxTokens: void 0,
175
176
  useSummaries: false,
176
177
  analytics: false,
@@ -243,7 +244,8 @@ function loadConfigFile(projectDir) {
243
244
  useSummaries: typeof parsed.useSummaries === "boolean" ? parsed.useSummaries : void 0,
244
245
  analytics: typeof parsed.analytics === "boolean" ? parsed.analytics : void 0,
245
246
  persistAfterCompaction: typeof parsed.persistAfterCompaction === "boolean" ? parsed.persistAfterCompaction : void 0,
246
- debug: typeof parsed.debug === "boolean" ? parsed.debug : void 0
247
+ debug: typeof parsed.debug === "boolean" ? parsed.debug : void 0,
248
+ injectionMethod: parsed.injectionMethod === "systemPrompt" || parsed.injectionMethod === "chatMessage" ? parsed.injectionMethod : void 0
247
249
  };
248
250
  } catch {
249
251
  return {};
@@ -327,6 +329,7 @@ var PreloadSkillsPlugin = async (ctx) => {
327
329
  lastLoaded: now
328
330
  });
329
331
  }
332
+ saveAnalytics();
330
333
  };
331
334
  const saveAnalytics = () => {
332
335
  if (!config.analytics) return;
@@ -422,6 +425,7 @@ var PreloadSkillsPlugin = async (ctx) => {
422
425
  return sessionStates.get(sessionID);
423
426
  };
424
427
  const pendingSkillInjections = /* @__PURE__ */ new Map();
428
+ const pendingToolFilePaths = /* @__PURE__ */ new Map();
425
429
  const queueSkillsForInjection = (sessionID, skillNames, triggerType, state) => {
426
430
  const newSkillNames = skillNames.filter((name) => !state.loadedSkills.has(name));
427
431
  if (newSkillNames.length === 0) return;
@@ -445,7 +449,45 @@ var PreloadSkillsPlugin = async (ctx) => {
445
449
  });
446
450
  }
447
451
  };
452
+ const useSystemPromptInjection = config.injectionMethod === "systemPrompt";
448
453
  return {
454
+ "experimental.chat.system.transform": useSystemPromptInjection ? async (input, output) => {
455
+ if (!input.sessionID) return;
456
+ const state = getSessionState(input.sessionID);
457
+ const skillsToInject = [];
458
+ if (initialSkills.length > 0) {
459
+ skillsToInject.push(...initialSkills);
460
+ }
461
+ for (const name of state.loadedSkills) {
462
+ const skill = skillCache.get(name);
463
+ if (skill && !skillsToInject.find((s) => s.name === name)) {
464
+ skillsToInject.push(skill);
465
+ }
466
+ }
467
+ const pending = pendingSkillInjections.get(input.sessionID);
468
+ if (pending && pending.length > 0) {
469
+ for (const skill of pending) {
470
+ if (!skillsToInject.find((s) => s.name === skill.name)) {
471
+ skillsToInject.push(skill);
472
+ }
473
+ }
474
+ pendingSkillInjections.delete(input.sessionID);
475
+ }
476
+ if (skillsToInject.length > 0) {
477
+ const formatted = formatSkillsForInjection(skillsToInject, {
478
+ useSummaries: config.useSummaries,
479
+ skillSettings: config.skillSettings
480
+ });
481
+ output.system.push(formatted);
482
+ if (!state.initialSkillsInjected && initialSkills.length > 0) {
483
+ state.initialSkillsInjected = true;
484
+ log("info", "Injected skills into system prompt", {
485
+ sessionID: input.sessionID,
486
+ skills: skillsToInject.map((s) => s.name)
487
+ });
488
+ }
489
+ }
490
+ } : void 0,
449
491
  "chat.message": async (input, output) => {
450
492
  if (!input.sessionID) return;
451
493
  const state = getSessionState(input.sessionID);
@@ -474,53 +516,82 @@ var PreloadSkillsPlugin = async (ctx) => {
474
516
  }
475
517
  }
476
518
  }
477
- const contentToInject = [];
478
- if (!state.initialSkillsInjected && initialFormattedContent) {
479
- contentToInject.push(initialFormattedContent);
480
- state.initialSkillsInjected = true;
481
- log("info", "Injected initial preloaded skills", {
482
- sessionID: input.sessionID,
483
- skills: initialSkills.map((s) => s.name)
484
- });
485
- }
486
- const pending = pendingSkillInjections.get(input.sessionID);
487
- if (pending && pending.length > 0) {
488
- const formatted = formatSkillsForInjection(pending, { useSummaries: config.useSummaries, skillSettings: config.skillSettings });
489
- if (formatted) {
490
- contentToInject.push(formatted);
491
- log("info", "Injected triggered skills", {
519
+ if (!useSystemPromptInjection) {
520
+ const contentToInject = [];
521
+ if (!state.initialSkillsInjected && initialFormattedContent) {
522
+ contentToInject.push(initialFormattedContent);
523
+ state.initialSkillsInjected = true;
524
+ log("info", "Injected initial preloaded skills", {
492
525
  sessionID: input.sessionID,
493
- skills: pending.map((s) => s.name)
526
+ skills: initialSkills.map((s) => s.name)
494
527
  });
495
528
  }
496
- pendingSkillInjections.delete(input.sessionID);
497
- }
498
- if (contentToInject.length > 0) {
499
- firstTextPart.text = `${contentToInject.join("\n\n")}
529
+ const pending = pendingSkillInjections.get(input.sessionID);
530
+ if (pending && pending.length > 0) {
531
+ const formatted = formatSkillsForInjection(pending, {
532
+ useSummaries: config.useSummaries,
533
+ skillSettings: config.skillSettings
534
+ });
535
+ if (formatted) {
536
+ contentToInject.push(formatted);
537
+ log("info", "Injected triggered skills", {
538
+ sessionID: input.sessionID,
539
+ skills: pending.map((s) => s.name)
540
+ });
541
+ }
542
+ pendingSkillInjections.delete(input.sessionID);
543
+ }
544
+ if (contentToInject.length > 0) {
545
+ firstTextPart.text = `${contentToInject.join("\n\n")}
500
546
 
501
547
  ---
502
548
 
503
549
  ${firstTextPart.text}`;
550
+ }
551
+ }
552
+ },
553
+ "tool.execute.before": async (input, output) => {
554
+ if (!FILE_TOOLS.includes(input.tool)) return;
555
+ const filePath = getFilePathFromArgs(output.args);
556
+ if (filePath) {
557
+ pendingToolFilePaths.set(input.callID, filePath);
558
+ log("debug", "Captured file path from tool", {
559
+ tool: input.tool,
560
+ callID: input.callID,
561
+ filePath
562
+ });
504
563
  }
505
564
  },
506
565
  "tool.execute.after": async (input, _output) => {
507
566
  if (!FILE_TOOLS.includes(input.tool)) return;
508
567
  if (!input.sessionID) return;
568
+ const filePath = pendingToolFilePaths.get(input.callID);
569
+ pendingToolFilePaths.delete(input.callID);
570
+ if (!filePath) {
571
+ log("debug", "No file path found for tool call", {
572
+ tool: input.tool,
573
+ callID: input.callID
574
+ });
575
+ return;
576
+ }
509
577
  const state = getSessionState(input.sessionID);
510
- const toolArgs = _output.metadata?.args;
511
- if (!toolArgs) return;
512
- const filePath = getFilePathFromArgs(toolArgs);
513
- if (!filePath) return;
514
578
  const ext = extname(filePath);
579
+ log("debug", "Processing file access", {
580
+ tool: input.tool,
581
+ filePath,
582
+ extension: ext
583
+ });
515
584
  if (ext && config.fileTypeSkills) {
516
585
  const extSkills = getSkillsForExtension(ext, config.fileTypeSkills);
517
586
  if (extSkills.length > 0) {
587
+ log("debug", "Found skills for extension", { ext, skills: extSkills });
518
588
  queueSkillsForInjection(input.sessionID, extSkills, "fileType", state);
519
589
  }
520
590
  }
521
591
  if (config.pathPatterns) {
522
592
  const pathSkills = getSkillsForPath(filePath, config.pathPatterns);
523
593
  if (pathSkills.length > 0) {
594
+ log("debug", "Found skills for path pattern", { filePath, skills: pathSkills });
524
595
  queueSkillsForInjection(input.sessionID, pathSkills, "path", state);
525
596
  }
526
597
  }
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":";;;;;AAGO,SAAS,eAAe,IAAA,EAAsB;AACnD,EAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,CAAC,CAAA;AAClC;AAEO,SAAS,gBAAA,CAAiB,UAAkB,OAAA,EAA0B;AAC3E,EAAA,IAAI,eAAe,OAAA,CAChB,OAAA,CAAQ,SAAA,EAAW,qBAAyB,EAC5C,OAAA,CAAQ,OAAA,EAAS,gBAAoB,CAAA,CACrC,QAAQ,KAAA,EAAO,gBAAoB,CAAA,CACnC,OAAA,CAAQ,OAAO,cAAkB,CAAA;AAEpC,EAAA,YAAA,GAAe,YAAA,CAAa,OAAA,CAAQ,mBAAA,EAAqB,MAAM,CAAA;AAE/D,EAAA,YAAA,GAAe,YAAA,CACZ,OAAA,CAAQ,0BAAA,EAA4B,aAAa,EACjD,OAAA,CAAQ,qBAAA,EAAuB,IAAI,CAAA,CACnC,QAAQ,qBAAA,EAAuB,OAAO,CAAA,CACtC,OAAA,CAAQ,qBAAqB,MAAM,CAAA;AAEtC,EAAA,MAAM,KAAA,GAAQ,IAAI,MAAA,CAAO,CAAA,CAAA,EAAI,YAAY,CAAA,CAAA,CAAG,CAAA;AAC5C,EAAA,OAAO,KAAA,CAAM,KAAK,QAAQ,CAAA;AAC5B;AASO,SAAS,cAAA,CACd,WACA,UAAA,EACS;AACT,EAAA,IAAI,UAAU,UAAA,EAAY;AACxB,IAAA,MAAM,QAAA,GAAW,IAAA,CAAK,UAAA,EAAY,SAAA,CAAU,UAAU,CAAA;AACtD,IAAA,IAAI,CAAC,UAAA,CAAW,QAAQ,CAAA,EAAG,OAAO,KAAA;AAAA,EACpC;AAEA,EAAA,IAAI,UAAU,oBAAA,EAAsB;AAClC,IAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,UAAA,EAAY,cAAc,CAAA;AACvD,IAAA,IAAI,CAAC,UAAA,CAAW,eAAe,CAAA,EAAG,OAAO,KAAA;AAEzC,IAAA,IAAI;AACF,MAAA,MAAM,cAAc,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,eAAA,EAAiB,OAAO,CAAC,CAAA;AACrE,MAAA,MAAM,IAAA,GAAO;AAAA,QACX,GAAG,WAAA,CAAY,YAAA;AAAA,QACf,GAAG,WAAA,CAAY,eAAA;AAAA,QACf,GAAG,WAAA,CAAY;AAAA,OACjB;AACA,MAAA,IAAI,CAAC,IAAA,CAAK,SAAA,CAAU,oBAAoB,GAAG,OAAO,KAAA;AAAA,IACpD,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,SAAA,CAAU,MAAM,GAAG,OAAO,KAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,IAAA;AACT;AAOO,SAAS,mBAAA,CAAoB,MAAc,QAAA,EAA6B;AAC7E,EAAA,MAAM,SAAA,GAAY,KAAK,WAAA,EAAY;AACnC,EAAA,OAAO,QAAA,CAAS,KAAK,CAAC,EAAA,KAAO,UAAU,QAAA,CAAS,EAAA,CAAG,WAAA,EAAa,CAAC,CAAA;AACnE;;;ACpEA,IAAM,cAAA,GAAiB,UAAA;AAEvB,IAAM,kBAAA,GAAqB;AAAA,EACzB,CAAC,GAAA,KAAgBA,IAAAA,CAAK,GAAA,EAAK,aAAa,QAAQ,CAAA;AAAA,EAChD,CAAC,GAAA,KAAgBA,IAAAA,CAAK,GAAA,EAAK,WAAW,QAAQ,CAAA;AAAA,EAC9C,MAAMA,IAAAA,CAAK,OAAA,EAAQ,EAAG,SAAA,EAAW,YAAY,QAAQ,CAAA;AAAA,EACrD,MAAMA,IAAAA,CAAK,OAAA,EAAQ,EAAG,WAAW,QAAQ;AAC3C,CAAA;AAEA,SAAS,aAAA,CAAc,WAAmB,UAAA,EAAmC;AAC3E,EAAA,KAAA,MAAW,WAAW,kBAAA,EAAoB;AACxC,IAAA,MAAM,QAAA,GAAW,QAAQ,UAAU,CAAA;AACnC,IAAA,MAAM,SAAA,GAAYA,IAAAA,CAAK,QAAA,EAAU,SAAA,EAAW,cAAc,CAAA;AAE1D,IAAA,IAAIC,UAAAA,CAAW,SAAS,CAAA,EAAG;AACzB,MAAA,OAAO,SAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAQA,SAAS,iBAAiB,OAAA,EAAkC;AAC1D,EAAA,MAAM,gBAAA,GAAmB,OAAA,CAAQ,KAAA,CAAM,0BAA0B,CAAA;AACjE,EAAA,IAAI,CAAC,gBAAA,GAAmB,CAAC,CAAA,EAAG;AAC1B,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,WAAA,GAAc,iBAAiB,CAAC,CAAA;AACtC,EAAA,MAAM,SAA0B,EAAC;AAEjC,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,KAAA,CAAM,iBAAiB,CAAA;AACrD,EAAA,IAAI,SAAA,GAAY,CAAC,CAAA,EAAG;AAClB,IAAA,MAAA,CAAO,IAAA,GAAO,SAAA,CAAU,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,EAClC;AAEA,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,KAAA,CAAM,wBAAwB,CAAA;AAC5D,EAAA,IAAI,SAAA,GAAY,CAAC,CAAA,EAAG;AAClB,IAAA,MAAA,CAAO,WAAA,GAAc,SAAA,CAAU,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,EACzC;AAEA,EAAA,MAAM,YAAA,GAAe,WAAA,CAAY,KAAA,CAAM,oBAAoB,CAAA;AAC3D,EAAA,IAAI,YAAA,GAAe,CAAC,CAAA,EAAG;AACrB,IAAA,MAAA,CAAO,OAAA,GAAU,YAAA,CAAa,CAAC,CAAA,CAAE,IAAA,EAAK;AAAA,EACxC;AAEA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,kBAAA,CAAmB,OAAA,EAAiB,SAAA,GAAoB,GAAA,EAAa;AAC5E,EAAA,MAAM,kBAAA,GAAqB,OAAA,CAAQ,OAAA,CAAQ,8BAAA,EAAgC,EAAE,CAAA;AAE7E,EAAA,MAAM,eAAe,kBAAA,CAAmB,KAAA,CAAM,QAAQ,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAC9D,EAAA,MAAM,OAAA,GAAU,YAAA,CACb,OAAA,CAAQ,YAAA,EAAc,EAAE,EACxB,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA,CACnB,IAAA,EAAK;AAER,EAAA,IAAI,OAAA,CAAQ,MAAA,IAAU,SAAA,EAAW,OAAO,OAAA;AACxC,EAAA,OAAO,OAAA,CAAQ,MAAM,CAAA,EAAG,SAAS,EAAE,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA,GAAI,KAAA;AAC9D;AAEO,SAAS,SAAA,CAAU,WAAmB,UAAA,EAAwC;AACnF,EAAA,MAAM,QAAA,GAAW,aAAA,CAAc,SAAA,EAAW,UAAU,CAAA;AAEpD,EAAA,IAAI,CAAC,QAAA,EAAU;AACb,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAUC,YAAAA,CAAa,QAAA,EAAU,OAAO,CAAA;AAC9C,IAAA,MAAM,EAAE,IAAA,EAAM,WAAA,EAAa,OAAA,EAAQ,GAAI,iBAAiB,OAAO,CAAA;AAE/D,IAAA,OAAO;AAAA,MACL,MAAM,IAAA,IAAQ,SAAA;AAAA,MACd,aAAa,WAAA,IAAe,EAAA;AAAA,MAC5B,OAAA,EAAS,OAAA,IAAW,kBAAA,CAAmB,OAAO,CAAA;AAAA,MAC9C,OAAA;AAAA,MACA,QAAA;AAAA,MACA,UAAA,EAAY,eAAe,OAAO;AAAA,KACpC;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAEO,SAAS,UAAA,CAAW,YAAsB,UAAA,EAAmC;AAClF,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,UAAU,CAAA,EAAG;AAC9B,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,MAAM,SAAwB,EAAC;AAE/B,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,IAAA,EAAM,UAAU,CAAA;AACxC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AAAA,IACnB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,wBAAA,CACd,MAAA,EACA,OAAA,GAAmC,KAAA,EAC3B;AACR,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,IAAK,MAAA,CAAO,WAAW,CAAA,EAAG;AACjD,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAsB,OAAO,OAAA,KAAY,YAC3C,EAAE,YAAA,EAAc,SAAQ,GACxB,OAAA;AAEJ,EAAA,MAAM,kBAAA,GAAqB,KAAK,YAAA,IAAgB,KAAA;AAChD,EAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,aAAA,IAAiB,EAAC;AAE7C,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,KAAU;AAClC,IAAA,MAAM,eAAA,GAAkB,aAAA,CAAc,KAAA,CAAM,IAAI,CAAA,EAAG,UAAA;AACnD,IAAA,MAAM,mBAAmB,eAAA,IAAmB,kBAAA;AAC5C,IAAA,MAAM,UAAU,gBAAA,IAAoB,KAAA,CAAM,OAAA,GAAU,KAAA,CAAM,UAAU,KAAA,CAAM,OAAA;AAC1E,IAAA,OAAO,CAAA,uBAAA,EAA0B,MAAM,IAAI,CAAA;AAAA,EAAO,OAAO;AAAA,kBAAA,CAAA;AAAA,EAC3D,CAAC,CAAA;AAED,EAAA,OAAO,CAAA;AAAA;;AAAA,EAGP,KAAA,CAAM,IAAA,CAAK,MAAM,CAAC;AAAA,mBAAA,CAAA;AAEpB;AAEO,SAAS,qBAAqB,MAAA,EAA+B;AAClE,EAAA,OAAO,MAAA,CAAO,OAAO,CAAC,GAAA,EAAK,UAAU,GAAA,GAAM,KAAA,CAAM,YAAY,CAAC,CAAA;AAChE;AAEO,SAAS,yBAAA,CACd,QACA,SAAA,EACe;AACf,EAAA,MAAM,SAAwB,EAAC;AAC/B,EAAA,IAAI,WAAA,GAAc,CAAA;AAElB,EAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,IAAA,IAAI,WAAA,GAAc,KAAA,CAAM,UAAA,IAAc,SAAA,EAAW;AAC/C,MAAA,MAAA,CAAO,KAAK,KAAK,CAAA;AACjB,MAAA,WAAA,IAAe,KAAA,CAAM,UAAA;AAAA,IACvB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;;;AC1IA,IAAM,eAAA,GAAkB,qBAAA;AACxB,IAAM,kBAAA,GAAqB,+BAAA;AAC3B,IAAM,aAAa,CAAC,MAAA,EAAQ,MAAA,EAAQ,OAAA,EAAS,QAAQ,MAAM,CAAA;AAE3D,IAAM,cAAA,GAAsC;AAAA,EAC1C,QAAQ,EAAC;AAAA,EACT,gBAAgB,EAAC;AAAA,EACjB,aAAa,EAAC;AAAA,EACd,cAAc,EAAC;AAAA,EACf,iBAAiB,EAAC;AAAA,EAClB,QAAQ,EAAC;AAAA,EACT,mBAAmB,EAAC;AAAA,EACpB,eAAe,EAAC;AAAA,EAChB,SAAA,EAAW,MAAA;AAAA,EACX,YAAA,EAAc,KAAA;AAAA,EACd,SAAA,EAAW,KAAA;AAAA,EACX,sBAAA,EAAwB,IAAA;AAAA,EACxB,KAAA,EAAO;AACT,CAAA;AAEA,SAAS,eAAe,UAAA,EAAmC;AACzD,EAAA,MAAM,SAAA,GAAY;AAAA,IAChBF,IAAAA,CAAK,UAAA,EAAY,WAAA,EAAa,eAAe,CAAA;AAAA,IAC7CA,IAAAA,CAAK,YAAY,eAAe,CAAA;AAAA,IAChCA,IAAAA,CAAKG,OAAAA,EAAQ,EAAG,SAAA,EAAW,YAAY,eAAe;AAAA,GACxD;AAEA,EAAA,KAAA,MAAW,QAAQ,SAAA,EAAW;AAC5B,IAAA,IAAIF,UAAAA,CAAW,IAAI,CAAA,EAAG;AACpB,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,uBAAuB,GAAA,EAAwC;AACtE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,SAAiB,EAAC;AAE7C,EAAA,MAAM,SAAmC,EAAC;AAC1C,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AAC9C,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,MAAA,CAAO,GAAG,IAAI,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,OAAO,MAAM,QAAQ,CAAA;AAAA,IACzD;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,uBAAuB,GAAA,EAAkC;AAChE,EAAA,IAAI,CAAC,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA,SAAU,EAAC;AAEjC,EAAA,OAAO,GAAA,CAAI,MAAA;AAAA,IACT,CAAC,IAAA,KACC,OAAO,IAAA,KAAS,QAAA,IAChB,IAAA,KAAS,IAAA,IACT,OAAO,IAAA,CAAK,KAAA,KAAU,QAAA,IACtB,OAAO,KAAK,EAAA,KAAO;AAAA,GACvB;AACF;AAEA,SAAS,mBAAmB,GAAA,EAA6C;AACvE,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,SAAiB,EAAC;AAE7C,EAAA,MAAM,SAAwC,EAAC;AAC/C,EAAA,KAAA,MAAW,CAAC,SAAA,EAAW,QAAQ,KAAK,MAAA,CAAO,OAAA,CAAQ,GAAG,CAAA,EAAG;AACvD,IAAA,IAAI,OAAO,QAAA,KAAa,QAAA,IAAY,QAAA,KAAa,IAAA,EAAM;AACrD,MAAA,MAAM,SAAwB,EAAC;AAC/B,MAAA,IAAI,YAAA,IAAgB,QAAA,IAAY,OAAO,QAAA,CAAS,eAAe,SAAA,EAAW;AACxE,QAAA,MAAA,CAAO,aAAa,QAAA,CAAS,UAAA;AAAA,MAC/B;AACA,MAAA,IAAI,MAAA,CAAO,IAAA,CAAK,MAAM,CAAA,CAAE,SAAS,CAAA,EAAG;AAClC,QAAA,MAAA,CAAO,SAAS,CAAA,GAAI,MAAA;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAEA,SAAS,eAAe,UAAA,EAAkD;AACxE,EAAA,MAAM,UAAA,GAAa,eAAe,UAAU,CAAA;AAC5C,EAAA,IAAI,CAAC,UAAA,EAAY;AACf,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,IAAI;AACF,IAAA,MAAM,OAAA,GAAUC,YAAAA,CAAa,UAAA,EAAY,OAAO,CAAA;AAChD,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,KAAA,CAAM,OAAO,CAAA;AAEjC,IAAA,OAAO;AAAA,MACL,MAAA,EAAQ,MAAM,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,GAAI,MAAA,CAAO,SAAS,EAAC;AAAA,MACxD,cAAA,EAAgB,sBAAA,CAAuB,MAAA,CAAO,cAAc,CAAA;AAAA,MAC5D,WAAA,EAAa,sBAAA,CAAuB,MAAA,CAAO,WAAW,CAAA;AAAA,MACtD,YAAA,EAAc,sBAAA,CAAuB,MAAA,CAAO,YAAY,CAAA;AAAA,MACxD,eAAA,EAAiB,sBAAA,CAAuB,MAAA,CAAO,eAAe,CAAA;AAAA,MAC9D,MAAA,EAAQ,sBAAA,CAAuB,MAAA,CAAO,MAAM,CAAA;AAAA,MAC5C,iBAAA,EAAmB,sBAAA,CAAuB,MAAA,CAAO,iBAAiB,CAAA;AAAA,MAClE,aAAA,EAAe,kBAAA,CAAmB,MAAA,CAAO,aAAa,CAAA;AAAA,MACtD,WACE,OAAO,MAAA,CAAO,SAAA,KAAc,QAAA,GAAW,OAAO,SAAA,GAAY,KAAA,CAAA;AAAA,MAC5D,cACE,OAAO,MAAA,CAAO,YAAA,KAAiB,SAAA,GAC3B,OAAO,YAAA,GACP,KAAA,CAAA;AAAA,MACN,WACE,OAAO,MAAA,CAAO,SAAA,KAAc,SAAA,GAAY,OAAO,SAAA,GAAY,KAAA,CAAA;AAAA,MAC7D,wBACE,OAAO,MAAA,CAAO,sBAAA,KAA2B,SAAA,GACrC,OAAO,sBAAA,GACP,KAAA,CAAA;AAAA,MACN,OAAO,OAAO,MAAA,CAAO,KAAA,KAAU,SAAA,GAAY,OAAO,KAAA,GAAQ,KAAA;AAAA,KAC5D;AAAA,EACF,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,EAAC;AAAA,EACV;AACF;AAEA,SAAS,oBAAoB,IAAA,EAA8C;AACzE,EAAA,IAAI,OAAO,IAAA,CAAK,QAAA,KAAa,QAAA,SAAiB,IAAA,CAAK,QAAA;AACnD,EAAA,IAAI,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,SAAiB,IAAA,CAAK,IAAA;AAC/C,EAAA,IAAI,OAAO,IAAA,CAAK,IAAA,KAAS,QAAA,SAAiB,IAAA,CAAK,IAAA;AAC/C,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,qBAAA,CACP,KACA,cAAA,EACU;AACV,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,cAAc,CAAA,EAAG;AAClE,IAAA,MAAM,UAAA,GAAa,OAAA,CAAQ,KAAA,CAAM,GAAG,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAA,EAAK,CAAE,WAAA,EAAa,CAAA;AACvE,IAAA,IAAI,UAAA,CAAW,QAAA,CAAS,GAAA,CAAI,WAAA,EAAa,CAAA,EAAG;AAC1C,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA,IAC3B;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AAC5B;AAEA,SAAS,gBAAA,CACP,UACA,YAAA,EACU;AACV,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,KAAA,MAAW,CAAC,OAAA,EAAS,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,EAAG;AAChE,IAAA,IAAI,gBAAA,CAAiB,QAAA,EAAU,OAAO,CAAA,EAAG;AACvC,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA;AAAA,IAC3B;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,MAAM,CAAC,CAAA;AAC5B;AAEA,SAAS,kBAAA,CACP,YACA,MAAA,EACU;AACV,EAAA,MAAM,WAAqB,EAAC;AAE5B,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,IAAI,IAAA,CAAK,WAAW,GAAG,CAAA,IAAK,OAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,EAAG;AACjD,MAAA,QAAA,CAAS,KAAK,GAAG,MAAA,CAAO,KAAK,KAAA,CAAM,CAAC,CAAC,CAAE,CAAA;AAAA,IACzC,CAAA,MAAO;AACL,MAAA,QAAA,CAAS,KAAK,IAAI,CAAA;AAAA,IACpB;AAAA,EACF;AAEA,EAAA,OAAO,CAAC,GAAG,IAAI,GAAA,CAAI,QAAQ,CAAC,CAAA;AAC9B;AAEO,IAAM,mBAAA,GAA8B,OAAO,GAAA,KAAqB;AACrE,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAA0B;AACpD,EAAA,MAAM,aAAA,uBAAoB,GAAA,EAA2B;AAErD,EAAA,MAAM,UAAA,GAAa,cAAA,CAAe,GAAA,CAAI,SAAS,CAAA;AAC/C,EAAA,MAAM,MAAA,GAA8B;AAAA,IAClC,GAAG,cAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,GAAA,GAAM,CACV,KAAA,EACA,OAAA,EACA,KAAA,KACG;AACH,IAAA,IAAI,KAAA,KAAU,OAAA,IAAW,CAAC,MAAA,CAAO,KAAA,EAAO;AAExC,IAAA,GAAA,CAAI,MAAA,CAAO,IAAI,GAAA,CAAI;AAAA,MACjB,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS,gBAAA;AAAA,QACT,KAAA;AAAA,QACA,OAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA;AAAA,EACH,CAAA;AAEA,EAAA,MAAM,eAAA,GAAkB,CACtB,SAAA,EACA,SAAA,EACA,WAAA,KACG;AACH,IAAA,IAAI,CAAC,OAAO,SAAA,EAAW;AAEvB,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,EAAG;AACjC,MAAA,aAAA,CAAc,IAAI,SAAA,EAAW;AAAA,QAC3B,SAAA,EAAW,SAAA;AAAA,QACX,UAAA,sBAAgB,GAAA;AAAI,OACrB,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,IAAA,GAAO,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA;AACxC,IAAA,MAAM,GAAA,GAAM,KAAK,GAAA,EAAI;AAErB,IAAA,IAAI,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA,EAAG;AAClC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,UAAA,CAAW,GAAA,CAAI,SAAS,CAAA;AAC3C,MAAA,KAAA,CAAM,SAAA,EAAA;AACN,MAAA,KAAA,CAAM,UAAA,GAAa,GAAA;AAAA,IACrB,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,UAAA,CAAW,IAAI,SAAA,EAAW;AAAA,QAC7B,SAAA;AAAA,QACA,SAAA,EAAW,CAAA;AAAA,QACX,WAAA;AAAA,QACA,WAAA,EAAa,GAAA;AAAA,QACb,UAAA,EAAY;AAAA,OACb,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,gBAAgB,MAAM;AAC1B,IAAA,IAAI,CAAC,OAAO,SAAA,EAAW;AAEvB,IAAA,IAAI;AACF,MAAA,MAAM,aAAA,GAAgBF,IAAAA,CAAK,GAAA,CAAI,SAAA,EAAW,aAAa,kBAAkB,CAAA;AACzE,MAAA,MAAM,GAAA,GAAM,QAAQ,aAAa,CAAA;AACjC,MAAA,IAAI,CAACC,UAAAA,CAAW,GAAG,CAAA,EAAG;AACpB,QAAA,SAAA,CAAU,GAAA,EAAK,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA;AAAA,MACpC;AAEA,MAAA,MAAM,eAAwC,EAAC;AAC/C,MAAA,KAAA,MAAW,CAAC,SAAA,EAAW,IAAI,CAAA,IAAK,aAAA,EAAe;AAC7C,QAAA,YAAA,CAAa,SAAS,CAAA,GAAI;AAAA,UACxB,WAAW,IAAA,CAAK,SAAA;AAAA,UAChB,UAAA,EAAY,MAAA,CAAO,WAAA,CAAY,IAAA,CAAK,UAAU;AAAA,SAChD;AAAA,MACF;AAEA,MAAA,aAAA,CAAc,eAAe,IAAA,CAAK,SAAA,CAAU,YAAA,EAAc,IAAA,EAAM,CAAC,CAAC,CAAA;AAAA,IACpE,CAAA,CAAA,MAAQ;AACN,MAAA,GAAA,CAAI,QAAQ,0BAA0B,CAAA;AAAA,IACxC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAyB;AAEhD,EAAA,MAAM,oBAAA,GAAuB,CAC3B,UAAA,EACA,aAAA,EACA,aACA,SAAA,KACkD;AAClD,IAAA,MAAM,WAAW,kBAAA,CAAmB,UAAA,EAAY,MAAA,CAAO,MAAA,IAAU,EAAE,CAAA;AACnE,IAAA,IAAI,MAAA,GAAS,UAAA,CAAW,QAAA,EAAU,GAAA,CAAI,SAAS,CAAA;AAE/C,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,UAAA,CAAW,GAAA,CAAI,KAAA,CAAM,IAAA,EAAM,KAAK,CAAA;AAAA,IAClC;AAEA,IAAA,IAAI,OAAO,SAAA,EAAW;AACpB,MAAA,MAAM,eAAA,GAAkB,OAAO,SAAA,GAAY,aAAA;AAC3C,MAAA,MAAA,GAAS,yBAAA,CAA0B,QAAQ,eAAe,CAAA;AAAA,IAC5D;AAEA,IAAA,KAAA,MAAW,SAAS,MAAA,EAAQ;AAC1B,MAAA,eAAA,CAAgB,SAAA,EAAW,KAAA,CAAM,IAAA,EAAM,WAAW,CAAA;AAAA,IACpD;AAEA,IAAA,OAAO;AAAA,MACL,MAAA;AAAA,MACA,UAAA,EAAY,qBAAqB,MAAM;AAAA,KACzC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,2BAA2B,MAAgB;AAC/C,IAAA,IAAI,CAAC,MAAA,CAAO,iBAAA,EAAmB,MAAA,SAAe,EAAC;AAE/C,IAAA,MAAM,WAAqB,EAAC;AAC5B,IAAA,KAAA,MAAW,EAAE,KAAA,EAAO,EAAA,EAAI,SAAA,EAAU,IAAK,OAAO,iBAAA,EAAmB;AAC/D,MAAA,IAAI,cAAA,CAAe,SAAA,EAAW,GAAA,CAAI,SAAS,CAAA,EAAG;AAC5C,QAAA,QAAA,CAAS,KAAK,KAAK,CAAA;AAAA,MACrB;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AAEA,EAAA,IAAI,gBAA+B,EAAC;AACpC,EAAA,IAAI,uBAAA,GAA0B,EAAA;AAC9B,EAAA,IAAI,iBAAA,GAAoB,CAAA;AAExB,EAAA,MAAM,oBAAA,GAAuB;AAAA,IAC3B,GAAG,MAAA,CAAO,MAAA;AAAA,IACV,GAAG,wBAAA;AAAyB,GAC9B;AAEA,EAAA,IAAI,oBAAA,CAAqB,SAAS,CAAA,EAAG;AACnC,IAAA,MAAM,MAAA,GAAS,oBAAA;AAAA,MACb,oBAAA;AAAA,MACA,CAAA;AAAA,MACA,SAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,aAAA,GAAgB,MAAA,CAAO,MAAA;AACvB,IAAA,iBAAA,GAAoB,MAAA,CAAO,UAAA;AAC3B,IAAA,uBAAA,GAA0B,wBAAA;AAAA,MACxB,aAAA;AAAA,MACA,EAAE,YAAA,EAAc,MAAA,CAAO,YAAA,EAAc,aAAA,EAAe,OAAO,aAAA;AAAc,KAC3E;AAEA,IAAA,MAAM,cAAc,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AACnD,IAAA,MAAM,eAAe,oBAAA,CAAqB,MAAA;AAAA,MACxC,CAAC,CAAA,KAAM,CAAC,WAAA,CAAY,QAAA,CAAS,CAAC,CAAA,IAAK,CAAC,CAAA,CAAE,UAAA,CAAW,GAAG;AAAA,KACtD;AAEA,IAAA,GAAA,CAAI,MAAA,EAAQ,CAAA,OAAA,EAAU,aAAA,CAAc,MAAM,CAAA,eAAA,CAAA,EAAmB;AAAA,MAC3D,MAAA,EAAQ,WAAA;AAAA,MACR,MAAA,EAAQ,iBAAA;AAAA,MACR,OAAA,EAAS,YAAA,CAAa,MAAA,GAAS,CAAA,GAAI,YAAA,GAAe;AAAA,KACnD,CAAA;AAAA,EACH;AAEA,EAAA,MAAM,kBAAA,GACJ,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,kBAAkB,EAAE,CAAA,CAAE,MAAA,GAAS,KAClD,MAAA,CAAO,IAAA,CAAK,MAAA,CAAO,WAAA,IAAe,EAAE,CAAA,CAAE,MAAA,GAAS,CAAA,IAC/C,OAAO,IAAA,CAAK,MAAA,CAAO,YAAA,IAAgB,EAAE,CAAA,CAAE,MAAA,GAAS,CAAA,IAChD,MAAA,CAAO,KAAK,MAAA,CAAO,eAAA,IAAmB,EAAE,EAAE,MAAA,GAAS,CAAA;AAErD,EAAA,IAAI,oBAAA,CAAqB,MAAA,KAAW,CAAA,IAAK,CAAC,kBAAA,EAAoB;AAC5D,IAAA,GAAA,CAAI,QAAQ,4DAA4D,CAAA;AAAA,EAC1E;AAEA,EAAA,MAAM,eAAA,GAAkB,CAAC,SAAA,KAAoC;AAC3D,IAAA,IAAI,CAAC,aAAA,CAAc,GAAA,CAAI,SAAS,CAAA,EAAG;AACjC,MAAA,aAAA,CAAc,IAAI,SAAA,EAAW;AAAA,QAC3B,qBAAA,EAAuB,KAAA;AAAA,QACvB,YAAA,EAAc,IAAI,GAAA,CAAI,aAAA,CAAc,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,QACtD,eAAA,EAAiB;AAAA,OAClB,CAAA;AAAA,IACH;AACA,IAAA,OAAO,aAAA,CAAc,IAAI,SAAS,CAAA;AAAA,EACpC,CAAA;AAEA,EAAA,MAAM,sBAAA,uBAA6B,GAAA,EAA2B;AAE9D,EAAA,MAAM,uBAAA,GAA0B,CAC9B,SAAA,EACA,UAAA,EACA,aACA,KAAA,KACG;AACH,IAAA,MAAM,aAAA,GAAgB,UAAA,CAAW,MAAA,CAAO,CAAC,IAAA,KAAS,CAAC,KAAA,CAAM,YAAA,CAAa,GAAA,CAAI,IAAI,CAAC,CAAA;AAC/E,IAAA,IAAI,aAAA,CAAc,WAAW,CAAA,EAAG;AAEhC,IAAA,MAAM,MAAA,GAAS,oBAAA;AAAA,MACb,aAAA;AAAA,MACA,KAAA,CAAM,eAAA;AAAA,MACN,WAAA;AAAA,MACA;AAAA,KACF;AAEA,IAAA,IAAI,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAA,EAAG;AAC5B,MAAA,KAAA,MAAW,KAAA,IAAS,OAAO,MAAA,EAAQ;AACjC,QAAA,KAAA,CAAM,YAAA,CAAa,GAAA,CAAI,KAAA,CAAM,IAAI,CAAA;AAAA,MACnC;AACA,MAAA,KAAA,CAAM,mBAAmB,MAAA,CAAO,UAAA;AAEhC,MAAA,MAAM,QAAA,GAAW,sBAAA,CAAuB,GAAA,CAAI,SAAS,KAAK,EAAC;AAC3D,MAAA,sBAAA,CAAuB,GAAA,CAAI,WAAW,CAAC,GAAG,UAAU,GAAG,MAAA,CAAO,MAAM,CAAC,CAAA;AAErE,MAAA,GAAA,CAAI,OAAA,EAAS,CAAA,OAAA,EAAU,WAAW,CAAA,qBAAA,CAAA,EAAyB;AAAA,QACzD,SAAA;AAAA,QACA,QAAQ,MAAA,CAAO,MAAA,CAAO,IAAI,CAAC,CAAA,KAAM,EAAE,IAAI,CAAA;AAAA,QACvC,QAAQ,MAAA,CAAO;AAAA,OAChB,CAAA;AAAA,IACH;AAAA,EACF,CAAA;AAEA,EAAA,OAAO;AAAA,IACL,cAAA,EAAgB,OACd,KAAA,EAOA,MAAA,KACkB;AAClB,MAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AAEtB,MAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,KAAA,CAAM,SAAS,CAAA;AAC7C,MAAA,MAAM,aAAA,GAAgB,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,MAAM,CAAA;AAChE,MAAA,IAAI,CAAC,aAAA,IAAiB,EAAE,MAAA,IAAU,aAAA,CAAA,EAAgB;AAElD,MAAA,MAAM,cAAc,aAAA,CAAc,IAAA;AAElC,MAAA,IAAI,MAAM,KAAA,IAAS,MAAA,CAAO,WAAA,GAAc,KAAA,CAAM,KAAK,CAAA,EAAG;AACpD,QAAA,uBAAA;AAAA,UACE,KAAA,CAAM,SAAA;AAAA,UACN,MAAA,CAAO,WAAA,CAAY,KAAA,CAAM,KAAK,CAAA;AAAA,UAC9B,OAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAEA,MAAA,IAAI,OAAO,eAAA,EAAiB;AAC1B,QAAA,KAAA,MAAW,CAAC,OAAA,EAAS,UAAU,CAAA,IAAK,MAAA,CAAO,OAAA;AAAA,UACzC,MAAA,CAAO;AAAA,SACT,EAAG;AACD,UAAA,IAAI,mBAAA,CAAoB,WAAA,EAAa,CAAC,OAAO,CAAC,CAAA,EAAG;AAC/C,YAAA,uBAAA;AAAA,cACE,KAAA,CAAM,SAAA;AAAA,cACN,UAAA;AAAA,cACA,SAAA;AAAA,cACA;AAAA,aACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,MAAA,MAAM,kBAA4B,EAAC;AAEnC,MAAA,IAAI,CAAC,KAAA,CAAM,qBAAA,IAAyB,uBAAA,EAAyB;AAC3D,QAAA,eAAA,CAAgB,KAAK,uBAAuB,CAAA;AAC5C,QAAA,KAAA,CAAM,qBAAA,GAAwB,IAAA;AAC9B,QAAA,GAAA,CAAI,QAAQ,mCAAA,EAAqC;AAAA,UAC/C,WAAW,KAAA,CAAM,SAAA;AAAA,UACjB,QAAQ,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,SACxC,CAAA;AAAA,MACH;AAEA,MAAA,MAAM,OAAA,GAAU,sBAAA,CAAuB,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AAC1D,MAAA,IAAI,OAAA,IAAW,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AACjC,QAAA,MAAM,SAAA,GAAY,wBAAA,CAAyB,OAAA,EAAS,EAAE,YAAA,EAAc,OAAO,YAAA,EAAc,aAAA,EAAe,MAAA,CAAO,aAAA,EAAe,CAAA;AAC9H,QAAA,IAAI,SAAA,EAAW;AACb,UAAA,eAAA,CAAgB,KAAK,SAAS,CAAA;AAC9B,UAAA,GAAA,CAAI,QAAQ,2BAAA,EAA6B;AAAA,YACvC,WAAW,KAAA,CAAM,SAAA;AAAA,YACjB,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,WAClC,CAAA;AAAA,QACH;AACA,QAAA,sBAAA,CAAuB,MAAA,CAAO,MAAM,SAAS,CAAA;AAAA,MAC/C;AAEA,MAAA,IAAI,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC9B,QAAA,aAAA,CAAc,IAAA,GAAO,CAAA,EAAG,eAAA,CAAgB,IAAA,CAAK,MAAM,CAAC;;AAAA;;AAAA,EAAc,cAAc,IAAI,CAAA,CAAA;AAAA,MACtF;AAAA,IACF,CAAA;AAAA,IAEA,oBAAA,EAAsB,OACpB,KAAA,EAKA,OAAA,KAKkB;AAClB,MAAA,IAAI,CAAC,UAAA,CAAW,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA,EAAG;AACtC,MAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AAEtB,MAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,KAAA,CAAM,SAAS,CAAA;AAE7C,MAAA,MAAM,QAAA,GAAY,QAAQ,QAAA,EACtB,IAAA;AACJ,MAAA,IAAI,CAAC,QAAA,EAAU;AAEf,MAAA,MAAM,QAAA,GAAW,oBAAoB,QAAQ,CAAA;AAC7C,MAAA,IAAI,CAAC,QAAA,EAAU;AAEf,MAAA,MAAM,GAAA,GAAM,QAAQ,QAAQ,CAAA;AAC5B,MAAA,IAAI,GAAA,IAAO,OAAO,cAAA,EAAgB;AAChC,QAAA,MAAM,SAAA,GAAY,qBAAA,CAAsB,GAAA,EAAK,MAAA,CAAO,cAAc,CAAA;AAClE,QAAA,IAAI,SAAA,CAAU,SAAS,CAAA,EAAG;AACxB,UAAA,uBAAA,CAAwB,KAAA,CAAM,SAAA,EAAW,SAAA,EAAW,UAAA,EAAY,KAAK,CAAA;AAAA,QACvE;AAAA,MACF;AAEA,MAAA,IAAI,OAAO,YAAA,EAAc;AACvB,QAAA,MAAM,UAAA,GAAa,gBAAA,CAAiB,QAAA,EAAU,MAAA,CAAO,YAAY,CAAA;AACjE,QAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,UAAA,uBAAA,CAAwB,KAAA,CAAM,SAAA,EAAW,UAAA,EAAY,MAAA,EAAQ,KAAK,CAAA;AAAA,QACpE;AAAA,MACF;AAAA,IACF,CAAA;AAAA,IAEA,iCAAA,EAAmC,OACjC,KAAA,EACA,MAAA,KACkB;AAClB,MAAA,IAAI,CAAC,OAAO,sBAAA,EAAwB;AAEpC,MAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,GAAA,CAAI,KAAA,CAAM,SAAS,CAAA;AAC/C,MAAA,IAAI,CAAC,KAAA,IAAS,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA,EAAG;AAE7C,MAAA,MAAM,kBAAiC,EAAC;AACxC,MAAA,KAAA,MAAW,IAAA,IAAQ,MAAM,YAAA,EAAc;AACrC,QAAA,MAAM,KAAA,GAAQ,UAAA,CAAW,GAAA,CAAI,IAAI,CAAA;AACjC,QAAA,IAAI,KAAA,EAAO,eAAA,CAAgB,IAAA,CAAK,KAAK,CAAA;AAAA,MACvC;AAEA,MAAA,IAAI,eAAA,CAAgB,WAAW,CAAA,EAAG;AAElC,MAAA,MAAM,SAAA,GAAY,wBAAA;AAAA,QAChB,eAAA;AAAA,QACA,EAAE,YAAA,EAAc,MAAA,CAAO,YAAA,EAAc,aAAA,EAAe,OAAO,aAAA;AAAc,OAC3E;AACA,MAAA,MAAA,CAAO,OAAA,CAAQ,IAAA;AAAA,QACb,CAAA;;AAAA;;AAAA,EAAsG,SAAS,CAAA;AAAA,OACjH;AAEA,MAAA,KAAA,CAAM,qBAAA,GAAwB,KAAA;AAE9B,MAAA,GAAA,CAAI,QAAQ,+CAAA,EAAiD;AAAA,QAC3D,WAAW,KAAA,CAAM,SAAA;AAAA,QACjB,YAAY,eAAA,CAAgB;AAAA,OAC7B,CAAA;AAED,MAAA,aAAA,EAAc;AAAA,IAChB,CAAA;AAAA,IAEA,KAAA,EAAO,OAAO,EAAE,KAAA,EAAM,KAAuC;AAC3D,MAAA,IACE,KAAA,CAAM,IAAA,KAAS,iBAAA,IACf,WAAA,IAAe,MAAM,UAAA,EACrB;AACA,QAAA,MAAM,SAAA,GAAY,MAAM,UAAA,CAAW,SAAA;AACnC,QAAA,aAAA,CAAc,OAAO,SAAS,CAAA;AAC9B,QAAA,sBAAA,CAAuB,OAAO,SAAS,CAAA;AACvC,QAAA,aAAA,CAAc,OAAO,SAAS,CAAA;AAC9B,QAAA,GAAA,CAAI,OAAA,EAAS,0BAAA,EAA4B,EAAE,SAAA,EAAW,CAAA;AACtD,QAAA,aAAA,EAAc;AAAA,MAChB;AAAA,IACF;AAAA,GACF;AACF;AAEA,IAAO,aAAA,GAAQ","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"]}
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, Model } from \"@opencode-ai/sdk\"\nimport type {\n PreloadSkillsConfig,\n ParsedSkill,\n SessionState,\n ConditionalSkill,\n SkillSettings,\n SkillUsageStats,\n AnalyticsData,\n InjectionMethod,\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 injectionMethod: \"chatMessage\",\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 injectionMethod:\n parsed.injectionMethod === \"systemPrompt\" ||\n parsed.injectionMethod === \"chatMessage\"\n ? (parsed.injectionMethod as InjectionMethod)\n : 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 saveAnalytics()\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 const pendingToolFilePaths = new Map<string, string>()\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 const useSystemPromptInjection = config.injectionMethod === \"systemPrompt\"\n\n return {\n \"experimental.chat.system.transform\": useSystemPromptInjection\n ? async (\n input: { sessionID?: string; model: Model },\n output: { system: string[] }\n ): Promise<void> => {\n if (!input.sessionID) return\n\n const state = getSessionState(input.sessionID)\n const skillsToInject: ParsedSkill[] = []\n\n if (initialSkills.length > 0) {\n skillsToInject.push(...initialSkills)\n }\n\n for (const name of state.loadedSkills) {\n const skill = skillCache.get(name)\n if (skill && !skillsToInject.find((s) => s.name === name)) {\n skillsToInject.push(skill)\n }\n }\n\n const pending = pendingSkillInjections.get(input.sessionID)\n if (pending && pending.length > 0) {\n for (const skill of pending) {\n if (!skillsToInject.find((s) => s.name === skill.name)) {\n skillsToInject.push(skill)\n }\n }\n pendingSkillInjections.delete(input.sessionID)\n }\n\n if (skillsToInject.length > 0) {\n const formatted = formatSkillsForInjection(skillsToInject, {\n useSummaries: config.useSummaries,\n skillSettings: config.skillSettings,\n })\n output.system.push(formatted)\n\n if (!state.initialSkillsInjected && initialSkills.length > 0) {\n state.initialSkillsInjected = true\n log(\"info\", \"Injected skills into system prompt\", {\n sessionID: input.sessionID,\n skills: skillsToInject.map((s) => s.name),\n })\n }\n }\n }\n : undefined,\n\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 if (!useSystemPromptInjection) {\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, {\n useSummaries: config.useSummaries,\n skillSettings: config.skillSettings,\n })\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\n \"tool.execute.before\": async (\n input: { tool: string; sessionID: string; callID: string },\n output: { args: Record<string, unknown> }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n\n const filePath = getFilePathFromArgs(output.args)\n if (filePath) {\n pendingToolFilePaths.set(input.callID, filePath)\n log(\"debug\", \"Captured file path from tool\", {\n tool: input.tool,\n callID: input.callID,\n filePath,\n })\n }\n },\n\n \"tool.execute.after\": async (\n input: { tool: string; sessionID: string; callID: string },\n _output: { title: string; output: string; metadata: unknown }\n ): Promise<void> => {\n if (!FILE_TOOLS.includes(input.tool)) return\n if (!input.sessionID) return\n\n const filePath = pendingToolFilePaths.get(input.callID)\n pendingToolFilePaths.delete(input.callID)\n\n if (!filePath) {\n log(\"debug\", \"No file path found for tool call\", {\n tool: input.tool,\n callID: input.callID,\n })\n return\n }\n\n const state = getSessionState(input.sessionID)\n const ext = extname(filePath)\n\n log(\"debug\", \"Processing file access\", {\n tool: input.tool,\n filePath,\n extension: ext,\n })\n\n if (ext && config.fileTypeSkills) {\n const extSkills = getSkillsForExtension(ext, config.fileTypeSkills)\n if (extSkills.length > 0) {\n log(\"debug\", \"Found skills for extension\", { ext, skills: extSkills })\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 log(\"debug\", \"Found skills for path pattern\", { filePath, skills: pathSkills })\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.4.0",
3
+ "version": "1.5.1",
4
4
  "description": "Smart skill loading for OpenCode — automatic, contextual, and budget-aware",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",