/**
 * Agent Infrastructure
 *
 * Encapsulates all infrastructure dependencies for agents.
 * Extracts the 15+ managers from BaseAgent to reduce the God Object anti-pattern.
 *
 * Benefits:
 * - Single Responsibility: Infrastructure concerns separated from agent logic
 * - Testability: Easy to mock infrastructure for unit tests
 * - Dependency Injection: Clear dependencies via constructor
 * - Lazy Loading: Heavy resources loaded on-demand
 */
import { EventEmitter } from 'events';
import { getEnhancedMemory } from '../../memory/index.js';
import { logger } from '../../utils/logger.js';
import { getErrorMessage } from '../../errors/index.js';
// Runtime imports for createAgentInfrastructureSync
import { getServiceContainer } from '../../infrastructure/service-container.js';
import { createTokenCounter } from '../../utils/token-counter.js';
import { createContextManager } from '../../context/context-manager-v2.js';
import { getAgentModeManager } from '../agent-mode.js';
import { getSandboxManager } from '../../security/sandbox.js';
import { getMCPClient } from '../../mcp/mcp-client.js';
import { getPromptCacheManager } from '../../optimization/prompt-cache.js';
import { getHooksManager } from '../../hooks/lifecycle-hooks.js';
import { getMoltbotHooksManager } from '../../hooks/moltbot-hooks.js';
import { getModelRouter } from '../../optimization/model-routing.js';
import { getPluginMarketplace } from '../../plugins/marketplace.js';
import { getRepairCoordinator } from '../execution/repair-coordinator.js';
// ============================================================================
// AgentInfrastructure Class
// ============================================================================
/**
 * Encapsulates all infrastructure dependencies for agents.
 *
 * This class manages:
 * - Core services via IServiceContainer (settings, checkpoints, sessions, costs)
 * - Token counting and context management
 * - Agent modes and sandbox security
 * - MCP servers and plugins
 * - Memory system
 * - Model routing optimization
 */
export class AgentInfrastructure extends EventEmitter {
    deps;
    config;
    // Memory system (lazy-loaded)
    _memory = null;
    // Model routing state
    _lastRoutingDecision = null;
    constructor(deps, config = {}) {
        super();
        this.deps = deps;
        this.config = {
            memoryEnabled: config.memoryEnabled ?? true,
            useModelRouting: config.useModelRouting ?? false,
        };
    }
    // ============================================================================
    // Core Service Accessors (from IServiceContainer)
    // ============================================================================
    /** Settings manager */
    get settings() {
        return this.deps.container.settings;
    }
    /** Checkpoint manager */
    get checkpoints() {
        return this.deps.container.checkpoints;
    }
    /** Session store */
    get sessions() {
        return this.deps.container.sessions;
    }
    /** Cost tracker */
    get costs() {
        return this.deps.container.costs;
    }
    // ============================================================================
    // Infrastructure Accessors
    // ============================================================================
    /** Token counter */
    get tokenCounter() {
        return this.deps.tokenCounter;
    }
    /** Context manager */
    get contextManager() {
        return this.deps.contextManager;
    }
    /** Mode manager */
    get modeManager() {
        return this.deps.modeManager;
    }
    /** Sandbox manager */
    get sandboxManager() {
        return this.deps.sandboxManager;
    }
    /** MCP client */
    get mcpClient() {
        return this.deps.mcpClient;
    }
    /** Prompt cache manager */
    get promptCacheManager() {
        return this.deps.promptCacheManager;
    }
    /** Hooks manager */
    get hooksManager() {
        return this.deps.hooksManager;
    }
    /** Moltbot hooks manager (intro, session persistence, command logging) */
    get moltbotHooksManager() {
        return this.deps.moltbotHooksManager;
    }
    /** Model router */
    get modelRouter() {
        return this.deps.modelRouter;
    }
    /** Plugin marketplace */
    get marketplace() {
        return this.deps.marketplace;
    }
    /** Repair coordinator */
    get repairCoordinator() {
        return this.deps.repairCoordinator;
    }
    // ============================================================================
    // Memory System
    // ============================================================================
    /**
     * Lazy-loaded memory system
     */
    get memory() {
        if (!this._memory) {
            this._memory = getEnhancedMemory({
                enabled: this.config.memoryEnabled,
                embeddingEnabled: true,
                useSQLite: true,
                maxMemories: 10000,
                autoSummarize: true,
            });
            // Set project context
            const cwd = process.cwd();
            if (cwd) {
                this._memory.setProjectContext(cwd).catch(err => {
                    logger.warn('Failed to set project context for memory', {
                        error: getErrorMessage(err),
                    });
                });
            }
        }
        return this._memory;
    }
    /** Check if memory is enabled */
    get memoryEnabled() {
        return this.config.memoryEnabled;
    }
    /** Enable/disable memory */
    setMemoryEnabled(enabled) {
        this.config.memoryEnabled = enabled;
        if (!enabled && this._memory) {
            this._memory.dispose();
            this._memory = null;
        }
    }
    /**
     * Store a memory entry
     */
    async remember(type, content, options = {}) {
        if (!this.config.memoryEnabled) {
            throw new Error('Memory system is disabled');
        }
        return this.memory.store({
            type,
            content,
            ...options,
        });
    }
    /**
     * Recall memories matching a query
     */
    async recall(query, options = {}) {
        if (!this.config.memoryEnabled) {
            return [];
        }
        return this.memory.recall({
            query,
            ...options,
        });
    }
    /**
     * Build memory context for system prompt
     */
    async getMemoryContext(options = {}) {
        if (!this.config.memoryEnabled) {
            return '';
        }
        return this.memory.buildContext({
            query: options.query,
            includePreferences: options.includePreferences ?? true,
            includeProject: options.includeProject ?? true,
            includeRecentSummaries: options.includeRecentSummaries ?? true,
        });
    }
    /**
     * Store conversation summary
     */
    async storeConversationSummary(sessionId, summary, topics, messageCount, decisions) {
        if (!this.config.memoryEnabled)
            return;
        await this.memory.storeSummary({
            sessionId,
            summary,
            topics,
            decisions,
            messageCount,
        });
    }
    /**
     * Get memory stats
     */
    getMemoryStats() {
        if (!this.config.memoryEnabled || !this._memory) {
            return null;
        }
        return this.memory.getStats();
    }
    /**
     * Format memory status
     */
    formatMemoryStatus() {
        if (!this.config.memoryEnabled) {
            return '🧠 Memory: Disabled';
        }
        if (!this._memory) {
            return '🧠 Memory: Not initialized';
        }
        return this.memory.formatStatus();
    }
    // ============================================================================
    // Model Routing
    // ============================================================================
    /** Check if model routing is enabled */
    get useModelRouting() {
        return this.config.useModelRouting;
    }
    /** Enable/disable model routing */
    setModelRouting(enabled) {
        this.config.useModelRouting = enabled;
    }
    /** Get last routing decision */
    get lastRoutingDecision() {
        return this._lastRoutingDecision;
    }
    /** Set last routing decision */
    setLastRoutingDecision(decision) {
        this._lastRoutingDecision = decision;
    }
    /**
     * Get model routing statistics
     */
    getModelRoutingStats() {
        return {
            enabled: this.config.useModelRouting,
            totalCost: this.modelRouter.getTotalCost(),
            savings: this.modelRouter.getEstimatedSavings(),
            usageByModel: Object.fromEntries(this.modelRouter.getUsageStats()),
            lastDecision: this._lastRoutingDecision,
        };
    }
    /**
     * Format model routing stats
     */
    formatModelRoutingStats() {
        const stats = this.getModelRoutingStats();
        const lines = [
            '🧭 Model Routing Statistics',
            `├─ Enabled: ${stats.enabled ? '✅' : '❌'}`,
            `├─ Total Cost: $${stats.totalCost.toFixed(4)}`,
            `├─ Savings: $${stats.savings.saved.toFixed(4)} (${stats.savings.percentage.toFixed(1)}%)`,
        ];
        if (stats.lastDecision) {
            lines.push(`├─ Last Model: ${stats.lastDecision.recommendedModel}`);
            lines.push(`└─ Reason: ${stats.lastDecision.reason}`);
        }
        else {
            lines.push('└─ No routing decisions yet');
        }
        return lines.join('\n');
    }
    // ============================================================================
    // Lifecycle
    // ============================================================================
    /**
     * Dispose of all resources
     */
    async dispose() {
        // Dispose token counter
        if (this.deps.tokenCounter) {
            this.deps.tokenCounter.dispose();
        }
        // Dispose context manager
        if (this.deps.contextManager) {
            this.deps.contextManager.dispose();
        }
        // Dispose repair coordinator
        if (this.deps.repairCoordinator) {
            this.deps.repairCoordinator.dispose();
        }
        // Dispose memory
        if (this._memory) {
            this._memory.dispose();
            this._memory = null;
        }
        this.emit('disposed');
    }
}
// ============================================================================
// Factory Function
// ============================================================================
/**
 * Create AgentInfrastructure with default implementations
 *
 * This factory uses the Service Locator pattern internally but returns
 * a properly encapsulated AgentInfrastructure instance.
 */
export async function createAgentInfrastructure(apiKey, model, baseURL, config = {}) {
    // Lazy imports to avoid circular dependencies
    const { getServiceContainer } = await import('../../infrastructure/service-container.js');
    const { createTokenCounter } = await import('../../utils/token-counter.js');
    const { createContextManager } = await import('../../context/context-manager-v2.js');
    const { getAgentModeManager } = await import('../agent-mode.js');
    const { getSandboxManager } = await import('../../security/sandbox.js');
    const { getMCPClient } = await import('../../mcp/mcp-client.js');
    const { getPromptCacheManager } = await import('../../optimization/prompt-cache.js');
    const { getHooksManager } = await import('../../hooks/lifecycle-hooks.js');
    const { getMoltbotHooksManager } = await import('../../hooks/moltbot-hooks.js');
    const { getModelRouter } = await import('../../optimization/model-routing.js');
    const { getPluginMarketplace } = await import('../../plugins/marketplace.js');
    const { getRepairCoordinator } = await import('../execution/repair-coordinator.js');
    const container = getServiceContainer();
    const deps = {
        container,
        tokenCounter: createTokenCounter(model),
        contextManager: createContextManager(model),
        modeManager: getAgentModeManager(),
        sandboxManager: getSandboxManager(),
        mcpClient: getMCPClient(),
        promptCacheManager: getPromptCacheManager(),
        hooksManager: getHooksManager(process.cwd()),
        moltbotHooksManager: getMoltbotHooksManager(process.cwd()),
        modelRouter: getModelRouter(),
        marketplace: getPluginMarketplace(),
        repairCoordinator: getRepairCoordinator(apiKey, baseURL),
    };
    return new AgentInfrastructure(deps, config);
}
/**
 * Create AgentInfrastructure for testing with mock dependencies
 */
export function createTestInfrastructure(overrides = {}, config = {}) {
    // Create minimal mock implementations
    const mockContainer = {
        settings: {},
        checkpoints: {},
        sessions: {},
        costs: {},
    };
    const mockTokenCounter = {
        dispose: () => { },
    };
    const mockContextManager = {
        dispose: () => { },
    };
    const mockModeManager = {};
    const mockSandboxManager = {};
    const mockMCPClient = {};
    const mockPromptCacheManager = {};
    const mockHooksManager = {};
    const mockMoltbotHooksManager = {
        getIntroManager: () => ({
            loadIntro: async () => ({ content: '', sources: [], truncated: false }),
            getConfig: () => ({ enabled: false, sources: [], combineMode: 'prepend' }),
        }),
        getSessionManager: () => ({
            startSession: async () => ({ id: 'test', projectPath: '', createdAt: '', updatedAt: '', messages: [], metadata: {} }),
            endSession: async () => { },
            dispose: () => { },
        }),
        getCommandLogger: () => ({
            logToolCall: () => { },
            logBashCommand: () => { },
            logFileEdit: () => { },
            flush: async () => { },
            dispose: () => { },
        }),
        dispose: () => { },
    };
    const mockModelRouter = {
        getTotalCost: () => 0,
        getEstimatedSavings: () => ({ saved: 0, percentage: 0 }),
        getUsageStats: () => new Map(),
    };
    const mockMarketplace = {};
    const mockRepairCoordinator = {
        dispose: () => { },
    };
    const deps = {
        container: mockContainer,
        tokenCounter: mockTokenCounter,
        contextManager: mockContextManager,
        modeManager: mockModeManager,
        sandboxManager: mockSandboxManager,
        mcpClient: mockMCPClient,
        promptCacheManager: mockPromptCacheManager,
        hooksManager: mockHooksManager,
        moltbotHooksManager: mockMoltbotHooksManager,
        modelRouter: mockModelRouter,
        marketplace: mockMarketplace,
        repairCoordinator: mockRepairCoordinator,
        ...overrides,
    };
    return new AgentInfrastructure(deps, {
        memoryEnabled: false,
        ...config,
    });
}
/**
 * Create AgentInfrastructure synchronously using singleton getters
 *
 * This is the preferred factory for use in constructors where async
 * initialization isn't possible. Uses the same sync singleton patterns
 * that were previously scattered throughout CodeBuddyAgent.
 */
export function createAgentInfrastructureSync(options, config = {}) {
    // Use top-level imports (ESM compatible)
    const container = getServiceContainer();
    const deps = {
        container,
        tokenCounter: createTokenCounter(options.model),
        contextManager: createContextManager(options.model, options.maxContextTokens),
        modeManager: getAgentModeManager(),
        sandboxManager: getSandboxManager(),
        mcpClient: getMCPClient(),
        promptCacheManager: getPromptCacheManager(),
        hooksManager: getHooksManager(process.cwd()),
        moltbotHooksManager: getMoltbotHooksManager(process.cwd()),
        modelRouter: getModelRouter(),
        marketplace: getPluginMarketplace(),
        repairCoordinator: getRepairCoordinator(options.apiKey, options.baseURL),
    };
    return new AgentInfrastructure(deps, config);
}
//# sourceMappingURL=agent-infrastructure.js.map