diff --git a/crates/chat-cli/src/cli/chat/conversation_state.rs b/crates/chat-cli/src/cli/chat/conversation_state.rs index 6238114adb..b6b9c8414d 100644 --- a/crates/chat-cli/src/cli/chat/conversation_state.rs +++ b/crates/chat-cli/src/cli/chat/conversation_state.rs @@ -1049,12 +1049,13 @@ mod tests { #[tokio::test] async fn test_conversation_state_history_handling_truncation() { let mut database = Database::new().await.unwrap(); + let mut output = SharedWriter::null(); let mut tool_manager = ToolManager::default(); let mut conversation_state = ConversationState::new( Context::new(), "fake_conv_id", - tool_manager.load_tools(&database).await.unwrap(), + tool_manager.load_tools(&database, &mut output).await.unwrap(), None, None, tool_manager, @@ -1076,10 +1077,11 @@ mod tests { #[tokio::test] async fn test_conversation_state_history_handling_with_tool_results() { let mut database = Database::new().await.unwrap(); + let mut output = SharedWriter::null(); // Build a long conversation history of tool use results. let mut tool_manager = ToolManager::default(); - let tool_config = tool_manager.load_tools(&database).await.unwrap(); + let tool_config = tool_manager.load_tools(&database, &mut output).await.unwrap(); let mut conversation_state = ConversationState::new( Context::new(), "fake_conv_id", @@ -1150,6 +1152,7 @@ mod tests { #[tokio::test] async fn test_conversation_state_with_context_files() { let mut database = Database::new().await.unwrap(); + let mut output = SharedWriter::null(); let ctx = Context::builder().with_test_home().await.unwrap().build_fake(); ctx.fs().write(AMAZONQ_FILENAME, "test context").await.unwrap(); @@ -1158,7 +1161,7 @@ mod tests { let mut conversation_state = ConversationState::new( ctx, "fake_conv_id", - tool_manager.load_tools(&database).await.unwrap(), + tool_manager.load_tools(&database, &mut output).await.unwrap(), None, None, tool_manager, @@ -1199,6 +1202,7 @@ mod tests { // tracing_subscriber::fmt::try_init().ok(); let mut database = Database::new().await.unwrap(); + let mut output = SharedWriter::null(); let mut tool_manager = ToolManager::default(); let ctx = Context::builder().with_test_home().await.unwrap().build_fake(); @@ -1227,7 +1231,7 @@ mod tests { let mut conversation_state = ConversationState::new( ctx, "fake_conv_id", - tool_manager.load_tools(&database).await.unwrap(), + tool_manager.load_tools(&database, &mut output).await.unwrap(), None, Some(SharedWriter::stdout()), tool_manager, diff --git a/crates/chat-cli/src/cli/chat/mod.rs b/crates/chat-cli/src/cli/chat/mod.rs index c4378c4ff3..d70e3261a9 100644 --- a/crates/chat-cli/src/cli/chat/mod.rs +++ b/crates/chat-cli/src/cli/chat/mod.rs @@ -411,7 +411,7 @@ pub async fn chat( .interactive(interactive) .build(telemetry, tool_manager_output) .await?; - let tool_config = tool_manager.load_tools(database).await?; + let tool_config = tool_manager.load_tools(database, &mut output).await?; let mut tool_permissions = ToolPermissions::new(tool_config.len()); if accept_all || trust_all_tools { tool_permissions.trust_all = true; diff --git a/crates/chat-cli/src/cli/chat/tool_manager.rs b/crates/chat-cli/src/cli/chat/tool_manager.rs index 12c92d203c..dee5d6c96c 100644 --- a/crates/chat-cli/src/cli/chat/tool_manager.rs +++ b/crates/chat-cli/src/cli/chat/tool_manager.rs @@ -52,6 +52,7 @@ use tracing::{ warn, }; +use super::util::shared_writer::SharedWriter; use crate::api_client::model::{ ToolResult, ToolResultContentBlock, @@ -723,7 +724,11 @@ impl Clone for ToolManager { } impl ToolManager { - pub async fn load_tools(&mut self, database: &Database) -> eyre::Result> { + pub async fn load_tools( + &mut self, + database: &Database, + output: &mut SharedWriter, + ) -> eyre::Result> { let tx = self.loading_status_sender.take(); let display_task = self.loading_display_task.take(); self.schema = { @@ -771,7 +776,21 @@ impl ToolManager { .map_or(5000_u64, |s| s as u64); Box::pin(tokio::time::sleep(std::time::Duration::from_millis(init_timeout))) } else { - Box::pin(future::pending()) + // if it is non-interactive we will want to use the "mcp.noInteractiveTimeout" + let init_timeout = database + .settings + .get_int(Setting::McpNoInteractiveTimeout) + .map_or(30_000_u64, |s| s as u64); + Box::pin(async move { + tokio::time::sleep(std::time::Duration::from_millis(init_timeout)).await; + let _ = queue!( + output, + style::Print( + "Not all mcp servers loaded. Configure no-interactive timeout with q settings mcp.noInteractiveTimeout" + ), + style::Print("\n") + ); + }) }; tokio::select! { _ = display_fut => {}, diff --git a/crates/chat-cli/src/database/settings.rs b/crates/chat-cli/src/database/settings.rs index 1830bc74e1..bac2e06bbf 100644 --- a/crates/chat-cli/src/database/settings.rs +++ b/crates/chat-cli/src/database/settings.rs @@ -29,6 +29,7 @@ pub enum Setting { ApiCodeWhispererService, ApiQService, McpInitTimeout, + McpNoInteractiveTimeout, McpLoadedBefore, } @@ -47,6 +48,7 @@ impl AsRef for Setting { Self::ApiCodeWhispererService => "api.codewhisperer.service", Self::ApiQService => "api.q.service", Self::McpInitTimeout => "mcp.initTimeout", + Self::McpNoInteractiveTimeout => "mcp.noInteractiveTimeout", Self::McpLoadedBefore => "mcp.loadedBefore", } } @@ -75,6 +77,7 @@ impl TryFrom<&str> for Setting { "api.codewhisperer.service" => Ok(Self::ApiCodeWhispererService), "api.q.service" => Ok(Self::ApiQService), "mcp.initTimeout" => Ok(Self::McpInitTimeout), + "mcp.noInteractiveTimeout" => Ok(Self::McpNoInteractiveTimeout), "mcp.loadedBefore" => Ok(Self::McpLoadedBefore), _ => Err(DatabaseError::InvalidSetting(value.to_string())), }