From 95823872f75d9336f05eb80cdb3179255d4c237c Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Tue, 24 Mar 2026 11:00:41 -0400 Subject: [PATCH] Don't block thread creation when PromptStore fails to initialize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit NativeAgentServer::connect used prompt_store.await? which turned any PromptStore initialization failure (permission denied, disk issues, etc.) into a hard connection error, preventing all new native agent threads. Changed to .log_err() so the error is logged at ERROR level but thread creation proceeds with prompt_store: None. NativeAgent::new already accepts Option> and handles None gracefully — user custom prompts won't load but threads still work. Added a regression test that serializes a stale thread ID, loads the panel (triggering 'last active thread not found in database'), then verifies NewThread still produces a connected thread. --- crates/agent/src/native_agent_server.rs | 7 +++-- crates/agent_ui/src/agent_panel.rs | 38 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/crates/agent/src/native_agent_server.rs b/crates/agent/src/native_agent_server.rs index 7f19f9005e3ff54e361f57075b7af06508476564..661abb5070b14b71d944c0eb9333494472e39a52 100644 --- a/crates/agent/src/native_agent_server.rs +++ b/crates/agent/src/native_agent_server.rs @@ -10,6 +10,7 @@ use gpui::{App, Entity, Task}; use project::{AgentId, Project}; use prompt_store::PromptStore; use settings::{LanguageModelSelection, Settings as _, update_settings_file}; +use util::ResultExt as _; use crate::{NativeAgent, NativeAgentConnection, ThreadStore, templates::Templates}; @@ -47,11 +48,11 @@ impl AgentServer for NativeAgentServer { cx.spawn(async move |cx| { log::debug!("Creating templates for native agent"); let templates = Templates::new(); - let prompt_store = prompt_store.await?; + let prompt_store = prompt_store.await.log_err(); log::debug!("Creating native agent entity"); - let agent = cx - .update(|cx| NativeAgent::new(thread_store, templates, Some(prompt_store), fs, cx)); + let agent = + cx.update(|cx| NativeAgent::new(thread_store, templates, prompt_store, fs, cx)); // Create the connection wrapper let connection = NativeAgentConnection(agent); diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index a5ef231f8d5d5e9cfd85af6e6f2d9e02ddc8841d..33c5700170d75d249cea23c83c19b43f8ca8e355 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -6248,4 +6248,42 @@ mod tests { "the new worktree workspace should use the same agent (Codex) that was selected in the original panel", ); } + + /// Regression test: NewThread must produce a connected thread even when + /// the PromptStore fails to initialize (e.g. LMDB permission error). + /// Before the fix, `NativeAgentServer::connect` propagated the + /// PromptStore error with `?`, which put every new ConversationView + /// into LoadError and made it impossible to start any native-agent + /// thread. + #[gpui::test] + async fn test_new_thread_with_prompt_store_error(cx: &mut TestAppContext) { + let (panel, mut cx) = setup_panel(cx).await; + + // NativeAgentServer::connect needs a global Fs. + let fs = FakeFs::new(cx.executor()); + cx.update(|_, cx| { + ::set_global(fs.clone(), cx); + }); + cx.run_until_parked(); + + // Dispatch NewThread, which goes through the real NativeAgentServer + // path. In tests the PromptStore LMDB open fails with + // "Permission denied"; the fix (.log_err() instead of ?) lets + // the connection succeed anyway. + panel.update_in(&mut cx, |panel, window, cx| { + panel.new_thread(&NewThread, window, cx); + }); + cx.run_until_parked(); + + panel.read_with(&cx, |panel, cx| { + assert!( + panel.active_conversation_view().is_some(), + "panel should have a conversation view after NewThread" + ); + assert!( + panel.active_agent_thread(cx).is_some(), + "panel should have an active, connected agent thread" + ); + }); + } }