fix(claude-code-hooks): cache idle hook config and parent lookups

Reduce repeated session.idle work by reusing hook config loads across a short TTL and by retrying parent session lookup instead of permanently caching transient failures.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
YeonGyu-Kim
2026-04-01 17:43:00 -07:00
parent 724d21b3cc
commit f4b8e1c365
7 changed files with 441 additions and 11 deletions
@@ -4,6 +4,8 @@ import type { ClaudeHookEvent } from "./types"
import { log } from "../../shared/logger"
import { getOpenCodeConfigDir } from "../../shared"
const CONFIG_CACHE_TTL_MS = 30_000
export interface DisabledHooksConfig {
Stop?: string[]
PreToolUse?: string[]
@@ -16,12 +18,40 @@ export interface PluginExtendedConfig {
disabledHooks?: DisabledHooksConfig
}
interface PluginExtendedConfigCacheEntry {
value: PluginExtendedConfig
cachedAt: number
}
const USER_CONFIG_PATH = join(getOpenCodeConfigDir({ binary: "opencode" }), "opencode-cc-plugin.json")
const configCache = new Map<string, PluginExtendedConfigCacheEntry>()
function getProjectConfigPath(): string {
return join(process.cwd(), ".opencode", "opencode-cc-plugin.json")
}
function getCacheKey(): string {
return process.cwd()
}
function getCachedConfig(cacheKey: string): PluginExtendedConfig | undefined {
const cachedEntry = configCache.get(cacheKey)
if (!cachedEntry) {
return undefined
}
if (Date.now() - cachedEntry.cachedAt >= CONFIG_CACHE_TTL_MS) {
configCache.delete(cacheKey)
return undefined
}
return cachedEntry.value
}
export function clearPluginExtendedConfigCache(): void {
configCache.clear()
}
async function loadConfigFromPath(path: string): Promise<PluginExtendedConfig | null> {
if (!existsSync(path)) {
return null
@@ -53,6 +83,12 @@ function mergeDisabledHooks(
}
export async function loadPluginExtendedConfig(): Promise<PluginExtendedConfig> {
const cacheKey = getCacheKey()
const cachedConfig = getCachedConfig(cacheKey)
if (cachedConfig) {
return cachedConfig
}
const userConfig = await loadConfigFromPath(USER_CONFIG_PATH)
const projectConfig = await loadConfigFromPath(getProjectConfigPath())
@@ -71,6 +107,11 @@ export async function loadPluginExtendedConfig(): Promise<PluginExtendedConfig>
})
}
configCache.set(cacheKey, {
value: merged,
cachedAt: Date.now(),
})
return merged
}