import { type RecallOptions } from "./recall.js"; /** * Host-agnostic hook handlers. Claude Code, Codex CLI, and Grok Build share the * same lifecycle events; field names differ: * - Claude: snake_case (`user_input`, `tool_name`, `session_id`) * - Codex: `prompt` instead of `user_input` * - Grok: camelCase (`toolName`, `toolInput`, `sessionId`, `workspaceRoot`) plus * native tool names (`run_terminal_command`, `search_replace`) * * {@link normalizeHookPayload} collapses those shapes so handlers stay host-agnostic. * * Every handler is **fail-open**: a hook runs on every prompt and every turn * boundary, so any failure must degrade to "do nothing" (empty stdout, exit 0) * rather than break — or worse, trap — the host agent. */ /** The instruction injected when the Stop hook blocks once per turn. */ export declare const STOP_DIRECTIVE: string; export interface HookResult { /** Text to print to stdout (may be ""). */ stdout: string; /** Process exit code (always 0 — hooks fail open). */ exitCode: number; } export interface HookDeps { /** Recall memory text for a prompt. Defaults to the real {@link recall}. */ recall?: (options: RecallOptions) => Promise; /** Initialize/register the project for a cwd. Defaults to a daemon call. */ initProject?: (cwd?: string) => Promise; /** * Loop guard for the Stop hook. Returns `true` if this turn key was already * seen (so the agent may stop), `false` the first time (so we block once and * mark it seen). Defaults to an atomic marker file under the temp dir. */ markerSeen?: (key: string) => Promise; } /** * Collapse host-specific envelope fields onto the Claude/Codex snake_case names the * handlers already use. Idempotent: re-normalizing a snake_case payload is a no-op. */ export declare function normalizeHookPayload(payload: Record): Record; export declare function handleUserPromptSubmit(payload: Record, deps: HookDeps): Promise; /** * PreToolUse: recalls *additional* memory targeted to the specific tool action (the file being * edited, the command being run) and injects it as `additionalContext`, supplementing the * task-level memory UserPromptSubmit already injected. * * Injection-only by design: it never emits `permissionDecision`/`updatedInput`/a legacy * `decision`, and always exits 0 — memory must never block, gate, or rewrite a real tool call * (only exit 2 / a deny would). On Claude this context rides alongside the tool result; on older * Codex builds that don't yet support PreToolUse `additionalContext` it is simply dropped (the * tool still runs), so this is purely additive over the guaranteed UserPromptSubmit path. */ export declare function handlePreToolUse(payload: Record, deps: HookDeps): Promise; export declare function handleSessionStart(payload: Record, deps: HookDeps): Promise; export declare function handleStop(payload: Record, deps: HookDeps): Promise; /** * Parses raw hook stdin JSON and dispatches by event name. Unknown events, * blank input, and invalid JSON all degrade to a no-op — a hook must never * throw out of the CLI. */ export declare function runHook(event: string, raw: string, deps?: HookDeps): Promise;