/** * Config Adapter Tests */ import { describe, it, expect } from 'vitest'; import { systemConfigToV3Config, v3ConfigToSystemConfig } from '../src/config-adapter.js'; import type { SystemConfig } from '@claude-flow/shared'; import type { V3Config } from '../src/types.js'; describe('ConfigAdapter', () => { describe('systemConfigToV3Config', () => { it('should convert minimal SystemConfig to V3Config', () => { const systemConfig: SystemConfig = { orchestrator: { lifecycle: { autoStart: true, maxConcurrentAgents: 10, shutdownTimeoutMs: 30000, cleanupOrphanedAgents: true, }, session: { dataDir: '/test/data', persistState: true, stateFile: 'session.json', }, monitoring: { enabled: true, metricsIntervalMs: 5000, healthCheckIntervalMs: 10000, }, }, swarm: { topology: 'hierarchical-mesh', maxAgents: 15, }, memory: { type: 'hybrid', }, mcp: { enabled: true, transport: { type: 'stdio', host: 'localhost', port: 3000, }, enabledTools: ['agent/*', 'swarm/*'], security: { requireAuth: false, allowedOrigins: ['*'], rateLimiting: { enabled: true, maxRequestsPerMinute: 100, }, }, }, logging: { level: 'info', pretty: true, destination: 'console', format: 'text', }, hooks: { enabled: true, autoExecute: true, definitions: [], }, }; const v3Config = systemConfigToV3Config(systemConfig); expect(v3Config.version).toBe('3.0.0'); expect(v3Config.projectRoot).toBe('/test/data'); expect(v3Config.agents.maxConcurrent).toBe(10); expect(v3Config.agents.autoSpawn).toBe(false); // Default is false for safety expect(v3Config.swarm.topology).toBe('hierarchical-mesh'); // V3 anti-drift default expect(v3Config.swarm.maxAgents).toBe(15); expect(v3Config.memory.backend).toBe('hybrid'); expect(v3Config.mcp.serverHost).toBe('localhost'); expect(v3Config.mcp.serverPort).toBe(3000); expect(v3Config.mcp.autoStart).toBe(false); // Default is false for safety expect(v3Config.cli.colorOutput).toBe(true); expect(v3Config.cli.verbosity).toBe('normal'); // Default verbosity level expect(v3Config.hooks.enabled).toBe(false); // Default is false expect(v3Config.hooks.autoExecute).toBe(false); // Default is false }); it('should handle missing optional fields', () => { const minimalConfig: SystemConfig = { orchestrator: { lifecycle: { autoStart: false, maxConcurrentAgents: 5, shutdownTimeoutMs: 30000, cleanupOrphanedAgents: true, }, session: { dataDir: '/data', persistState: true, stateFile: 'session.json', }, monitoring: { enabled: true, metricsIntervalMs: 5000, healthCheckIntervalMs: 10000, }, }, swarm: { topology: 'mesh', maxAgents: 10, }, memory: { type: 'sqlite', }, mcp: { enabled: false, transport: { type: 'http', host: '127.0.0.1', port: 8080, }, enabledTools: [], security: { requireAuth: false, allowedOrigins: ['*'], rateLimiting: { enabled: true, maxRequestsPerMinute: 100, }, }, }, logging: { level: 'debug', pretty: false, destination: 'file', format: 'json', }, hooks: { enabled: false, autoExecute: false, definitions: [], }, }; const v3Config = systemConfigToV3Config(minimalConfig); expect(v3Config.agents.maxConcurrent).toBe(5); expect(v3Config.agents.autoSpawn).toBe(false); expect(v3Config.memory.backend).toBe('sqlite'); expect(v3Config.mcp.autoStart).toBe(false); expect(v3Config.cli.colorOutput).toBe(true); // Default is always true }); }); describe('v3ConfigToSystemConfig', () => { it('should convert V3Config to SystemConfig', () => { const v3Config: V3Config = { version: '3.0.0', projectRoot: '/test/project', agents: { defaultType: 'coder', autoSpawn: true, maxConcurrent: 20, timeout: 60000, providers: [], }, swarm: { topology: 'hierarchical', maxAgents: 20, autoScale: true, coordinationStrategy: 'consensus', healthCheckInterval: 15000, }, memory: { backend: 'agentdb', persistPath: '/test/memory', cacheSize: 500000, enableHNSW: true, vectorDimension: 768, }, mcp: { serverHost: '0.0.0.0', serverPort: 4000, autoStart: true, transportType: 'websocket', tools: ['memory/*'], }, cli: { colorOutput: true, interactive: true, verbosity: 'verbose', outputFormat: 'json', progressStyle: 'bar', }, hooks: { enabled: true, autoExecute: false, hooks: [ { name: 'test-hook', event: 'pre-task', handler: '/path/to/handler.js', priority: 10, enabled: true, }, ], }, }; const systemConfig = v3ConfigToSystemConfig(v3Config); // Core orchestrator conversion (autoStart not mapped) expect(systemConfig.orchestrator?.lifecycle?.maxConcurrentAgents).toBe(20); expect(systemConfig.orchestrator?.session?.dataDir).toBe('/test/project'); expect(systemConfig.swarm?.topology).toBe('hierarchical'); expect(systemConfig.swarm?.maxAgents).toBe(20); expect(systemConfig.swarm?.autoScale?.enabled).toBe(true); expect(systemConfig.swarm?.coordination?.consensusRequired).toBe(true); expect(systemConfig.memory?.type).toBe('agentdb'); expect(systemConfig.memory?.path).toBe('/test/memory'); expect(systemConfig.memory?.agentdb?.dimensions).toBe(768); expect(systemConfig.memory?.agentdb?.indexType).toBe('hnsw'); // MCP enabled not mapped, just transport expect(systemConfig.mcp?.transport?.type).toBe('websocket'); expect(systemConfig.mcp?.transport?.host).toBe('0.0.0.0'); expect(systemConfig.mcp?.transport?.port).toBe(4000); // logging and hooks not included in v3ConfigToSystemConfig conversion }); it('should handle different coordination strategies', () => { const leaderConfig: V3Config = { version: '3.0.0', projectRoot: '/test', agents: { defaultType: 'coder', autoSpawn: false, maxConcurrent: 10, timeout: 30000, providers: [], }, swarm: { topology: 'star', maxAgents: 10, autoScale: false, coordinationStrategy: 'leader', healthCheckInterval: 5000, }, memory: { backend: 'memory', persistPath: '/data', cacheSize: 100000, enableHNSW: false, vectorDimension: 1536, }, mcp: { serverHost: 'localhost', serverPort: 3000, autoStart: false, transportType: 'stdio', tools: [], }, cli: { colorOutput: true, interactive: true, verbosity: 'normal', outputFormat: 'text', progressStyle: 'spinner', }, hooks: { enabled: false, autoExecute: false, hooks: [], }, }; const systemConfig = v3ConfigToSystemConfig(leaderConfig); expect(systemConfig.swarm?.coordination?.consensusRequired).toBe(false); expect(systemConfig.memory?.agentdb?.indexType).toBe('flat'); }); }); describe('round-trip conversion', () => { it('should preserve key config values through round-trip', () => { const originalSystemConfig: SystemConfig = { orchestrator: { lifecycle: { autoStart: true, maxConcurrentAgents: 12, shutdownTimeoutMs: 30000, cleanupOrphanedAgents: true, }, session: { dataDir: '/test/roundtrip', persistState: true, stateFile: 'session.json', }, monitoring: { enabled: true, metricsIntervalMs: 5000, healthCheckIntervalMs: 8000, }, }, swarm: { topology: 'hierarchical-mesh', maxAgents: 12, }, memory: { type: 'hybrid', path: '/test/memory', agentdb: { dimensions: 1536, indexType: 'hnsw', efConstruction: 200, m: 16, quantization: 'none', }, }, mcp: { enabled: true, transport: { type: 'http', host: '127.0.0.1', port: 5000, }, enabledTools: ['test/*'], security: { requireAuth: false, allowedOrigins: ['*'], rateLimiting: { enabled: true, maxRequestsPerMinute: 100, }, }, }, logging: { level: 'warn', pretty: true, destination: 'console', format: 'text', }, hooks: { enabled: true, autoExecute: true, definitions: [], }, }; const v3Config = systemConfigToV3Config(originalSystemConfig); const roundTripConfig = v3ConfigToSystemConfig(v3Config); // Core values preserved through round-trip expect(roundTripConfig.orchestrator?.lifecycle?.maxConcurrentAgents).toBe(12); expect(roundTripConfig.swarm?.topology).toBe('hierarchical-mesh'); expect(roundTripConfig.swarm?.maxAgents).toBe(12); expect(roundTripConfig.memory?.type).toBe('hybrid'); expect(roundTripConfig.memory?.path).toBe('/test/memory'); expect(roundTripConfig.mcp?.transport?.type).toBe('http'); expect(roundTripConfig.mcp?.transport?.port).toBe(5000); // Note: logging is not included in v3ConfigToSystemConfig }); }); });