/**
 * Agent Stream Service
 *
 * Singleton EventEmitter that broadcasts structured streaming events from
 * in-process Crewly Agent runtimes. SSE endpoints subscribe to this service
 * to forward real-time agent output to the frontend Dashboard.
 *
 * Event types:
 * - text_chunk: Incremental text from the model
 * - tool_call_start: A tool call has started executing
 * - tool_call_finish: A tool call completed (with result and duration)
 * - step_finish: A reasoning step completed
 *
 * @module services/agent/crewly-agent/agent-stream
 */
import { EventEmitter } from 'events';
/** Maximum preview length for serialized args/results */
const MAX_PREVIEW_LENGTH = 200;
/**
 * Singleton service that broadcasts agent streaming events.
 *
 * Runtime services call emit methods when streaming callbacks fire.
 * SSE endpoints subscribe via the EventEmitter 'stream' event.
 *
 * @example
 * ```typescript
 * const streamService = AgentStreamService.getInstance();
 *
 * // Publish events (from runtime)
 * streamService.emitTextChunk('my-agent', 'Hello ');
 *
 * // Subscribe (from SSE endpoint)
 * streamService.on('stream', (event: AgentStreamEvent) => {
 *   if (event.sessionName === targetSession) {
 *     res.write(`data: ${JSON.stringify(event)}\n\n`);
 *   }
 * });
 * ```
 */
export class AgentStreamService extends EventEmitter {
    static instance = null;
    /**
     * Get the singleton instance.
     *
     * @returns Shared AgentStreamService instance
     */
    static getInstance() {
        if (!AgentStreamService.instance) {
            AgentStreamService.instance = new AgentStreamService();
        }
        return AgentStreamService.instance;
    }
    /**
     * Reset the singleton (for testing).
     */
    static resetInstance() {
        if (AgentStreamService.instance) {
            AgentStreamService.instance.removeAllListeners();
        }
        AgentStreamService.instance = null;
    }
    /**
     * Emit a text chunk event.
     *
     * @param sessionName - Agent session name
     * @param text - Text content
     */
    emitTextChunk(sessionName, text) {
        const event = {
            type: 'text_chunk',
            sessionName,
            timestamp: new Date().toISOString(),
            text,
        };
        this.emit('stream', event);
    }
    /**
     * Emit a tool call start event.
     *
     * @param sessionName - Agent session name
     * @param toolName - Name of the tool
     * @param args - Tool arguments
     */
    emitToolCallStart(sessionName, toolName, args) {
        const event = {
            type: 'tool_call_start',
            sessionName,
            timestamp: new Date().toISOString(),
            toolName,
            argsPreview: JSON.stringify(args).substring(0, MAX_PREVIEW_LENGTH),
        };
        this.emit('stream', event);
    }
    /**
     * Emit a tool call finish event.
     *
     * @param sessionName - Agent session name
     * @param toolName - Name of the tool
     * @param args - Tool arguments
     * @param result - Tool execution result
     * @param durationMs - Execution time in milliseconds
     */
    emitToolCallFinish(sessionName, toolName, args, result, durationMs) {
        const event = {
            type: 'tool_call_finish',
            sessionName,
            timestamp: new Date().toISOString(),
            toolName,
            argsPreview: JSON.stringify(args).substring(0, MAX_PREVIEW_LENGTH),
            resultPreview: result ? JSON.stringify(result).substring(0, MAX_PREVIEW_LENGTH) : 'void',
            durationMs,
        };
        this.emit('stream', event);
    }
    /**
     * Emit a step finish event.
     *
     * @param sessionName - Agent session name
     * @param stepIndex - Step number (1-based)
     * @param hasToolCalls - Whether the step included tool calls
     */
    emitStepFinish(sessionName, stepIndex, hasToolCalls) {
        const event = {
            type: 'step_finish',
            sessionName,
            timestamp: new Date().toISOString(),
            stepIndex,
            hasToolCalls,
        };
        this.emit('stream', event);
    }
}
//# sourceMappingURL=agent-stream.service.js.map