/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import { HookRegistry } from './hookRegistry.js';
import { HookRunner } from './hookRunner.js';
import { HookAggregator } from './hookAggregator.js';
import { HookPlanner } from './hookPlanner.js';
import { HookEventHandler } from './hookEventHandler.js';
import { logs } from '@opentelemetry/api-logs';
import { SERVICE_NAME } from '../telemetry/constants.js';
import { debugLogger } from '../utils/debugLogger.js';
export class HookSystem {
    hookRegistry;
    hookRunner;
    hookAggregator;
    hookPlanner;
    hookEventHandler;
    constructor(config) {
        const logger = logs.getLogger(SERVICE_NAME);
        const messageBus = config.getMessageBus();
        // Initialize components
        this.hookRegistry = new HookRegistry(config);
        this.hookRunner = new HookRunner(config);
        this.hookAggregator = new HookAggregator();
        this.hookPlanner = new HookPlanner(this.hookRegistry);
        this.hookEventHandler = new HookEventHandler(config, logger, this.hookPlanner, this.hookRunner, this.hookAggregator, messageBus);
    }
    /**
     * Initialize the hook system
     */
    async initialize() {
        await this.hookRegistry.initialize();
        debugLogger.debug('Hook system initialized successfully');
    }
    /**
     * Get the hook event bus for firing events
     */
    getEventHandler() {
        return this.hookEventHandler;
    }
    /**
     * Get hook registry for management operations
     */
    getRegistry() {
        return this.hookRegistry;
    }
    /**
     * Enable or disable a hook
     */
    setHookEnabled(hookName, enabled) {
        this.hookRegistry.setHookEnabled(hookName, enabled);
    }
    /**
     * Get all registered hooks for display/management
     */
    getAllHooks() {
        return this.hookRegistry.getAllHooks();
    }
    /**
     * Fire hook events directly
     */
    async fireSessionStartEvent(source) {
        const result = await this.hookEventHandler.fireSessionStartEvent(source);
        return result.finalOutput;
    }
    async fireSessionEndEvent(reason) {
        return this.hookEventHandler.fireSessionEndEvent(reason);
    }
    async firePreCompressEvent(trigger) {
        return this.hookEventHandler.firePreCompressEvent(trigger);
    }
    async fireBeforeAgentEvent(prompt) {
        const result = await this.hookEventHandler.fireBeforeAgentEvent(prompt);
        return result.finalOutput;
    }
    async fireAfterAgentEvent(prompt, response, stopHookActive = false) {
        const result = await this.hookEventHandler.fireAfterAgentEvent(prompt, response, stopHookActive);
        return result.finalOutput;
    }
    async fireBeforeModelEvent(llmRequest) {
        try {
            const result = await this.hookEventHandler.fireBeforeModelEvent(llmRequest);
            const hookOutput = result.finalOutput;
            if (hookOutput?.shouldStopExecution()) {
                return {
                    blocked: true,
                    stopped: true,
                    reason: hookOutput.getEffectiveReason(),
                };
            }
            const blockingError = hookOutput?.getBlockingError();
            if (blockingError?.blocked) {
                const beforeModelOutput = hookOutput;
                const syntheticResponse = beforeModelOutput.getSyntheticResponse();
                return {
                    blocked: true,
                    reason: hookOutput?.getEffectiveReason() || 'Model call blocked by hook',
                    syntheticResponse,
                };
            }
            if (hookOutput) {
                const beforeModelOutput = hookOutput;
                const modifiedRequest = beforeModelOutput.applyLLMRequestModifications(llmRequest);
                return {
                    blocked: false,
                    modifiedConfig: modifiedRequest?.config,
                    modifiedContents: modifiedRequest?.contents,
                };
            }
            return { blocked: false };
        }
        catch (error) {
            debugLogger.debug(`BeforeModelHookEvent failed:`, error);
            return { blocked: false };
        }
    }
    async fireAfterModelEvent(originalRequest, chunk) {
        try {
            const result = await this.hookEventHandler.fireAfterModelEvent(originalRequest, chunk);
            const hookOutput = result.finalOutput;
            if (hookOutput?.shouldStopExecution()) {
                return {
                    response: chunk,
                    stopped: true,
                    reason: hookOutput.getEffectiveReason(),
                };
            }
            const blockingError = hookOutput?.getBlockingError();
            if (blockingError?.blocked) {
                return {
                    response: chunk,
                    blocked: true,
                    reason: hookOutput?.getEffectiveReason(),
                };
            }
            if (hookOutput) {
                const afterModelOutput = hookOutput;
                const modifiedResponse = afterModelOutput.getModifiedResponse();
                if (modifiedResponse) {
                    return { response: modifiedResponse };
                }
            }
            return { response: chunk };
        }
        catch (error) {
            debugLogger.debug(`AfterModelHookEvent failed:`, error);
            return { response: chunk };
        }
    }
    async fireBeforeToolSelectionEvent(llmRequest) {
        try {
            const result = await this.hookEventHandler.fireBeforeToolSelectionEvent(llmRequest);
            const hookOutput = result.finalOutput;
            if (hookOutput) {
                const toolSelectionOutput = hookOutput;
                const modifiedConfig = toolSelectionOutput.applyToolConfigModifications({
                    toolConfig: llmRequest.config?.toolConfig,
                    tools: llmRequest.config?.tools,
                });
                return {
                    toolConfig: modifiedConfig.toolConfig,
                    tools: modifiedConfig.tools,
                };
            }
            return {};
        }
        catch (error) {
            debugLogger.debug(`BeforeToolSelectionEvent failed:`, error);
            return {};
        }
    }
    async fireBeforeToolEvent(toolName, toolInput, mcpContext) {
        try {
            const result = await this.hookEventHandler.fireBeforeToolEvent(toolName, toolInput, mcpContext);
            return result.finalOutput;
        }
        catch (error) {
            debugLogger.debug(`BeforeTool hook failed for ${toolName}:`, error);
            return undefined;
        }
    }
    async fireAfterToolEvent(toolName, toolInput, toolResponse, mcpContext) {
        try {
            const result = await this.hookEventHandler.fireAfterToolEvent(toolName, toolInput, toolResponse, mcpContext);
            return result.finalOutput;
        }
        catch (error) {
            debugLogger.debug(`AfterTool hook failed for ${toolName}:`, error);
            return undefined;
        }
    }
}
//# sourceMappingURL=hookSystem.js.map