From 202d6ff2887264f245a00ecdd235a37409c8e983 Mon Sep 17 00:00:00 2001 From: kev1n77 Date: Tue, 26 May 2026 16:22:55 +0800 Subject: [PATCH] fix(cli): increase thread stack to 16 MiB to prevent stack overflow on Windows --- src/apps/cli/src/main.rs | 28 ++++++++++- src/crates/core/src/service/config/manager.rs | 23 ++++++---- .../core/src/service/config/providers.rs | 46 +------------------ 3 files changed, 41 insertions(+), 56 deletions(-) diff --git a/src/apps/cli/src/main.rs b/src/apps/cli/src/main.rs index 098833d2c..f4404139b 100644 --- a/src/apps/cli/src/main.rs +++ b/src/apps/cli/src/main.rs @@ -525,8 +525,7 @@ async fn run_interactive( // ======================== Main ======================== -#[tokio::main] -async fn main() -> Result<()> { +async fn run_cli() -> Result<()> { let cli = Cli::parse(); let is_tui_mode = matches!(cli.command, None | Some(Commands::Chat { .. })); @@ -766,3 +765,28 @@ async fn run_interactive_with_session(config: CliConfig, session_id: String) -> Ok(()) } +fn main() { + let worker = std::thread::Builder::new() + .stack_size(16 * 1024 * 1024) + .spawn(|| { + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("failed to build tokio runtime"); + runtime.block_on(run_cli()) + }) + .expect("failed to spawn bitfun-cli worker thread"); + + match worker.join() { + Ok(Ok(())) => {} + Ok(Err(err)) => { + eprintln!("Error: {err}"); + std::process::exit(1); + } + Err(_) => { + eprintln!("Error: bitfun-cli worker thread panicked"); + std::process::exit(1); + } + } +} + diff --git a/src/crates/core/src/service/config/manager.rs b/src/crates/core/src/service/config/manager.rs index 7575f2784..c18984736 100644 --- a/src/crates/core/src/service/config/manager.rs +++ b/src/crates/core/src/service/config/manager.rs @@ -92,21 +92,26 @@ impl ConfigManager { /// Loads or creates the configuration file. async fn load_or_create_config(&mut self) -> BitFunResult<()> { if self.config_file.exists() { - self.load_and_migrate_config().await?; + self.load_existing_config().await?; } else { - self.config = self.providers.get_default_config(); - Self::add_default_agent_models_config(&mut self.config.ai.agent_models); - Self::add_default_func_agent_models_config(&mut self.config.ai.func_agent_models); - self.config.version = env!("CARGO_PKG_VERSION").to_string(); - self.save_config().await?; - debug!("Created default config file"); + self.create_default_config().await?; } Ok(()) } - /// Loads and migrates configuration. - async fn load_and_migrate_config(&mut self) -> BitFunResult<()> { + /// Creates the first config file using the already initialized defaults. + async fn create_default_config(&mut self) -> BitFunResult<()> { + Self::add_default_agent_models_config(&mut self.config.ai.agent_models); + Self::add_default_func_agent_models_config(&mut self.config.ai.func_agent_models); + self.config.version = env!("CARGO_PKG_VERSION").to_string(); + self.save_config().await?; + debug!("Created default config file"); + Ok(()) + } + + /// Loads an existing config file and migrates it if needed. + async fn load_existing_config(&mut self) -> BitFunResult<()> { let content = fs::read_to_string(&self.config_file) .await .map_err(|e| BitFunError::config(format!("Failed to read config file: {}", e)))?; diff --git a/src/crates/core/src/service/config/providers.rs b/src/crates/core/src/service/config/providers.rs index e2b8ab941..33037592d 100644 --- a/src/crates/core/src/service/config/providers.rs +++ b/src/crates/core/src/service/config/providers.rs @@ -570,51 +570,7 @@ impl ConfigProviderRegistry { /// Builds the default configuration. pub fn get_default_config(&self) -> GlobalConfig { - let mut config = GlobalConfig::default(); - - if let Some(provider) = self.get_provider("app") { - if let Ok(app_config) = serde_json::from_value(provider.get_default_config()) { - config.app = app_config; - } - } - - if let Some(provider) = self.get_provider("theme") { - if let Ok(theme_config) = serde_json::from_value(provider.get_default_config()) { - config.theme = theme_config; - } - } - - if let Some(provider) = self.get_provider("themes") { - if let Ok(themes_config) = serde_json::from_value(provider.get_default_config()) { - config.themes = Some(themes_config); - } - } - - if let Some(provider) = self.get_provider("editor") { - if let Ok(editor_config) = serde_json::from_value(provider.get_default_config()) { - config.editor = editor_config; - } - } - - if let Some(provider) = self.get_provider("terminal") { - if let Ok(terminal_config) = serde_json::from_value(provider.get_default_config()) { - config.terminal = terminal_config; - } - } - - if let Some(provider) = self.get_provider("workspace") { - if let Ok(workspace_config) = serde_json::from_value(provider.get_default_config()) { - config.workspace = workspace_config; - } - } - - if let Some(provider) = self.get_provider("ai") { - if let Ok(ai_config) = serde_json::from_value(provider.get_default_config()) { - config.ai = ai_config; - } - } - - config + GlobalConfig::default() } /// Validates the full configuration.