import { TaskStatus } from './task-state.js'; import type { TaskState, TaskTypeName, Provider, PendingQuestion } from './task-state.js'; import type { TaskHandle } from './task-handle.js'; import { TaskFileWriter } from '../services/task-file-writer.js'; export interface TaskManagerOptions { /** * Root directory for persistence files. * `undefined` means persistence is disabled (in-memory only). */ persistenceRoot: string | undefined; fileWriter?: TaskFileWriter | undefined; } export interface CreateTaskInput { prompt: string; cwd: string; provider: Provider; taskType: TaskTypeName; model?: string; effort?: 'low' | 'medium' | 'high' | 'xhigh'; timeoutMs?: number; dependsOn?: string[]; labels?: string[]; keepAlive?: number; } export type StatusChangeListener = (task: TaskState, previousStatus: TaskStatus) => void; export type OutputListener = (taskId: string, line: string) => void; /** * Central orchestrator for task lifecycle management. * * Wraps {@link TaskStore} with: * - Human-readable ID generation (adjective-animal-number) * - {@link TaskHandle} creation for provider adapters * - Event bus (status changes, output lines) * - Output ring buffer capping * * Spec reference: §3.1 (layer model), §3.2 (TaskHandle) */ export declare class TaskManager { private readonly store; private readonly handles; private readonly abortControllers; private readonly abortListeners; private readonly statusListeners; private readonly outputListeners; private readonly createListeners; private readonly lastMetaWrite; readonly persistenceRoot: string | undefined; readonly fileWriter: TaskFileWriter | undefined; constructor(options: TaskManagerOptions); /** * Create a new task with a human-readable ID, store it, and return * the initial {@link TaskState}. */ createTask(input: CreateTaskInput): TaskState; /** * Restore a previously persisted task into the store without generating * a new ID or firing create listeners. Used during startup recovery. */ restoreTask(task: TaskState): void; getTask(id: string): TaskState | undefined; getBySessionId(sessionId: string): TaskState | undefined; getHandle(id: string): TaskHandle | undefined; getAllTasks(): TaskState[]; /** * Apply a partial update to a task. * * If the update includes a status change, the FSM is validated by the store. * On successful status change the event bus is notified. */ updateTask(id: string, updates: Partial): TaskState | undefined; /** * Append a line to the task's in-memory output ring buffer. * Caps at {@link OUTPUT_RING_BUFFER_MAX} lines (oldest lines evicted). */ appendOutput(id: string, line: string): void; /** * Record a verbose-only output line. * Updates lastOutputAt and fires the output listener with a prefix, * but does NOT push to the in-memory ring buffer. */ appendOutputFileOnly(id: string, line: string): void; /** * Write meta.json at most once every 10 seconds per task. * Keeps disk state fresh without hammering I/O on every delta. */ private refreshMetaPeriodically; registerAbort(id: string, controller: AbortController): void; unregisterAbort(id: string): void; getAbortController(id: string): AbortController | undefined; /** * Register a callback for when a task's abort controller fires. * Returns an unsubscribe function. */ onAborted(id: string, cb: () => void): () => void; /** Fire abort listeners for a task. Called when AbortController signals. */ fireAbortListeners(id: string): void; queuePendingQuestion(id: string, q: PendingQuestion): void; dequeuePendingQuestion(id: string): PendingQuestion | undefined; getPendingQuestions(id: string): readonly PendingQuestion[]; /** * Subscribe to status change events. * Returns an unsubscribe function. */ onStatusChange(cb: StatusChangeListener): () => void; /** * Subscribe to output line events. * Returns an unsubscribe function. */ onOutput(cb: OutputListener): () => void; /** * Subscribe to task creation events. * Returns an unsubscribe function. */ onTaskCreate(cb: (task: TaskState) => void): () => void; /** * Emit a status change event to all listeners. * Public so that the TaskHandle implementation can call it directly. */ emitStatusChange(task: TaskState, previousStatus: TaskStatus): void; /** * Remove terminal tasks whose keepAlive window has elapsed since completion. * Returns the number of tasks evicted. */ evictExpired(): number; private generateId; }