import type { AgentResult, ContextUsage } from '../core/types/agent-types.js'; import type { ContinuationSink } from '../agent-adapter/types.js'; import { startBgWaitGuard } from './bg-wait-guard.js'; export interface WebBgHoldDeps { /** The turn's terminal result (carries pending/undelivered background-task counts). */ result: AgentResult; /** Register the continuation sink on the live agent process (proc.setContinuationSink). */ registerSink: (sink: ContinuationSink) => void; /** Publish a session.status delta. During the hold: running:true, backgroundRunning:true; * on seal: running:false. */ publishStatus: (p: { running: boolean; backgroundRunning: boolean; }) => void; /** Append + publish a continuation assistant message (history record + session.message). */ publishAssistant: (text: string) => void; /** Append + publish a continuation tool call (history record + session.message). */ publishTool: (name: string, input: any, toolUseId: string) => void; /** Persist a complete normalized continuation tool result in DEBUG mode. */ publishToolResult?: (toolUseId: string, content: string, isError: boolean) => void; /** Persist and publish an exact continuation context snapshot. */ publishContextUsage?: (usage: ContextUsage) => void; /** Busy bracket (trackPendingTask). +1 for the whole wait window so a deferred daemon restart * does not fire and kill the Claude child (F1); -1 when the guard settles. */ track: (delta: number) => void; /** Register the hold's abort handle (user Stop while the hold is up). Invoked once, right after * the hold is installed, with a function that seals the hold: guard settled (busy bracket * released) + running:false published. Idempotent with every other seal path. */ registerAbort?: (abort: () => void) => void; /** Injectable guard factory for tests (defaults to the real startBgWaitGuard). */ startGuard?: typeof startBgWaitGuard; /** Injectable timers forwarded to the guard (tests drive grace/max-wait deterministically). */ guardTimers?: { set: (fn: () => void, ms: number) => unknown; clear: (h: unknown) => void; }; graceMs?: number; maxWaitMs?: number; } /** * Hold a web session open for its spontaneous background-task continuation. The turn's foreground * work has ended, but background work (running or finished-but-unnotified) remains. Instead of * sealing running:false immediately, keep the session marked running+backgroundRunning, register a * ContinuationSink, and arm a bg-wait-guard. When the background task later re-invokes the model, its * output streams in as new session messages; when no work remains (or on grace / max-wait / interrupt) * we seal running:false. * * Returns true when the hold was installed — the caller MUST then skip its own running:false publish. * Returns false when there was nothing to hold (caller seals as usual). Assumes the gate * (shouldHoldWebForBg) already passed; the internal remaining-count check is a defensive re-guard. */ export declare function holdWebForBg(deps: WebBgHoldDeps): boolean;