Break ground on assistant2 (#21109)

This PR breaks ground on a new `assistant2` crate.

In order to see this new version of the assistant, both of the following
must be true:
1. The `assistant2` feature flag is enabled for your user
   - It is **not** currently enabled for all staff.
2. You are running a development build of Zed

The intent here is to enable the folks working on `assistant2` to
incrementally land work onto `main` without breaking use of the current
Assistant for anyone.

<img width="1136" alt="Screenshot 2024-11-23 at 10 46 08 AM"
src="https://github.com/user-attachments/assets/5723a13f-5be1-4486-9460-ead7329ba78e">

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-11-23 11:24:52 -05:00 committed by GitHub
parent f30de4852a
commit 9adc3b4e82
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 243 additions and 5 deletions

View file

@ -0,0 +1,22 @@
[package]
name = "assistant2"
version = "0.1.0"
edition = "2021"
publish = false
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/assistant.rs"
doctest = false
[dependencies]
anyhow.workspace = true
command_palette_hooks.workspace = true
feature_flags.workspace = true
gpui.workspace = true
proto.workspace = true
ui.workspace = true
workspace.workspace = true

View file

@ -0,0 +1 @@
../../LICENSE-GPL

View file

@ -0,0 +1,40 @@
mod assistant_panel;
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::{Assistant2FeatureFlag, FeatureFlagAppExt};
use gpui::{actions, AppContext};
pub use crate::assistant_panel::AssistantPanel;
actions!(assistant2, [ToggleFocus, NewChat]);
const NAMESPACE: &str = "assistant2";
/// Initializes the `assistant2` crate.
pub fn init(cx: &mut AppContext) {
assistant_panel::init(cx);
feature_gate_assistant2_actions(cx);
}
fn feature_gate_assistant2_actions(cx: &mut AppContext) {
const ASSISTANT1_NAMESPACE: &str = "assistant";
CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.hide_namespace(NAMESPACE);
});
cx.observe_flag::<Assistant2FeatureFlag, _>(move |is_enabled, cx| {
if is_enabled {
CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.show_namespace(NAMESPACE);
filter.hide_namespace(ASSISTANT1_NAMESPACE);
});
} else {
CommandPaletteFilter::update_global(cx, |filter, _cx| {
filter.hide_namespace(NAMESPACE);
filter.show_namespace(ASSISTANT1_NAMESPACE);
});
}
})
.detach();
}

View file

@ -0,0 +1,123 @@
use anyhow::Result;
use gpui::{
prelude::*, px, Action, AppContext, AsyncWindowContext, EventEmitter, FocusHandle,
FocusableView, Pixels, Task, View, ViewContext, WeakView, WindowContext,
};
use ui::prelude::*;
use workspace::dock::{DockPosition, Panel, PanelEvent};
use workspace::{Pane, Workspace};
use crate::{NewChat, ToggleFocus};
pub fn init(cx: &mut AppContext) {
cx.observe_new_views(
|workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
workspace.register_action(|workspace, _: &ToggleFocus, cx| {
workspace.toggle_panel_focus::<AssistantPanel>(cx);
});
},
)
.detach();
}
pub struct AssistantPanel {
pane: View<Pane>,
}
impl AssistantPanel {
pub fn load(
workspace: WeakView<Workspace>,
cx: AsyncWindowContext,
) -> Task<Result<View<Self>>> {
cx.spawn(|mut cx| async move {
workspace.update(&mut cx, |workspace, cx| {
cx.new_view(|cx| Self::new(workspace, cx))
})
})
}
fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
let pane = cx.new_view(|cx| {
let mut pane = Pane::new(
workspace.weak_handle(),
workspace.project().clone(),
Default::default(),
None,
NewChat.boxed_clone(),
cx,
);
pane.set_can_split(false, cx);
pane.set_can_navigate(true, cx);
pane
});
Self { pane }
}
}
impl FocusableView for AssistantPanel {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.pane.focus_handle(cx)
}
}
impl EventEmitter<PanelEvent> for AssistantPanel {}
impl Panel for AssistantPanel {
fn persistent_name() -> &'static str {
"AssistantPanel2"
}
fn position(&self, _cx: &WindowContext) -> DockPosition {
DockPosition::Right
}
fn position_is_valid(&self, _: DockPosition) -> bool {
true
}
fn set_position(&mut self, _position: DockPosition, _cx: &mut ViewContext<Self>) {}
fn size(&self, _cx: &WindowContext) -> Pixels {
px(640.)
}
fn set_size(&mut self, _size: Option<Pixels>, _cx: &mut ViewContext<Self>) {}
fn is_zoomed(&self, cx: &WindowContext) -> bool {
self.pane.read(cx).is_zoomed()
}
fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext<Self>) {
self.pane.update(cx, |pane, cx| pane.set_zoomed(zoomed, cx));
}
fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {}
fn pane(&self) -> Option<View<Pane>> {
Some(self.pane.clone())
}
fn remote_id() -> Option<proto::PanelId> {
Some(proto::PanelId::AssistantPanel)
}
fn icon(&self, _cx: &WindowContext) -> Option<IconName> {
Some(IconName::ZedAssistant)
}
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
Some("Assistant Panel")
}
fn toggle_action(&self) -> Box<dyn Action> {
Box::new(ToggleFocus)
}
}
impl Render for AssistantPanel {
fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
div().child(Label::new("Assistant II"))
}
}