export enum TaskStatus { WAITING = 'waiting', PENDING = 'pending', RUNNING = 'running', RATE_LIMITED = 'rate_limited', WAITING_ANSWER = 'waiting_answer', COMPLETED = 'completed', FAILED = 'failed', TIMED_OUT = 'timed_out', CANCELLED = 'cancelled', UNKNOWN = 'unknown', } export const TERMINAL_STATUSES: ReadonlySet = new Set([ TaskStatus.COMPLETED, TaskStatus.FAILED, TaskStatus.CANCELLED, TaskStatus.TIMED_OUT, TaskStatus.UNKNOWN, ]); export function isTerminalStatus(status: TaskStatus): boolean { return TERMINAL_STATUSES.has(status); } export type TaskTypeName = 'coder' | 'planner' | 'tester' | 'researcher' | 'general'; export type Provider = 'codex' | 'copilot' | 'claude-cli'; // --------------------------------------------------------------------------- // PendingQuestion — discriminated union for 5 pause-flow question variants // Spec reference: §3.3 // --------------------------------------------------------------------------- export type PendingQuestion = | { type: 'user_input'; requestId: string; questions: Array<{ id: string; text: string; options?: string[]; allowFreeform?: boolean; }>; } | { type: 'command_approval'; requestId: string; command: string; sandboxPolicy?: string; } | { type: 'file_approval'; requestId: string; fileChanges: Array<{ path: string; patch: string }>; } | { type: 'elicitation'; requestId: string; serverName?: string; message: string; schema?: unknown; } | { type: 'dynamic_tool'; requestId: string; toolName: string; arguments: string; }; export type PendingQuestionType = PendingQuestion['type']; // --------------------------------------------------------------------------- // TaskState — complete in-memory representation of a task // Spec reference: §3.2 (data model), §4.1 (FSM states) // --------------------------------------------------------------------------- export interface TaskState { // Identity id: string; status: TaskStatus; provider: Provider; taskType: TaskTypeName; // Execution prompt: string; cwd: string; model?: string; effort?: 'low' | 'medium' | 'high' | 'xhigh'; sessionId?: string; operationId?: string; // Lifecycle timestamps createdAt: string; updatedAt: string; startedAt?: string; completedAt?: string; lastOutputAt?: string; timeoutMs?: number; timeoutAt?: string; keepAlive?: number; // Output output: string[]; outputFilePath?: string; // Dependencies & labels dependsOn?: string[]; labels: string[]; // Pause state pendingQuestions: PendingQuestion[]; // Error tracking error?: string; exitCode?: number; result?: unknown; // Token usage from last thread/tokenUsage/updated event tokenUsage?: { totalTokens: number; inputTokens: number; outputTokens: number; contextWindow: number | null; }; // Recovery markers recovered?: boolean; degraded?: boolean; }