Files
SuperCharged-Claude-Code-Up…/dexto/packages/core/src/utils/service-initializer.ts
admin b52318eeae feat: Add intelligent auto-router and enhanced integrations
- Add intelligent-router.sh hook for automatic agent routing
- Add AUTO-TRIGGER-SUMMARY.md documentation
- Add FINAL-INTEGRATION-SUMMARY.md documentation
- Complete Prometheus integration (6 commands + 4 tools)
- Complete Dexto integration (12 commands + 5 tools)
- Enhanced Ralph with access to all agents
- Fix /clawd command (removed disable-model-invocation)
- Update hooks.json to v5 with intelligent routing
- 291 total skills now available
- All 21 commands with automatic routing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-28 00:27:56 +04:00

267 lines
10 KiB
TypeScript

/*
* Service Initializer: Centralized Wiring for Dexto Core Services
*
* This module is responsible for initializing and wiring together all core agent services (LLM, client manager, message manager, event bus, etc.)
* for the Dexto application. It provides a single entry point for constructing the service graph, ensuring consistent dependency injection
* and configuration across CLI, web, and test environments.
*
* **Configuration Pattern:**
* - The primary source of configuration is the config file (e.g., `agent.yml`), which allows users to declaratively specify both high-level
* and low-level service options (such as compression strategies for ContextManager, LLM provider/model, etc.).
* - For most use cases, the config file is sufficient and preferred, as it enables environment-specific, auditable, and user-friendly customization.
*
* **Service Architecture:**
* - All services are initialized based on the provided configuration.
* - For testing scenarios, mock the service dependencies directly using test frameworks rather than relying on service injection patterns.
*
* **Best Practice:**
* - Use the config file for all user-facing and environment-specific configuration, including low-level service details.
* - For testing, use proper mocking frameworks rather than service injection to ensure clean, maintainable tests.
*
* This pattern ensures a clean, scalable, and maintainable architecture, balancing flexibility with simplicity.
*/
import { MCPManager } from '../mcp/manager.js';
import { ToolManager } from '../tools/tool-manager.js';
import { SystemPromptManager } from '../systemPrompt/manager.js';
import { AgentStateManager } from '../agent/state-manager.js';
import { SessionManager } from '../session/index.js';
import { SearchService } from '../search/index.js';
import { dirname, resolve } from 'path';
import { createStorageManager, StorageManager } from '../storage/index.js';
import { createAllowedToolsProvider } from '../tools/confirmation/allowed-tools-provider/factory.js';
import type { IDextoLogger } from '../logger/v2/types.js';
import type { ValidatedAgentConfig } from '@core/agent/schemas.js';
import { AgentEventBus } from '../events/index.js';
import { ResourceManager } from '../resources/manager.js';
import { ApprovalManager } from '../approval/manager.js';
import { MemoryManager } from '../memory/index.js';
import { PluginManager } from '../plugins/manager.js';
import { registerBuiltInPlugins } from '../plugins/registrations/builtins.js';
/**
* Type for the core agent services returned by createAgentServices
*/
export type AgentServices = {
mcpManager: MCPManager;
toolManager: ToolManager;
systemPromptManager: SystemPromptManager;
agentEventBus: AgentEventBus;
stateManager: AgentStateManager;
sessionManager: SessionManager;
searchService: SearchService;
storageManager: StorageManager;
resourceManager: ResourceManager;
approvalManager: ApprovalManager;
memoryManager: MemoryManager;
pluginManager: PluginManager;
};
// High-level factory to load, validate, and wire up all agent services in one call
/**
* Initializes all agent services from a validated configuration.
* @param config The validated agent configuration object
* @param configPath Optional path to the config file (for relative path resolution)
* @param logger Logger instance for this agent (dependency injection)
* @param agentEventBus Pre-created event bus from DextoAgent constructor
* @returns All the initialized services required for a Dexto agent
*/
export async function createAgentServices(
config: ValidatedAgentConfig,
configPath: string | undefined,
logger: IDextoLogger,
agentEventBus: AgentEventBus
): Promise<AgentServices> {
// 0. Initialize telemetry FIRST (before any decorated classes are instantiated)
// This must happen before creating any services that use @InstrumentClass decorator
if (config.telemetry?.enabled) {
const { Telemetry } = await import('../telemetry/telemetry.js');
await Telemetry.init(config.telemetry);
logger.debug('Telemetry initialized');
}
// 1. Use the event bus provided by DextoAgent constructor
logger.debug('Using pre-created agent event bus');
// 2. Initialize storage manager (schema provides in-memory defaults, CLI enrichment adds filesystem paths)
logger.debug('Initializing storage manager');
const storageManager = await createStorageManager(config.storage, logger);
logger.debug('Storage manager initialized', {
cache: config.storage.cache.type,
database: config.storage.database.type,
});
// 3. Initialize approval system (generalized user approval)
// Created before MCP manager since MCP manager depends on it for elicitation support
logger.debug('Initializing approval manager');
const approvalManager = new ApprovalManager(
{
toolConfirmation: {
mode: config.toolConfirmation.mode,
...(config.toolConfirmation.timeout !== undefined && {
timeout: config.toolConfirmation.timeout,
}),
},
elicitation: {
enabled: config.elicitation.enabled,
...(config.elicitation.timeout !== undefined && {
timeout: config.elicitation.timeout,
}),
},
},
logger
);
logger.debug('Approval system initialized');
// 4. Initialize MCP manager
const mcpManager = new MCPManager(logger);
await mcpManager.initializeFromConfig(config.mcpServers);
// 4.1 - Wire approval manager into MCP manager for elicitation support
mcpManager.setApprovalManager(approvalManager);
logger.debug('Approval manager connected to MCP manager for elicitation support');
// 5. Initialize search service
const searchService = new SearchService(storageManager.getDatabase(), logger);
// 6. Initialize memory manager
const memoryManager = new MemoryManager(storageManager.getDatabase(), logger);
logger.debug('Memory manager initialized');
// 6.5 Initialize plugin manager
const configDir = configPath ? dirname(resolve(configPath)) : process.cwd();
const pluginManager = new PluginManager(
{
agentEventBus,
storageManager,
configDir,
},
logger
);
// Register built-in plugins from registry
registerBuiltInPlugins({ pluginManager, config });
logger.debug('Built-in plugins registered');
// Initialize plugin manager (loads custom and registry plugins, validates, calls initialize())
await pluginManager.initialize(config.plugins.custom, config.plugins.registry);
logger.info('Plugin manager initialized');
// 7. Initialize resource manager (MCP + internal resources)
// Moved before tool manager so it can be passed to internal tools
const resourceManager = new ResourceManager(
mcpManager,
{
internalResourcesConfig: config.internalResources,
blobStore: storageManager.getBlobStore(),
},
logger
);
await resourceManager.initialize();
// 8. Initialize tool manager with internal tools options
// 8.1 - Create allowed tools provider based on configuration
const allowedToolsProvider = createAllowedToolsProvider(
{
type: config.toolConfirmation.allowedToolsStorage,
storageManager,
},
logger
);
// 8.2 - Initialize tool manager with direct ApprovalManager integration
const toolManager = new ToolManager(
mcpManager,
approvalManager,
allowedToolsProvider,
config.toolConfirmation.mode,
agentEventBus,
config.toolConfirmation.toolPolicies,
{
internalToolsServices: {
searchService,
resourceManager,
},
internalToolsConfig: config.internalTools,
customToolsConfig: config.customTools,
},
logger
);
// NOTE: toolManager.initialize() is called in DextoAgent.start() after agent reference is set
// This allows custom tools to access the agent for bidirectional communication
const mcpServerCount = Object.keys(config.mcpServers).length;
if (mcpServerCount === 0) {
logger.info('Agent initialized without MCP servers - only built-in capabilities available');
} else {
logger.debug(`MCPManager initialized with ${mcpServerCount} MCP server(s)`);
}
if (config.internalTools.length === 0) {
logger.info('No internal tools enabled by configuration');
} else {
logger.info(`Internal tools enabled: ${config.internalTools.join(', ')}`);
}
// 9. Initialize prompt manager
logger.debug(
`[ServiceInitializer] Creating SystemPromptManager with configPath: ${configPath} → configDir: ${configDir}`
);
const systemPromptManager = new SystemPromptManager(
config.systemPrompt,
configDir,
memoryManager,
config.memories,
logger
);
// 10. Initialize state manager for runtime state tracking
const stateManager = new AgentStateManager(config, agentEventBus, logger);
logger.debug('Agent state manager initialized');
// 11. Initialize session manager
const sessionManager = new SessionManager(
{
stateManager,
systemPromptManager,
toolManager,
agentEventBus,
storageManager, // Add storage manager to session services
resourceManager, // Add resource manager for blob storage
pluginManager, // Add plugin manager for plugin execution
mcpManager, // Add MCP manager for ChatSession
},
{
maxSessions: config.sessions?.maxSessions,
sessionTTL: config.sessions?.sessionTTL,
},
logger
);
// Initialize the session manager with persistent storage
await sessionManager.init();
logger.debug('Session manager initialized with storage support');
// 12.5 Wire up plugin support to ToolManager (after SessionManager is created)
toolManager.setPluginSupport(pluginManager, sessionManager, stateManager);
logger.debug('Plugin support connected to ToolManager');
// 13. Return the core services
return {
mcpManager,
toolManager,
systemPromptManager,
agentEventBus,
stateManager,
sessionManager,
searchService,
storageManager,
resourceManager,
approvalManager,
memoryManager,
pluginManager,
};
}