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
@@ -1,7 +1,7 @@
import type { PluginInput } from "@opencode-ai/plugin"
import type { ContextCollector } from "../../../features/context-injector"
import { loadClaudeHooksConfig } from "../config"
import { loadPluginExtendedConfig } from "../config-loader"
import { clearClaudeHooksConfigCache, loadClaudeHooksConfig } from "../config"
import { clearPluginExtendedConfigCache, loadPluginExtendedConfig } from "../config-loader"
import { executeStopHooks, type StopContext } from "../stop"
import { clearTranscriptCache } from "../transcript"
import { clearToolInputCache, stopToolInputCacheCleanup } from "../tool-input-cache"
@@ -19,6 +19,8 @@ export function createSessionEventHandler(
config: PluginConfig,
contextCollector?: ContextCollector,
) {
const parentSessionIdCache = new Map<string, string | undefined>()
return async (input: { event: { type: string; properties?: unknown } }) => {
const { event } = input
@@ -38,6 +40,7 @@ export function createSessionEventHandler(
const props = event.properties as Record<string, unknown> | undefined
const sessionInfo = props?.info as { id?: string } | undefined
if (sessionInfo?.id) {
parentSessionIdCache.delete(sessionInfo.id)
clearTranscriptCache(sessionInfo.id)
clearToolInputCache(sessionInfo.id)
contextCollector?.clear(sessionInfo.id)
@@ -62,14 +65,17 @@ export function createSessionEventHandler(
const interruptStateBefore = sessionInterruptState.get(sessionID)
const interruptedBefore = interruptStateBefore?.interrupted === true
let parentSessionId: string | undefined
try {
const sessionInfo = await ctx.client.session.get({
path: { id: sessionID },
})
parentSessionId = sessionInfo.data?.parentID
} catch {
parentSessionId = undefined
let parentSessionId = parentSessionIdCache.get(sessionID)
if (parentSessionId === undefined && !parentSessionIdCache.has(sessionID)) {
try {
const sessionInfo = await ctx.client.session.get({
path: { id: sessionID },
})
parentSessionId = sessionInfo.data?.parentID
parentSessionIdCache.set(sessionID, parentSessionId)
} catch {
parentSessionId = undefined
}
}
if (!isHookDisabled(config, "Stop")) {
@@ -123,6 +129,8 @@ export function createSessionEventHandler(
export function disposeSessionEventHandler(contextCollector?: ContextCollector): void {
clearTranscriptCache()
clearClaudeHooksConfigCache()
clearPluginExtendedConfigCache()
stopToolInputCacheCleanup()
contextCollector?.clearAll()
clearAllSessionHookState()