#include "Config.h" #include #include #include #include using json = nlohmann::json; namespace secondvoice { Config& Config::getInstance() { static Config instance; return instance; } bool Config::load(const std::string& config_path, const std::string& env_path) { // Load .env file std::ifstream env_file(env_path); if (env_file.is_open()) { std::string line; while (std::getline(env_file, line)) { if (line.empty() || line[0] == '#') continue; auto pos = line.find('='); if (pos != std::string::npos) { std::string key = line.substr(0, pos); std::string value = line.substr(pos + 1); // Remove quotes if present if (!value.empty() && value.front() == '"' && value.back() == '"') { value = value.substr(1, value.length() - 2); } if (key == "OPENAI_API_KEY") { openai_key_ = value; } else if (key == "ANTHROPIC_API_KEY") { anthropic_key_ = value; } } } env_file.close(); } else { std::cerr << "Warning: Could not open .env file: " << env_path << std::endl; } // Load config.json std::cerr << "[Config] Opening config file: " << config_path << std::endl; std::ifstream config_file(config_path); if (!config_file.is_open()) { std::cerr << "Error: Could not open config file: " << config_path << std::endl; return false; } std::cerr << "[Config] File opened successfully" << std::endl; json config_json; try { std::cerr << "[Config] About to parse JSON..." << std::endl; config_file >> config_json; std::cerr << "[Config] JSON parsed successfully" << std::endl; } catch (const json::parse_error& e) { std::cerr << "Error parsing config.json: " << e.what() << std::endl; return false; } catch (...) { std::cerr << "Unknown error parsing config.json" << std::endl; return false; } // Parse audio config if (config_json.contains("audio")) { auto& audio = config_json["audio"]; audio_config_.sample_rate = audio.value("sample_rate", 16000); audio_config_.channels = audio.value("channels", 1); audio_config_.chunk_duration_seconds = audio.value("chunk_duration_seconds", 10); audio_config_.format = audio.value("format", "wav"); } // Parse whisper config if (config_json.contains("whisper")) { auto& whisper = config_json["whisper"]; whisper_config_.model = whisper.value("model", "whisper-1"); whisper_config_.language = whisper.value("language", "zh"); whisper_config_.temperature = whisper.value("temperature", 0.0f); whisper_config_.prompt = whisper.value("prompt", ""); whisper_config_.stream = whisper.value("stream", false); whisper_config_.response_format = whisper.value("response_format", "text"); } // Parse claude config if (config_json.contains("claude")) { auto& claude = config_json["claude"]; claude_config_.model = claude.value("model", "claude-haiku-4-20250514"); claude_config_.max_tokens = claude.value("max_tokens", 1024); claude_config_.temperature = claude.value("temperature", 0.3f); claude_config_.system_prompt = claude.value("system_prompt", ""); } // Parse UI config if (config_json.contains("ui")) { auto& ui = config_json["ui"]; ui_config_.window_width = ui.value("window_width", 800); ui_config_.window_height = ui.value("window_height", 600); ui_config_.font_size = ui.value("font_size", 16); ui_config_.max_display_lines = ui.value("max_display_lines", 50); } // Parse recording config if (config_json.contains("recording")) { auto& recording = config_json["recording"]; recording_config_.save_audio = recording.value("save_audio", true); recording_config_.output_directory = recording.value("output_directory", "./recordings"); } return true; } } // namespace secondvoice