From b14665f1749aef2c1da98e15923fd8322272230c Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Sun, 5 Apr 2026 10:55:44 +0900 Subject: [PATCH] fix: cache plugin component loading results Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- .../claude-code-plugin-loader/loader.ts | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/features/claude-code-plugin-loader/loader.ts b/src/features/claude-code-plugin-loader/loader.ts index db1ce7729..95a9065ff 100644 --- a/src/features/claude-code-plugin-loader/loader.ts +++ b/src/features/claude-code-plugin-loader/loader.ts @@ -27,12 +27,33 @@ export interface PluginComponentsResult { errors: PluginLoadError[] } +const cachedPluginComponentsByKey = new Map() + +function clonePluginComponentsResult( + result: PluginComponentsResult, +): PluginComponentsResult { + return structuredClone(result) +} + function isClaudeCodePluginsDisabled(): boolean { const disableFlag = process.env.OPENCODE_DISABLE_CLAUDE_CODE const disablePluginsFlag = process.env.OPENCODE_DISABLE_CLAUDE_CODE_PLUGINS return disableFlag === "true" || disableFlag === "1" || disablePluginsFlag === "true" || disablePluginsFlag === "1" } +function getPluginComponentsCacheKey(options?: PluginLoaderOptions): string { + const overrideEntries = Object.entries(options?.enabledPluginsOverride ?? {}) + .sort(([leftKey], [rightKey]) => leftKey.localeCompare(rightKey)) + + return JSON.stringify({ + enabledPluginsOverride: overrideEntries, + }) +} + +export function clearPluginComponentsCache(): void { + cachedPluginComponentsByKey.clear() +} + export async function loadAllPluginComponents(options?: PluginLoaderOptions): Promise { if (isClaudeCodePluginsDisabled()) { log("Claude Code plugin loading disabled via OPENCODE_DISABLE_CLAUDE_CODE env var") @@ -47,6 +68,12 @@ export async function loadAllPluginComponents(options?: PluginLoaderOptions): Pr } } + const cacheKey = getPluginComponentsCacheKey(options) + const cachedPluginComponents = cachedPluginComponentsByKey.get(cacheKey) + if (cachedPluginComponents) { + return clonePluginComponentsResult(cachedPluginComponents) + } + const { plugins, errors } = discoverInstalledPlugins(options) const [commands, skills, agents, mcpServers, hooksConfigs] = await Promise.all([ @@ -59,7 +86,7 @@ export async function loadAllPluginComponents(options?: PluginLoaderOptions): Pr log(`Loaded ${plugins.length} plugins with ${Object.keys(commands).length} commands, ${Object.keys(skills).length} skills, ${Object.keys(agents).length} agents, ${Object.keys(mcpServers).length} MCP servers`) - return { + const result = { commands, skills, agents, @@ -68,4 +95,8 @@ export async function loadAllPluginComponents(options?: PluginLoaderOptions): Pr plugins, errors, } + + cachedPluginComponentsByKey.set(cacheKey, clonePluginComponentsResult(result)) + + return clonePluginComponentsResult(result) }