Skip to main content
Glama
ConfigManager.test.ts14.5 kB
/** * Unit tests for ConfigManager */ import { existsSync, unlinkSync, writeFileSync } from "fs"; import { join } from "path"; import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { ProcessingMode } from "../../types/core.js"; import { ConfigManager, DEFAULT_CONFIG } from "../../utils/config.js"; describe("ConfigManager", () => { let configManager: ConfigManager; const test_config_file = "./test-config.json"; const test_config_dir = "./test-config"; beforeEach(() => { // Clear environment variables delete process.env.COGNITIVE_DEFAULT_MODE; delete process.env.COGNITIVE_ENABLE_EMOTION; delete process.env.COGNITIVE_TEMPERATURE; delete process.env.COGNITIVE_WORKING_MEMORY_CAPACITY; }); afterEach(() => { // Clean up test files if (existsSync(test_config_file)) { unlinkSync(test_config_file); } if (existsSync(test_config_dir)) { if (existsSync(join(test_config_dir, "cognitive.json"))) { unlinkSync(join(test_config_dir, "cognitive.json")); } try { unlinkSync(test_config_dir); } catch { // Directory might not be empty, ignore } } }); describe("Default Configuration", () => { it("should load default configuration", () => { configManager = new ConfigManager(); const config = configManager.getConfig(); expect(config.default_mode).toBe(ProcessingMode.BALANCED); expect(config.enable_emotion).toBe(true); expect(config.enable_metacognition).toBe(true); expect(config.working_memory_capacity).toBe(7); expect(config.temperature).toBe(0.7); expect(config.timeout_ms).toBe(30000); }); it("should apply constructor overrides", () => { const overrides = { temperature: 0.9, enable_emotion: false, max_reasoning_depth: 15, }; configManager = new ConfigManager(overrides); const config = configManager.getConfig(); expect(config.temperature).toBe(0.9); expect(config.enable_emotion).toBe(false); expect(config.max_reasoning_depth).toBe(15); // Other values should remain default expect(config.working_memory_capacity).toBe(7); }); }); describe("Environment Variable Configuration", () => { it("should load configuration from environment variables", () => { process.env.COGNITIVE_DEFAULT_MODE = "creative"; process.env.COGNITIVE_ENABLE_EMOTION = "false"; process.env.COGNITIVE_TEMPERATURE = "0.8"; process.env.COGNITIVE_WORKING_MEMORY_CAPACITY = "5"; process.env.COGNITIVE_TIMEOUT_MS = "45000"; configManager = new ConfigManager(); const config = configManager.getConfig(); expect(config.default_mode).toBe(ProcessingMode.CREATIVE); expect(config.enable_emotion).toBe(false); expect(config.temperature).toBe(0.8); expect(config.working_memory_capacity).toBe(5); expect(config.timeout_ms).toBe(45000); }); it("should handle boolean environment variables correctly", () => { process.env.COGNITIVE_ENABLE_EMOTION = "true"; process.env.COGNITIVE_ENABLE_METACOGNITION = "false"; process.env.COGNITIVE_ENABLE_PREDICTION = "true"; configManager = new ConfigManager(); const config = configManager.getConfig(); expect(config.enable_emotion).toBe(true); expect(config.enable_metacognition).toBe(false); expect(config.enable_prediction).toBe(true); }); it("should handle numeric environment variables correctly", () => { process.env.COGNITIVE_NOISE_LEVEL = "0.2"; process.env.COGNITIVE_ATTENTION_THRESHOLD = "0.4"; process.env.COGNITIVE_CONFIDENCE_THRESHOLD = "0.8"; configManager = new ConfigManager(); const config = configManager.getConfig(); expect(config.noise_level).toBe(0.2); expect(config.attention_threshold).toBe(0.4); expect(config.confidence_threshold).toBe(0.8); }); }); describe("File-based Configuration", () => { it("should load configuration from JSON file", () => { const file_config = { temperature: 0.5, enable_emotion: false, working_memory_capacity: 10, max_reasoning_depth: 20, }; writeFileSync(test_config_file, JSON.stringify(file_config)); configManager = new ConfigManager(); configManager.addConfigFilePath(test_config_file); configManager.reloadConfig(); const config = configManager.getConfig(); expect(config.temperature).toBe(0.5); expect(config.enable_emotion).toBe(false); expect(config.working_memory_capacity).toBe(10); expect(config.max_reasoning_depth).toBe(20); }); it("should handle invalid JSON files gracefully", () => { writeFileSync(test_config_file, "invalid json content"); configManager = new ConfigManager(); configManager.addConfigFilePath(test_config_file); // Should not throw, should use defaults expect(() => configManager.reloadConfig()).not.toThrow(); const config = configManager.getConfig(); expect(config.temperature).toBe(DEFAULT_CONFIG.temperature); }); it("should handle non-existent files gracefully", () => { configManager = new ConfigManager(); configManager.addConfigFilePath("./non-existent-config.json"); expect(() => configManager.reloadConfig()).not.toThrow(); const config = configManager.getConfig(); expect(config.temperature).toBe(DEFAULT_CONFIG.temperature); }); }); describe("Configuration Priority", () => { it("should apply configurations in correct priority order", () => { // Create file config const file_config = { temperature: 0.5, enable_emotion: false, }; writeFileSync(test_config_file, JSON.stringify(file_config)); // Set environment variable process.env.COGNITIVE_TEMPERATURE = "0.8"; // Constructor override const constructor_override = { temperature: 0.9, }; configManager = new ConfigManager(constructor_override); const config = configManager.getConfig(); // Constructor override should have highest priority expect(config.temperature).toBe(0.9); // Default values should be used for properties not in constructor override expect(config.enable_emotion).toBe(true); // Default value }); }); describe("Configuration Validation", () => { it("should validate configuration ranges", () => { expect(() => { new ConfigManager({ working_memory_capacity: 25, // Invalid: > 20 }); }).toThrow("Working memory capacity must be between 1 and 20"); expect(() => { new ConfigManager({ temperature: 3.0, // Invalid: > 2 }); }).toThrow("Temperature must be between 0 and 2"); expect(() => { new ConfigManager({ noise_level: 1.5, // Invalid: > 1 }); }).toThrow("Noise level must be between 0 and 1"); }); it("should return validation results", () => { configManager = new ConfigManager(); const result = configManager.validateConfig(); expect(result.valid).toBe(true); expect(result.errors).toHaveLength(0); expect(Array.isArray(result.warnings)).toBe(true); }); it("should detect configuration warnings", () => { configManager = new ConfigManager({ episodic_memory_size: 50, // Very small max_concurrent_sessions: 2000, // Very large }); const result = configManager.validateConfig(); expect(result.valid).toBe(true); expect(result.warnings.length).toBeGreaterThan(0); expect( result.warnings.some((w) => w.includes("Episodic memory size")) ).toBe(true); expect( result.warnings.some((w) => w.includes("concurrent session limit")) ).toBe(true); }); }); describe("Configuration Management", () => { beforeEach(() => { configManager = new ConfigManager(); }); it("should get and set individual configuration values", () => { expect(configManager.get("temperature")).toBe(0.7); configManager.set("temperature", 0.9); expect(configManager.get("temperature")).toBe(0.9); }); it("should update configuration with partial values", () => { const updates = { temperature: 0.8, enable_emotion: false, max_reasoning_depth: 15, }; configManager.updateConfig(updates); const config = configManager.getConfig(); expect(config.temperature).toBe(0.8); expect(config.enable_emotion).toBe(false); expect(config.max_reasoning_depth).toBe(15); // Other values should remain unchanged expect(config.working_memory_capacity).toBe(7); }); it("should get configuration sources", () => { const sources = configManager.getConfigSources(); expect(Array.isArray(sources)).toBe(true); expect(sources.some((s) => s.name === "environment")).toBe(true); }); it("should reload configuration", () => { configManager.set("temperature", 0.9); expect(configManager.get("temperature")).toBe(0.9); configManager.reloadConfig(); expect(configManager.get("temperature")).toBe(DEFAULT_CONFIG.temperature); }); }); describe("Mode-specific Configuration", () => { beforeEach(() => { configManager = new ConfigManager(); }); it("should provide intuitive mode configuration", () => { const mode_config = configManager.getModeConfig(ProcessingMode.INTUITIVE); expect(mode_config.system2_activation_threshold).toBe(0.8); // Higher threshold expect(mode_config.temperature).toBeGreaterThan( DEFAULT_CONFIG.temperature ); expect(mode_config.max_reasoning_depth).toBeLessThan( DEFAULT_CONFIG.max_reasoning_depth ); }); it("should provide deliberative mode configuration", () => { const mode_config = configManager.getModeConfig( ProcessingMode.DELIBERATIVE ); expect(mode_config.system2_activation_threshold).toBe(0.2); // Lower threshold expect(mode_config.temperature).toBeLessThan(DEFAULT_CONFIG.temperature); expect(mode_config.max_reasoning_depth).toBeGreaterThan( DEFAULT_CONFIG.max_reasoning_depth ); }); it("should provide creative mode configuration", () => { const mode_config = configManager.getModeConfig(ProcessingMode.CREATIVE); expect(mode_config.temperature).toBeGreaterThan( DEFAULT_CONFIG.temperature ); expect(mode_config.noise_level).toBeGreaterThan( DEFAULT_CONFIG.noise_level ); }); it("should provide analytical mode configuration", () => { const fresh_config_manager = new ConfigManager(); const base_config = fresh_config_manager.getConfig(); const mode_config = fresh_config_manager.getModeConfig( ProcessingMode.ANALYTICAL ); expect(mode_config.temperature).toBeLessThan(base_config.temperature); expect(mode_config.noise_level).toBeLessThan(base_config.noise_level); expect(mode_config.system2_activation_threshold).toBe(0.3); }); it("should return base config for balanced mode", () => { const fresh_config_manager = new ConfigManager(); const base_config = fresh_config_manager.getConfig(); const mode_config = fresh_config_manager.getModeConfig( ProcessingMode.BALANCED ); expect(mode_config.temperature).toBe(base_config.temperature); expect(mode_config.noise_level).toBe(base_config.noise_level); }); }); describe("Configuration Import/Export", () => { beforeEach(() => { configManager = new ConfigManager(); }); it("should export configuration to JSON", () => { const exported = configManager.exportConfig(); const parsed = JSON.parse(exported); expect(parsed.temperature).toBe(DEFAULT_CONFIG.temperature); expect(parsed.enable_emotion).toBe(DEFAULT_CONFIG.enable_emotion); expect(parsed.working_memory_capacity).toBe( DEFAULT_CONFIG.working_memory_capacity ); }); it("should import configuration from JSON", () => { const import_config = { temperature: 0.6, enable_emotion: false, max_reasoning_depth: 12, }; configManager.importConfig(JSON.stringify(import_config)); const config = configManager.getConfig(); expect(config.temperature).toBe(0.6); expect(config.enable_emotion).toBe(false); expect(config.max_reasoning_depth).toBe(12); }); it("should handle invalid JSON import", () => { expect(() => { configManager.importConfig("invalid json"); }).toThrow("Failed to import configuration"); }); }); describe("Configuration Presets", () => { beforeEach(() => { configManager = new ConfigManager(); }); it("should create configuration presets", () => { const preset_config = { temperature: 0.5, enable_emotion: false, }; // Should not throw expect(() => { configManager.createPreset("test-preset", preset_config); }).not.toThrow(); }); }); describe("Edge Cases", () => { it("should handle empty configuration updates", () => { configManager = new ConfigManager(); expect(() => { configManager.updateConfig({}); }).not.toThrow(); const config = configManager.getConfig(); expect(config.temperature).toBe(DEFAULT_CONFIG.temperature); }); it("should handle null and undefined values gracefully", () => { configManager = new ConfigManager(); // These should not cause issues configManager.addConfigFilePath(""); expect(() => { configManager.reloadConfig(); }).not.toThrow(); }); it("should handle configuration with extra properties", () => { const config_with_extra = { temperature: 0.8, extra_property: "should be ignored", another_extra: 123, }; configManager = new ConfigManager(config_with_extra as any); const config = configManager.getConfig(); expect(config.temperature).toBe(0.8); // TypeScript allows extra properties, so we just check the valid ones are set expect(config.working_memory_capacity).toBe( DEFAULT_CONFIG.working_memory_capacity ); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/keyurgolani/ThoughtMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server