/**
 * Tool Phases
 *
 * Defines phases for tool execution streaming, allowing
 * real-time updates during tool operations.
 */
import { EventEmitter } from 'events';
// ============================================================================
// Tool Phase Emitter
// ============================================================================
/**
 * Emitter for tool phase events
 */
export class ToolPhaseEmitter extends EventEmitter {
    _toolCallId;
    _toolName;
    startTime = 0;
    currentPhase = 'start';
    progress = 0;
    /** Get the tool call ID */
    get toolCallId() {
        return this._toolCallId;
    }
    /** Get the tool name */
    get toolName() {
        return this._toolName;
    }
    constructor(toolCallId, toolName) {
        super();
        this._toolCallId = toolCallId;
        this._toolName = toolName;
    }
    /**
     * Emit start phase
     */
    start(message) {
        this.startTime = Date.now();
        this.currentPhase = 'start';
        this.progress = 0;
        const event = {
            phase: 'start',
            toolCallId: this.toolCallId,
            toolName: this.toolName,
            progress: 0,
            message: message || `Starting ${this.toolName}...`,
            timestamp: this.startTime,
        };
        this.emit('phase', event);
        this.emit('phase:start', event);
    }
    /**
     * Emit update phase with progress
     */
    update(progress, message) {
        this.currentPhase = 'update';
        this.progress = Math.min(100, Math.max(0, progress));
        const event = {
            phase: 'update',
            toolCallId: this.toolCallId,
            toolName: this.toolName,
            progress: this.progress,
            message,
            timestamp: Date.now(),
        };
        this.emit('phase', event);
        this.emit('phase:update', event);
    }
    /**
     * Emit result phase
     */
    result(result) {
        this.currentPhase = 'result';
        this.progress = 100;
        const duration = Date.now() - this.startTime;
        const fullResult = {
            ...result,
            duration,
        };
        const event = {
            phase: 'result',
            toolCallId: this.toolCallId,
            toolName: this.toolName,
            progress: 100,
            message: result.success ? 'Completed' : 'Failed',
            result: fullResult,
            timestamp: Date.now(),
        };
        this.emit('phase', event);
        this.emit('phase:result', event);
    }
    /**
     * Emit error
     */
    error(error) {
        this.emit('error', error);
        this.result({
            success: false,
            error: error.message,
        });
    }
    /**
     * Get current phase
     */
    getPhase() {
        return this.currentPhase;
    }
    /**
     * Get current progress
     */
    getProgress() {
        return this.progress;
    }
    /**
     * Get elapsed time
     */
    getElapsedTime() {
        return this.startTime > 0 ? Date.now() - this.startTime : 0;
    }
}
// ============================================================================
// Phase Manager
// ============================================================================
/**
 * Manages multiple tool phase emitters
 */
export class ToolPhaseManager extends EventEmitter {
    emitters = new Map();
    phaseListeners = new Set();
    /**
     * Create emitter for a tool call
     */
    createEmitter(toolCallId, toolName) {
        const emitter = new ToolPhaseEmitter(toolCallId, toolName);
        // Forward events to manager
        emitter.on('phase', (event) => {
            this.emit('phase', event);
            this.notifyListeners(event);
        });
        emitter.on('error', (error) => {
            this.emit('error', { toolCallId, toolName, error });
        });
        this.emitters.set(toolCallId, emitter);
        return emitter;
    }
    /**
     * Get emitter for a tool call
     */
    getEmitter(toolCallId) {
        return this.emitters.get(toolCallId);
    }
    /**
     * Remove emitter for a tool call
     */
    removeEmitter(toolCallId) {
        const emitter = this.emitters.get(toolCallId);
        if (emitter) {
            emitter.removeAllListeners();
            this.emitters.delete(toolCallId);
            return true;
        }
        return false;
    }
    /**
     * Add a phase listener
     */
    addPhaseListener(listener) {
        this.phaseListeners.add(listener);
    }
    /**
     * Remove a phase listener
     */
    removePhaseListener(listener) {
        this.phaseListeners.delete(listener);
    }
    /**
     * Notify all listeners
     */
    notifyListeners(event) {
        for (const listener of this.phaseListeners) {
            try {
                listener(event);
            }
            catch {
                // Ignore listener errors
            }
        }
    }
    /**
     * Get all active tool calls
     */
    getActiveToolCalls() {
        return Array.from(this.emitters.entries())
            .filter(([_, emitter]) => emitter.getPhase() !== 'result')
            .map(([toolCallId, emitter]) => ({
            toolCallId,
            toolName: emitter.toolName,
            phase: emitter.getPhase(),
            progress: emitter.getProgress(),
        }));
    }
    /**
     * Clear all emitters
     */
    clear() {
        for (const emitter of this.emitters.values()) {
            emitter.removeAllListeners();
        }
        this.emitters.clear();
    }
    /**
     * Dispose
     */
    dispose() {
        this.clear();
        this.phaseListeners.clear();
        this.removeAllListeners();
    }
}
// ============================================================================
// Singleton
// ============================================================================
let phaseManagerInstance = null;
/**
 * Get or create the ToolPhaseManager singleton
 */
export function getToolPhaseManager() {
    if (!phaseManagerInstance) {
        phaseManagerInstance = new ToolPhaseManager();
    }
    return phaseManagerInstance;
}
/**
 * Reset the ToolPhaseManager singleton
 */
export function resetToolPhaseManager() {
    if (phaseManagerInstance) {
        phaseManagerInstance.dispose();
    }
    phaseManagerInstance = null;
}
//# sourceMappingURL=tool-phases.js.map