From 7c2b17540b8e06942093771a2ba445a030f8a628 Mon Sep 17 00:00:00 2001
From: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Date: Fri, 24 Jan 2025 12:51:14 -0300
Subject: [PATCH] assistant2: Adjust empty state when there is no provider
(#23609)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This PR add a "Configure a Provider" button if the user gets to the
assistant panel with no provider configured. Then, upon configuring it,
they'll see a similar welcome message.
| No provider | Empty state |
|--------|--------|
|
|
|
Release Notes:
- N/A
---
crates/assistant2/src/assistant_panel.rs | 74 ++++++++++++++++++-
.../src/context_editor.rs | 2 +-
2 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/crates/assistant2/src/assistant_panel.rs b/crates/assistant2/src/assistant_panel.rs
index f9e08fa738774fd49ae2f3bb29281450f3baa6c7..ee5ae4c57520cdd8405c23f7e3a485b55089b506 100644
--- a/crates/assistant2/src/assistant_panel.rs
+++ b/crates/assistant2/src/assistant_panel.rs
@@ -3,8 +3,8 @@ use std::sync::Arc;
use anyhow::{anyhow, Result};
use assistant_context_editor::{
- make_lsp_adapter_delegate, AssistantPanelDelegate, ContextEditor, ContextHistory,
- SlashCommandCompletionProvider,
+ make_lsp_adapter_delegate, AssistantPanelDelegate, ConfigurationError, ContextEditor,
+ ContextHistory, SlashCommandCompletionProvider,
};
use assistant_settings::{AssistantDockPosition, AssistantSettings};
use assistant_slash_command::SlashCommandWorkingSet;
@@ -662,11 +662,35 @@ impl AssistantPanel {
self.thread.clone().into_any()
}
+ fn configuration_error(&self, cx: &AppContext) -> Option {
+ let provider = LanguageModelRegistry::read_global(cx).active_provider();
+ let is_authenticated = provider
+ .as_ref()
+ .map_or(false, |provider| provider.is_authenticated(cx));
+
+ if provider.is_some() && is_authenticated {
+ return None;
+ }
+
+ if !is_authenticated {
+ return Some(ConfigurationError::ProviderNotAuthenticated);
+ }
+
+ None
+ }
+
fn render_thread_empty_state(&self, cx: &mut ViewContext) -> impl IntoElement {
let recent_threads = self
.thread_store
.update(cx, |this, _cx| this.recent_threads(3));
+ let create_welcome_heading = || {
+ h_flex()
+ .w_full()
+ .justify_center()
+ .child(Headline::new("Welcome to the Assistant Panel").size(HeadlineSize::Small))
+ };
+
v_flex()
.gap_2()
.child(
@@ -680,6 +704,52 @@ impl AssistantPanel {
.mb_4(),
),
)
+ .when(
+ matches!(
+ self.configuration_error(cx),
+ Some(ConfigurationError::ProviderNotAuthenticated)
+ ),
+ |parent| {
+ parent.child(
+ v_flex()
+ .gap_0p5()
+ .child(create_welcome_heading())
+ .child(
+ h_flex().mb_2().w_full().justify_center().child(
+ Label::new(
+ "To start using the assistant, configure at least one LLM provider.",
+ )
+ .color(Color::Muted),
+ ),
+ )
+ .child(
+ h_flex().w_full().justify_center().child(
+ Button::new("open-configuration", "Configure a Provider")
+ .size(ButtonSize::Compact)
+ .icon(Some(IconName::Sliders))
+ .icon_size(IconSize::Small)
+ .icon_position(IconPosition::Start)
+ .on_click(cx.listener(|this, _, cx| {
+ this.open_configuration(cx);
+ })),
+ ),
+ ),
+ )
+ },
+ )
+ .when(
+ recent_threads.is_empty() && self.configuration_error(cx).is_none(),
+ |parent| {
+ parent.child(
+ v_flex().gap_0p5().child(create_welcome_heading()).child(
+ h_flex().w_full().justify_center().child(
+ Label::new("Start typing to chat with your codebase")
+ .color(Color::Muted),
+ ),
+ ),
+ )
+ },
+ )
.when(!recent_threads.is_empty(), |parent| {
parent
.child(
diff --git a/crates/assistant_context_editor/src/context_editor.rs b/crates/assistant_context_editor/src/context_editor.rs
index e73ac2a46ddc9f813263d1cb96a27e909f39e12e..dfe9c6fc74447a7b6f1e01da02c1393bbe6ac51f 100644
--- a/crates/assistant_context_editor/src/context_editor.rs
+++ b/crates/assistant_context_editor/src/context_editor.rs
@@ -3499,7 +3499,7 @@ fn size_for_image(data: &RenderImage, max_size: Size) -> Size {
}
}
-enum ConfigurationError {
+pub enum ConfigurationError {
NoProvider,
ProviderNotAuthenticated,
}