assistant2: Ensure errors are also displayed in populated new thread view (#27869)
Follow-up to https://github.com/zed-industries/zed/pull/27812 This PR makes sure these errors cases also show up in the panel's empty state even when there is past data. | No ToS | Missing Provider | |--------|--------| |  |  | Release Notes: - N/A
This commit is contained in:
parent
92059803fb
commit
192097f58f
4 changed files with 243 additions and 143 deletions
|
@ -26,7 +26,9 @@ use prompt_library::{PromptLibrary, open_prompt_library};
|
|||
use prompt_store::PromptBuilder;
|
||||
use settings::{Settings, update_settings_file};
|
||||
use time::UtcOffset;
|
||||
use ui::{ContextMenu, KeyBinding, PopoverMenu, PopoverMenuHandle, Tab, Tooltip, prelude::*};
|
||||
use ui::{
|
||||
Banner, ContextMenu, KeyBinding, PopoverMenu, PopoverMenuHandle, Tab, Tooltip, prelude::*,
|
||||
};
|
||||
use util::ResultExt as _;
|
||||
use workspace::Workspace;
|
||||
use workspace::dock::{DockPosition, Panel, PanelEvent};
|
||||
|
@ -838,6 +840,7 @@ impl AssistantPanel {
|
|||
v_flex()
|
||||
.size_full()
|
||||
.when(recent_history.is_empty(), |this| {
|
||||
let configuration_error_ref = &configuration_error;
|
||||
this.child(
|
||||
v_flex()
|
||||
.size_full()
|
||||
|
@ -852,7 +855,8 @@ impl AssistantPanel {
|
|||
),
|
||||
)
|
||||
.when(no_error, |parent| {
|
||||
parent.child(
|
||||
parent
|
||||
.child(
|
||||
h_flex().child(
|
||||
Label::new("Ask and build anything.")
|
||||
.color(Color::Muted)
|
||||
|
@ -929,7 +933,7 @@ impl AssistantPanel {
|
|||
)
|
||||
})
|
||||
.map(|parent| {
|
||||
match configuration_error {
|
||||
match configuration_error_ref {
|
||||
Some(ConfigurationError::ProviderNotAuthenticated)
|
||||
| Some(ConfigurationError::NoProvider) => {
|
||||
parent
|
||||
|
@ -958,19 +962,23 @@ impl AssistantPanel {
|
|||
}),
|
||||
)
|
||||
}
|
||||
Some(ConfigurationError::ProviderPendingTermsAcceptance(provider)) => parent
|
||||
.children(
|
||||
Some(ConfigurationError::ProviderPendingTermsAcceptance(provider)) => {
|
||||
parent.children(
|
||||
provider.render_accept_terms(
|
||||
LanguageModelProviderTosView::ThreadEmptyState,
|
||||
LanguageModelProviderTosView::ThreadFreshStart,
|
||||
cx,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
None => parent,
|
||||
}
|
||||
})
|
||||
)
|
||||
})
|
||||
.when(!recent_history.is_empty(), |parent| {
|
||||
let focus_handle = focus_handle.clone();
|
||||
let configuration_error_ref = &configuration_error;
|
||||
|
||||
parent
|
||||
.p_1p5()
|
||||
.justify_end()
|
||||
|
@ -992,18 +1000,23 @@ impl AssistantPanel {
|
|||
Button::new("view-history", "View All")
|
||||
.style(ButtonStyle::Subtle)
|
||||
.label_size(LabelSize::Small)
|
||||
.key_binding(KeyBinding::for_action_in(
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&OpenHistory,
|
||||
&self.focus_handle(cx),
|
||||
window,
|
||||
cx,
|
||||
).map(|kb| kb.size(rems_from_px(12.))),)
|
||||
).map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.on_click(move |_event, window, cx| {
|
||||
window.dispatch_action(OpenHistory.boxed_clone(), cx);
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(v_flex().gap_1().children(
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.children(
|
||||
recent_history.into_iter().map(|entry| {
|
||||
// TODO: Add keyboard navigation.
|
||||
match entry {
|
||||
|
@ -1017,7 +1030,64 @@ impl AssistantPanel {
|
|||
}
|
||||
}
|
||||
}),
|
||||
))
|
||||
)
|
||||
)
|
||||
.map(|parent| {
|
||||
match configuration_error_ref {
|
||||
Some(ConfigurationError::ProviderNotAuthenticated)
|
||||
| Some(ConfigurationError::NoProvider) => {
|
||||
parent
|
||||
.child(
|
||||
Banner::new()
|
||||
.severity(ui::Severity::Warning)
|
||||
.children(
|
||||
Label::new(
|
||||
"Configure at least one LLM provider to start using the panel.",
|
||||
)
|
||||
.size(LabelSize::Small),
|
||||
)
|
||||
.action_slot(
|
||||
Button::new("settings", "Configure Provider")
|
||||
.style(ButtonStyle::Tinted(ui::TintColor::Warning))
|
||||
.label_size(LabelSize::Small)
|
||||
.key_binding(
|
||||
KeyBinding::for_action_in(
|
||||
&OpenConfiguration,
|
||||
&focus_handle,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
.map(|kb| kb.size(rems_from_px(12.))),
|
||||
)
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(
|
||||
OpenConfiguration.boxed_clone(),
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
}
|
||||
Some(ConfigurationError::ProviderPendingTermsAcceptance(provider)) => {
|
||||
parent
|
||||
.child(
|
||||
Banner::new()
|
||||
.severity(ui::Severity::Warning)
|
||||
.children(
|
||||
h_flex()
|
||||
.w_full()
|
||||
.children(
|
||||
provider.render_accept_terms(
|
||||
LanguageModelProviderTosView::ThreadtEmptyState,
|
||||
cx,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
None => parent,
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -353,7 +353,10 @@ pub trait LanguageModelProvider: 'static {
|
|||
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub enum LanguageModelProviderTosView {
|
||||
ThreadEmptyState,
|
||||
/// When there are some past interactions in the Agent Panel.
|
||||
ThreadtEmptyState,
|
||||
/// When there are no past interactions in the Agent Panel.
|
||||
ThreadFreshStart,
|
||||
PromptEditorPopup,
|
||||
Configuration,
|
||||
}
|
||||
|
|
|
@ -401,39 +401,30 @@ fn render_accept_terms(
|
|||
|
||||
let accept_terms_disabled = state.read(cx).accept_terms.is_some();
|
||||
|
||||
let thread_fresh_start = matches!(view_kind, LanguageModelProviderTosView::ThreadFreshStart);
|
||||
let thread_empty_state = matches!(view_kind, LanguageModelProviderTosView::ThreadtEmptyState);
|
||||
|
||||
let terms_button = Button::new("terms_of_service", "Terms of Service")
|
||||
.style(ButtonStyle::Subtle)
|
||||
.icon(IconName::ArrowUpRight)
|
||||
.icon_color(Color::Muted)
|
||||
.icon_size(IconSize::XSmall)
|
||||
.when(thread_empty_state, |this| this.label_size(LabelSize::Small))
|
||||
.on_click(move |_, _window, cx| cx.open_url("https://zed.dev/terms-of-service"));
|
||||
|
||||
let thread_view = match view_kind {
|
||||
LanguageModelProviderTosView::ThreadEmptyState => true,
|
||||
LanguageModelProviderTosView::PromptEditorPopup => false,
|
||||
LanguageModelProviderTosView::Configuration => false,
|
||||
};
|
||||
|
||||
let form = v_flex()
|
||||
.w_full()
|
||||
.gap_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.flex_wrap()
|
||||
.when(thread_view, |this| this.justify_center())
|
||||
.child(Label::new(
|
||||
"To start using Zed AI, please read and accept the",
|
||||
))
|
||||
.child(terms_button),
|
||||
)
|
||||
.child({
|
||||
let button_container = h_flex().w_full().child(
|
||||
let button_container = h_flex().child(
|
||||
Button::new("accept_terms", "I accept the Terms of Service")
|
||||
.when(!thread_empty_state, |this| {
|
||||
this.full_width()
|
||||
.style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.icon(IconName::Check)
|
||||
.icon_position(IconPosition::Start)
|
||||
.icon_size(IconSize::Small)
|
||||
.full_width()
|
||||
})
|
||||
.when(thread_empty_state, |this| {
|
||||
this.style(ButtonStyle::Tinted(TintColor::Warning))
|
||||
.label_size(LabelSize::Small)
|
||||
})
|
||||
.disabled(accept_terms_disabled)
|
||||
.on_click({
|
||||
let state = state.downgrade();
|
||||
|
@ -445,12 +436,48 @@ fn render_accept_terms(
|
|||
}),
|
||||
);
|
||||
|
||||
let form = if thread_empty_state {
|
||||
h_flex()
|
||||
.w_full()
|
||||
.flex_wrap()
|
||||
.justify_between()
|
||||
.child(
|
||||
h_flex()
|
||||
.child(
|
||||
Label::new("To start using Zed AI, please read and accept the")
|
||||
.size(LabelSize::Small),
|
||||
)
|
||||
.child(terms_button),
|
||||
)
|
||||
.child(button_container)
|
||||
} else {
|
||||
v_flex()
|
||||
.w_full()
|
||||
.gap_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.flex_wrap()
|
||||
.when(thread_fresh_start, |this| this.justify_center())
|
||||
.child(Label::new(
|
||||
"To start using Zed AI, please read and accept the",
|
||||
))
|
||||
.child(terms_button),
|
||||
)
|
||||
.child({
|
||||
match view_kind {
|
||||
LanguageModelProviderTosView::PromptEditorPopup => button_container.justify_end(),
|
||||
LanguageModelProviderTosView::Configuration => button_container.justify_start(),
|
||||
LanguageModelProviderTosView::ThreadEmptyState => button_container.justify_center(),
|
||||
LanguageModelProviderTosView::PromptEditorPopup => {
|
||||
button_container.w_full().justify_end()
|
||||
}
|
||||
});
|
||||
LanguageModelProviderTosView::Configuration => {
|
||||
button_container.w_full().justify_start()
|
||||
}
|
||||
LanguageModelProviderTosView::ThreadFreshStart => {
|
||||
button_container.w_full().justify_center()
|
||||
}
|
||||
LanguageModelProviderTosView::ThreadtEmptyState => div().w_0(),
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
Some(form.into_any())
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ impl RenderOnce for Banner {
|
|||
.child(content_area)
|
||||
.child(action_slot);
|
||||
} else {
|
||||
container = container.px_2().child(content_area);
|
||||
container = container.px_2().child(div().w_full().child(content_area));
|
||||
}
|
||||
|
||||
container
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue