import type { ISessionClient } from "../../platform/ports/session-client.ts"; import type { DispatchInput, DispatchTask, DispatchManagerConfig } from "../types.ts"; import { BudgetTracker } from "../budget/budget-tracker.ts"; import { FileSystemCheckpointStore } from "../checkpoint/checkpoint-store.ts"; import { InMemoryProgressStore } from "../progress/progress-store.ts"; export { extractSessionErrorMessage } from "./error-utils.ts"; export declare class DispatchManager { private tasks; private cleanupTimers; private sidecarGCTimers; private pendingNotifications; private cleanedUpTasks; private config; private client; private watchdog; private sessionToTask; private eventState; private store; private checkpointStore; private _cancelQueue; private _syncControllers; /** Maps completed sync task IDs to their opencode session IDs for continuation support. */ private completedSyncSessions; /** Timestamps (epoch ms) for completedSyncSessions entries — used for TTL eviction. */ private completedSyncSessionsSetAt; private subagentModelKey; /** Role-scoped dispatch configs (subtask 3) — resolved per subagent role in lifecycle. */ private roleConfigs; /** Subagent → role key map (subtask 3) — role-scoped overrides for model keys. */ private subagentRoleKey; private sessionMonitor; private metricsPersister; private budgetTracker; private notifyOutbox; private _deferredIdleTimers; private _directory; private progressStore; private taskTerminatedListeners; /** Parent→taskIds index for O(1) getTasksByParent lookups. */ private parentTasksIndex; /** Inflight running task count per parentSessionId — replaces O(n) scan in getInflightCount. */ private inflightByParent; /** Oldest startedAt timestamp per parentSessionId — replaces O(n) scan in getOldestInflightChildStartedAt. */ private oldestStartedAtByParent; /** Delegated lifecycle manager. */ private lifecycle; /** Delegated completion orchestrator. */ private orchestrator; constructor(client: ISessionClient, config?: Partial, subagentModelKey?: Map, roleConfigs?: ReadonlyMap, subagentRoleKey?: Map); launch(input: DispatchInput, parentContext: { sessionID: string; agent: string; directory: string; graphScoped?: boolean; }): Promise; executeSync(input: DispatchInput, parentContext: { sessionID: string; agent: string; directory: string; graphScoped?: boolean; }): Promise; reopenForContinuation(taskId: string, input: DispatchInput, parentContext: { sessionID: string; agent: string; directory: string; graphScoped?: boolean; }): Promise; cancelTask(taskId: string): Promise; /** * Approve a task that is paused in "awaiting_approval" state. * Transitions the task to "completed" and notifies the parent. * Returns false if the task is not in awaiting_approval state or not found. */ approveTask(taskId: string): Promise; /** * Reject a task that is paused in "awaiting_approval" state. * Transitions the task to "error" with the provided reason and notifies the parent. * Returns false if the task is not in awaiting_approval state or not found. */ rejectTask(taskId: string, reason?: string): Promise; getResult(taskId: string): Promise<{ kind: "ok" | "expired" | "not_found" | "fetch_error"; text: string; resultText: string; hadFence: boolean; totalChars: number; error?: string; }>; getInflightCount(parentSessionId: string): number; cleanupTask(taskId: string): void; flushPersist(): Promise; flushPersistSync(): void; dispose(): Promise; /** * True while the periodic pipelines that keep a manager live are armed: * the outbox sweeper, the config-aware budget sampler (see * CompletionOrchestrator.isRunning) and the progress sweeper. A manager * whose timers were stopped (flushPersistSync, dispose) reports false so * health() can surface the zombie instead of reporting healthy. */ isOperational(): boolean; /** Sweep completedSyncSessions entries older than 1 hour (COMPLETED_SYNC_TTL_MS). */ private cleanupCompletedSyncSessions; recover(): Promise; /** * Notify the parent session about a task's completion. * * Graph-scope suppression: graph-scoped tasks (dispatched by the graph * engine via `executeNode`/`graphParentContext`) return immediately without * sending — graph-node completion is reported EXCLUSIVELY by the graph * notifier (`createGraphNotifier`/`createGraphTerminalNotifier` in * `src/graph/engine/graph-notify.ts`). This guards the direct callers * (approveTask/rejectTask) and the `sendNotification` callback path used by * recovery-orchestrator and the completion-orchestrator outbox sweeper. * Real-session tasks notify exactly as before. */ notifyCompletion(task: DispatchTask, remainingTasks: number, resultText?: string): Promise; /** * Send a progress milestone `` to the parent session. * Used by dispatch_progress tool when a 25/50/75/100% threshold is crossed. * Fire-and-forget — errors are silently caught. */ sendProgressMilestone(taskId: string, text: string): Promise; handleSessionIdle(sessionId: string): Promise; handleSessionStatus(sessionId: string, statusType: string): Promise; handleMessageUpdated(sessionId: string): void; handleSessionError(sessionId: string, error: unknown): Promise; handleSessionDeleted(sessionId: string): Promise; getTask(taskId: string): DispatchTask | undefined; getTasksByParent(parentSessionId: string): DispatchTask[]; getAllTasks(): DispatchTask[]; getMetricsSnapshot(): import("../persistence/metrics.ts").MetricsSnapshot; isSyncSession(sessionId: string): boolean; getBudgetTracker(): BudgetTracker; getBudgetStatus(parentSessionId: string): string; getConfig(): Readonly; getEventState(): Map; getCheckpointStore(): FileSystemCheckpointStore; getProgressStore(): InMemoryProgressStore; /** Register a one-time listener for when a task enters a terminal state. * * If the task is already in a terminal status (completed/error/cancelled/timeout), * the callback fires immediately (async via microtask) to handle the listen-after- * terminate race — e.g. the loop coordinator registering after the worker has already finished. * Fire-once semantics are preserved: the callback is removed from the listener set * before the microtask fires, so notifyTerminated will not call it again. */ onTaskTerminated(taskId: string, callback: (taskId: string, status: string) => void): (taskId: string, status: string) => void; /** Remove a previously registered task-terminated listener. */ removeTaskTerminatedListener(taskId: string, callback: (taskId: string, status: string) => void): void; get _dirty(): boolean; get _persistTimer(): ReturnType | undefined; get sweeperTimer(): ReturnType | undefined; evaluateAndComplete(taskId: string, trigger: "idle-debounce" | "watchdog-reconcile" | "global-sweep" | "error-event" | "deleted-event", errorDetail?: string): Promise; handleTaskCompleted(taskId: string): Promise; handleTaskError(taskId: string, error: string): void; handleTaskTimeout(taskId: string, reason: string): void; materializeResult(taskId: string): Promise; materializeAndNotify(taskId: string): Promise; computeDepth(parentSessionId: string): number; leaveRunning(taskId: string): void; persistState(): void; scheduleCleanup(taskId: string): void; transition(taskId: string, from: import("../types.ts").DispatchTaskStatus[], to: import("../types.ts").DispatchTaskStatus, fields?: Partial>): boolean; /** * Update role-scoped dispatch configs and the subagent→role key map at runtime. */ updateDispatchConfigs(roleConfigs: ReadonlyMap, subagentRoleKey: Map): void; setStoreDirectory(directory: string): void; setRecoverySnapshotProvider(provider: (() => import("../../recovery/types.ts").RecoveryMetricsSnapshot | null) | null): void; } //# sourceMappingURL=manager.d.ts.map