import { createDecorator, type ServiceIdentifier } from '#/_base/di/instantiation'; import type { Event } from '#/_base/event'; import type { IDisposable } from '#/_base/di/lifecycle'; export type TaskState = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'; export const TERMINAL_TASK_STATES: ReadonlySet = new Set([ 'completed', 'failed', 'cancelled', ]); export class TaskCancelledError extends Error { constructor(readonly taskId: string) { super(`Task ${taskId} was cancelled`); this.name = 'TaskCancelledError'; } } export interface ITaskHandle extends IDisposable { readonly id: string; readonly state: TaskState; readonly result: Promise; readonly onDidChangeState: Event; readonly onDidOutput: Event; cancel(): void; } export interface IDeferredHandle extends ITaskHandle { resolve(value: T): void; reject(reason?: unknown): void; } export interface ITaskService { readonly _serviceBrand: undefined; run(fn: (signal: AbortSignal, output: (data: string) => void) => Promise): ITaskHandle; defer(): IDeferredHandle; } export const ITaskService: ServiceIdentifier = createDecorator('taskService');