/**
 * @fileoverview Task model for Claude prompt execution
 *
 * Represents a single task (prompt) to be executed by a Claude session.
 * Tasks support priority ordering, dependencies, and completion detection.
 *
 * @module task
 */
import { v4 as uuidv4 } from 'uuid';
/** Pre-compiled pattern for generic promise tag detection */
const PROMISE_TAG_PATTERN = /<promise>[^<]+<\/promise>/;
/** Escapes special regex characters in a string for safe use in RegExp constructor */
function escapeRegex(str) {
    return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
/**
 * A task representing a prompt to be executed by a Claude session.
 *
 * @description
 * Tasks have a lifecycle: pending → running → completed/failed
 * They support priority ordering and dependency chains.
 */
export class Task {
    id;
    prompt;
    workingDir;
    priority;
    dependencies;
    completionPhrase;
    timeoutMs;
    createdAt;
    _status = 'pending';
    _assignedSessionId = null;
    _startedAt = null;
    _completedAt = null;
    _output = '';
    _error = null;
    /** Pre-compiled regex for completion phrase detection (avoids re-creation per check) */
    _completionPattern;
    constructor(options, id) {
        this.id = id || uuidv4();
        this.prompt = options.prompt;
        this.workingDir = options.workingDir || process.cwd();
        this.priority = options.priority ?? 0;
        this.dependencies = options.dependencies || [];
        this.completionPhrase = options.completionPhrase;
        this.timeoutMs = options.timeoutMs;
        this.createdAt = Date.now();
        this._completionPattern = options.completionPhrase
            ? new RegExp(`<promise>${escapeRegex(options.completionPhrase)}</promise>`)
            : null;
    }
    get status() {
        return this._status;
    }
    get assignedSessionId() {
        return this._assignedSessionId;
    }
    get startedAt() {
        return this._startedAt;
    }
    get completedAt() {
        return this._completedAt;
    }
    get output() {
        return this._output;
    }
    get error() {
        return this._error;
    }
    isPending() {
        return this._status === 'pending';
    }
    isRunning() {
        return this._status === 'running';
    }
    isCompleted() {
        return this._status === 'completed';
    }
    isFailed() {
        return this._status === 'failed';
    }
    isDone() {
        return this._status === 'completed' || this._status === 'failed';
    }
    toDefinition() {
        return {
            id: this.id,
            prompt: this.prompt,
            workingDir: this.workingDir,
            priority: this.priority,
            dependencies: this.dependencies,
            completionPhrase: this.completionPhrase,
            timeoutMs: this.timeoutMs,
        };
    }
    toState() {
        return {
            ...this.toDefinition(),
            status: this._status,
            assignedSessionId: this._assignedSessionId,
            createdAt: this.createdAt,
            startedAt: this._startedAt,
            completedAt: this._completedAt,
            output: this._output,
            error: this._error,
        };
    }
    /** Reconstructs a Task from persisted state. */
    static fromState(state) {
        const task = new Task({
            prompt: state.prompt,
            workingDir: state.workingDir,
            priority: state.priority,
            dependencies: state.dependencies,
            completionPhrase: state.completionPhrase,
            timeoutMs: state.timeoutMs,
        }, state.id);
        task._status = state.status;
        task._assignedSessionId = state.assignedSessionId;
        task._startedAt = state.startedAt;
        task._completedAt = state.completedAt;
        task._output = state.output;
        task._error = state.error;
        return task;
    }
    /** Assigns this task to a session and marks it as running. */
    assign(sessionId) {
        if (this._status !== 'pending') {
            throw new Error(`Cannot assign task ${this.id}: status is ${this._status}`);
        }
        this._status = 'running';
        this._assignedSessionId = sessionId;
        this._startedAt = Date.now();
    }
    appendOutput(output) {
        this._output += output;
    }
    setError(error) {
        this._error = error;
    }
    complete() {
        this._status = 'completed';
        this._completedAt = Date.now();
    }
    fail(error) {
        this._status = 'failed';
        this._completedAt = Date.now();
        if (error) {
            this._error = error;
        }
    }
    reset() {
        this._status = 'pending';
        this._assignedSessionId = null;
        this._startedAt = null;
        this._completedAt = null;
        this._output = '';
        this._error = null;
    }
    /** Checks if output contains the completion phrase. */
    checkCompletion(output) {
        if (this._completionPattern) {
            return this._completionPattern.test(output);
        }
        // Default: check for any promise tag completion
        return PROMISE_TAG_PATTERN.test(output);
    }
    /** Returns true if the task has exceeded its timeout. */
    isTimedOut() {
        if (!this.timeoutMs || !this._startedAt) {
            return false;
        }
        return Date.now() - this._startedAt > this.timeoutMs;
    }
}
//# sourceMappingURL=task.js.map