Don't block thread creation when PromptStore fails to initialize (#52333)

NativeAgentServer::connect used `prompt_store.await?` which turned any
PromptStore initialization failure (permission denied, disk issues,
etc.) into a hard connection error, putting the ConversationView into
LoadError state and preventing all new native agent threads from being
created.

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<Entity<PromptStore>>` 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 the "last active thread not found in database"
warning), then dispatches NewThread through the real NativeAgentServer
path and verifies it produces a connected thread.

Release Notes:

- Agent panel now handles filesystem errors more gracefully
This commit is contained in:
Richard Feldman 2026-04-24 08:32:28 -04:00 committed by GitHub
parent 03064b953f
commit 4a15e201ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 42 additions and 3 deletions

View file

@ -11,6 +11,7 @@ use language_model::{LanguageModelId, LanguageModelProviderId, LanguageModelRegi
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};
@ -48,11 +49,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);

View file

@ -7123,4 +7123,42 @@ mod tests {
);
});
}
/// 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| {
<dyn fs::Fs>::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"
);
});
}
}