import type { ConfiguredHook, HookEntry, HookEvent, HookMatcher, HookRegistrationOptions, HttpHook, InProcessHook, ShellHook } from '../types/hooks.js'; interface LoadConfiguredHooksOptions { /** Load only trusted hooks that remain active under `--no-hooks`. */ policyOnly?: boolean | undefined; } /** * Registry of lifecycle hooks (both in-process and shell). One instance is * shared per session: the boot path loads `config.hooks` as shell entries and * plugins add in-process entries via `PluginAPI.registerHook`. The * `HookRunner` reads from it at each lifecycle phase. */ export declare class HookRegistry { private readonly entries; /** Register an in-process hook. Returns an unsubscribe function. */ registerInProcess(event: HookEvent, matcher: HookMatcher | undefined, hook: InProcessHook, owner?: string | undefined, options?: HookRegistrationOptions): () => void; /** * Register a single shell hook. The hook is owned by the runtime (no plugin * name) — it survives plugin uninstalls. Returns an unsubscribe function. */ registerShell(event: HookEvent, hook: ShellHook): () => void; /** Register a native HTTP hook. */ registerHttp(event: HookEvent, hook: HttpHook): () => void; /** Bulk-load command/HTTP hooks from a `config.hooks` map. */ loadShellHooks(hooks: Partial> | undefined, options?: LoadConfiguredHooksOptions): void; /** * Atomically replace the shell-hook set: drop every currently-registered * shell entry, then load the supplied `config.hooks` map. In-process * hooks (and their plugin owners) are untouched — only shell entries * are touched, because they are the only entries sourced from * `config.hooks`. * * Designed for hot-reload via `ConfigStore.watch`: when the operator * edits `config.json` and the store fires its watcher, the CLI calls * this with the new `config.hooks` value. Idempotent — calling twice * with the same map yields the same registry state (callers should still * guard at the change-detection layer to avoid wasted work). */ replaceShellHooks(hooks: Partial> | undefined, options?: LoadConfiguredHooksOptions): void; /** All entries registered for an event, in registration order. */ list(event: HookEvent): readonly HookEntry[]; /** True when any entry is registered for the event. */ has(event: HookEvent): boolean; /** Every entry currently registered (across all events). */ all(): readonly HookEntry[]; /** * Drop every in-process hook whose `owner` matches. Used by the plugin * loader during teardown as a belt-and-braces backstop for the per-call * unsubscribe functions pushed onto `pluginCleanupFns` — if a plugin * `setup()` throws partway through after registering some hooks, the * remaining unsubscribes may never run, and the registry would otherwise * hold dangling references to a torn-down plugin's closures. * * Returns the number of hooks actually removed (useful for tests). * Shell hooks are owned by the runtime, not a plugin, so they're never * drained by owner. */ drainByOwner(owner: string): number; /** Count of in-process hooks currently registered by `owner`. */ countByOwner(owner: string): number; /** Drop every registered hook (used in teardown / tests). */ clear(): void; private remove; } /** * Does a hook matcher apply to a tool name? `*` (or empty) matches everything; * otherwise the matcher is a case-insensitive pipe-delimited list of exact * tool names (`"edit|write"`). Non-tool events pass `undefined` and always match. */ export declare function hookMatcherMatches(matcher: HookMatcher, toolName: string | undefined): boolean; export {}; //# sourceMappingURL=registry.d.ts.map