import { type Task } from '../core/task-parser.js'; import type { ThreadRecord, RunThreadOptions } from '../core/types/thread-types.js'; import type { PlatformAdapter } from '../platform/index.js'; /** Test hook: clear in-memory dedup state to simulate a server restart. */ export declare function _testResetCallbackState(): void; /** Child-result notice delivered into a suspended parent's pendingMessages. Echoes the * delegation contract and demands acceptance verification before the result is trusted * (DR-0014 L1 纠偏: verify the deliverable, never the child's self-report). */ export declare function buildChildResultNotice(child: ThreadRecord): string; /** Rebuild RunThreadOptions for re-entering a suspended parent OR a rate-limit-paused thread. * extraHooks are not persisted on ThreadRecord, so the dispatch task-status-check hook is * reconstructed from metadata.taskId/taskProject (the reason dispatch threads must store them). * statusMsg is restored from metadata.statusMsgRef (persisted at dispatch by task-dispatch / * webhook) so the resumed run keeps updating the SAME live status message — without it the run * carries statusMsg=null and the message freezes at "Paused — rate limited" forever even though * the thread runs to completion (2026-06-23 finding: rate-limit resume status-message freeze). */ export declare function buildResumeOptions(parent: ThreadRecord): RunThreadOptions | null; /** Refresh the status message persisted at suspension (metadata.statusMsgRef): a resumed * thread's terminal summary, or the new suspension count if it suspended again. Without * this, the dispatch/webhook status message reads "suspended — waiting on children" * forever after the thread has finished (2026-06-11 verification finding). */ export declare function sealSuspendedStatusMsg(threadId: string, adapter?: PlatformAdapter | null): Promise; export type ResumeFn = (parentThreadId: string) => void; /** Resume a suspended manager thread to answer a subtask's question (ask_manager / DR-0016). * Unlike maybeResumeParent, this does NOT require the manager's child sets to be empty — the * manager is woken to answer, not because its children finished. It answers via answer_subtask, * whose handler sets pendingControl='wait', so the manager re-suspends on its still-live children * at the next step boundary. Shares the `resuming` guard so it never collides with a concurrent * completion-driven resume (whichever wins, the question + any child results both sit in * pendingMessages). No-op unless the manager is currently 'waiting'. */ export declare function resumeManagerForQuestion(managerThreadId: string, resume?: ResumeFn): void; /** Deliver a terminal child's result to its thread parent: remove the child from waitingOn, * queue the result notice into pendingMessages (persistent idempotency via * deliveredChildResults), and resume the parent when nothing is left to wait on. * Orphan children (parent purged or already terminal) degrade to a project-report notice. */ export declare function notifyThreadParent(childId: string, deps?: { resume?: ResumeFn; }): Promise; /** Child-task result notice delivered into a suspended manager's pendingMessages. * completed → acceptance instructions (verify the deliverable, never the report); * blocked → escalation instructions (the child cannot finish on its own). */ export declare function buildTaskResultNotice(task: Task, kind: 'completed' | 'blocked'): string; /** Event-bridge entry: a task completed or got blocked — wake every manager thread waiting * on it. For 'completed', the task's real status is verified on disk first: the dispatch * cycle publishes task.completed loosely (thread ended ≠ task done), so the disk state is * the source of truth. A rejected bogus event keeps the manager waiting; the genuine * completion publishes again later. */ export declare function notifyTaskParentThreads(taskId: string, kind: 'completed' | 'blocked', deps?: { resume?: ResumeFn; }): Promise; type WakeFn = (channel: string, notice: string) => void | Promise; /** Session→task wake (Problem 1): when a task created by an interactive session/agent turns * terminal, route a notice back to its origin channel. Default-on, no fallback — if origin_channel * is set we always wake it. Mutually exclusive with the thread-parent path: if any thread is * currently waiting on this task (waitingOnTasks), that path owns the result and we defer. * `wake` is injectable for testing (mirrors the `resume` injection on notifyTaskParentThreads). */ export declare function notifyTaskOriginSession(taskId: string, kind: 'completed' | 'blocked', deps?: { wake?: WakeFn; }): Promise; /** Sweep one waiting thread's waitingOnTasks against disk state: deliver already-done and * already-blocked children, drop missing ones, keep open ones. Closes the race window * where a child task turns terminal between the suspension snapshot and the waiting * persist (its event fired before anyone was listening). Also the recovery path for task * children — unlike thread children, open tasks survive restarts and stay awaited. */ export declare function reconcileWaitingTasks(threadId: string, deps?: { resume?: ResumeFn; }): Promise; /** Register the EventBus subscribers that wake suspended manager threads on child-task * terminal events (DR-0014 §8). Call once at startup, before recoverWaitingThreads. */ export declare function registerTaskTreeSubscribers(bus: { subscribe: (type: any, fn: (e: any) => void) => unknown; }): void; /** Startup recovery: re-deliver results that completed while the server was down. * Idempotent — safe to call repeatedly. Thread children still marked waiting whose records * are gone are treated as failed (the restart already failed all in-flight running threads, * so every surviving child THREAD record is terminal by the time this runs). Task children * are reconciled against disk — open ones stay awaited. Returns the number * of suspended parents processed. */ export declare function recoverWaitingThreads(deps?: { resume?: ResumeFn; }): Promise; /** * Fire the completion callback for an MCP-spawned thread once it is terminal. * - Non-terminal statuses (e.g. a parent that suspended via thread_wait and returned * from runThread in 'waiting') are ignored — suspension is not completion. * - Interactive parent (no parentThreadId): wake the parent by routing a synthetic turn onto * its channel via agentRunner.route. * - Thread-agent parent (parentThreadId set): deliver into the parent thread's * pendingMessages and resume it when its waitingOn empties (notifyThreadParent). * Threads not spawned via thread_start (no parentSessionId) are ignored. */ export declare function fireThreadCallback(threadId: string): Promise; export {};