Detailed changes
@@ -55,7 +55,7 @@ version = "0.1.0"
dependencies = [
"agent_settings",
"anyhow",
- "assistant_context_editor",
+ "assistant_context",
"assistant_tool",
"assistant_tools",
"chrono",
@@ -138,7 +138,7 @@ dependencies = [
"agent",
"agent_settings",
"anyhow",
- "assistant_context_editor",
+ "assistant_context",
"assistant_slash_command",
"assistant_slash_commands",
"assistant_tool",
@@ -169,6 +169,7 @@ dependencies = [
"jsonschema",
"language",
"language_model",
+ "languages",
"log",
"lsp",
"markdown",
@@ -203,7 +204,9 @@ dependencies = [
"theme",
"time",
"time_format",
+ "tree-sitter-md",
"ui",
+ "unindent",
"urlencoding",
"util",
"uuid",
@@ -557,7 +560,7 @@ dependencies = [
]
[[package]]
-name = "assistant_context_editor"
+name = "assistant_context"
version = "0.1.0"
dependencies = [
"agent_settings",
@@ -569,31 +572,23 @@ dependencies = [
"clock",
"collections",
"context_server",
- "editor",
- "feature_flags",
"fs",
"futures 0.3.31",
"fuzzy",
"gpui",
- "indexed_docs",
"indoc",
"language",
"language_model",
- "languages",
"log",
- "multi_buffer",
"open_ai",
- "ordered-float 2.10.1",
"parking_lot",
"paths",
- "picker",
"pretty_assertions",
"project",
"prompt_store",
"proto",
"rand 0.8.5",
"regex",
- "rope",
"rpc",
"serde",
"serde_json",
@@ -602,15 +597,12 @@ dependencies = [
"smol",
"telemetry_events",
"text",
- "theme",
- "tree-sitter-md",
"ui",
"unindent",
"util",
"uuid",
"workspace",
"workspace-hack",
- "zed_actions",
"zed_llm_client",
]
@@ -3031,7 +3023,7 @@ version = "0.44.0"
dependencies = [
"agent_settings",
"anyhow",
- "assistant_context_editor",
+ "assistant_context",
"assistant_slash_command",
"async-stripe",
"async-trait",
@@ -19924,7 +19916,6 @@ dependencies = [
"ashpd",
"askpass",
"assets",
- "assistant_context_editor",
"assistant_tool",
"assistant_tools",
"audio",
@@ -8,7 +8,7 @@ members = [
"crates/anthropic",
"crates/askpass",
"crates/assets",
- "crates/assistant_context_editor",
+ "crates/assistant_context",
"crates/assistant_slash_command",
"crates/assistant_slash_commands",
"crates/assistant_tool",
@@ -221,7 +221,7 @@ ai = { path = "crates/ai" }
anthropic = { path = "crates/anthropic" }
askpass = { path = "crates/askpass" }
assets = { path = "crates/assets" }
-assistant_context_editor = { path = "crates/assistant_context_editor" }
+assistant_context = { path = "crates/assistant_context" }
assistant_slash_command = { path = "crates/assistant_slash_command" }
assistant_slash_commands = { path = "crates/assistant_slash_commands" }
assistant_tool = { path = "crates/assistant_tool" }
@@ -21,7 +21,7 @@ test-support = [
[dependencies]
agent_settings.workspace = true
anyhow.workspace = true
-assistant_context_editor.workspace = true
+assistant_context.workspace = true
assistant_tool.workspace = true
chrono.workspace = true
client.workspace = true
@@ -1,5 +1,5 @@
use crate::thread::Thread;
-use assistant_context_editor::AssistantContext;
+use assistant_context::AssistantContext;
use assistant_tool::outline;
use collections::HashSet;
use futures::future;
@@ -8,7 +8,7 @@ use crate::{
thread_store::ThreadStore,
};
use anyhow::{Context as _, Result, anyhow};
-use assistant_context_editor::AssistantContext;
+use assistant_context::AssistantContext;
use collections::{HashSet, IndexSet};
use futures::{self, FutureExt};
use gpui::{App, Context, Entity, EventEmitter, Image, SharedString, Task, WeakEntity};
@@ -3,7 +3,7 @@ use crate::{
thread_store::{SerializedThreadMetadata, ThreadStore},
};
use anyhow::{Context as _, Result};
-use assistant_context_editor::SavedContextMetadata;
+use assistant_context::SavedContextMetadata;
use chrono::{DateTime, Utc};
use gpui::{App, AsyncApp, Entity, SharedString, Task, prelude::*};
use itertools::Itertools;
@@ -62,7 +62,7 @@ enum SerializedRecentOpen {
pub struct HistoryStore {
thread_store: Entity<ThreadStore>,
- context_store: Entity<assistant_context_editor::ContextStore>,
+ context_store: Entity<assistant_context::ContextStore>,
recently_opened_entries: VecDeque<HistoryEntryId>,
_subscriptions: Vec<gpui::Subscription>,
_save_recently_opened_entries_task: Task<()>,
@@ -71,7 +71,7 @@ pub struct HistoryStore {
impl HistoryStore {
pub fn new(
thread_store: Entity<ThreadStore>,
- context_store: Entity<assistant_context_editor::ContextStore>,
+ context_store: Entity<assistant_context::ContextStore>,
initial_recent_entries: impl IntoIterator<Item = HistoryEntryId>,
cx: &mut Context<Self>,
) -> Self {
@@ -96,7 +96,7 @@ impl SharedProjectContext {
}
}
-pub type TextThreadStore = assistant_context_editor::ContextStore;
+pub type TextThreadStore = assistant_context::ContextStore;
pub struct ThreadStore {
project: Entity<Project>,
@@ -22,7 +22,7 @@ test-support = [
agent.workspace = true
agent_settings.workspace = true
anyhow.workspace = true
-assistant_context_editor.workspace = true
+assistant_context.workspace = true
assistant_slash_command.workspace = true
assistant_slash_commands.workspace = true
assistant_tool.workspace = true
@@ -101,7 +101,10 @@ editor = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, "features" = ["test-support"] }
indoc.workspace = true
language = { workspace = true, "features" = ["test-support"] }
+languages = { workspace = true, features = ["test-support"] }
language_model = { workspace = true, "features" = ["test-support"] }
pretty_assertions.workspace = true
project = { workspace = true, features = ["test-support"] }
rand.workspace = true
+tree-sitter-md.workspace = true
+unindent.workspace = true
@@ -1,13 +1,14 @@
+use crate::{
+ ModelUsageContext,
+ language_model_selector::{
+ LanguageModelSelector, ToggleModelSelector, language_model_selector,
+ },
+};
use agent_settings::AgentSettings;
use fs::Fs;
use gpui::{Entity, FocusHandle, SharedString};
-use picker::popover_menu::PickerPopoverMenu;
-
-use crate::ModelUsageContext;
-use assistant_context_editor::language_model_selector::{
- LanguageModelSelector, ToggleModelSelector, language_model_selector,
-};
use language_model::{ConfiguredModel, LanguageModelRegistry};
+use picker::popover_menu::PickerPopoverMenu;
use settings::update_settings_file;
use std::sync::Arc;
use ui::{PopoverMenuHandle, Tooltip, prelude::*};
@@ -7,17 +7,35 @@ use std::time::Duration;
use db::kvp::{Dismissable, KEY_VALUE_STORE};
use serde::{Deserialize, Serialize};
+use crate::language_model_selector::ToggleModelSelector;
+use crate::{
+ AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode,
+ DeleteRecentlyOpenThread, ExpandMessageEditor, Follow, InlineAssistant, NewTextThread,
+ NewThread, OpenActiveThreadAsMarkdown, OpenAgentDiff, OpenHistory, ResetTrialEndUpsell,
+ ResetTrialUpsell, ToggleBurnMode, ToggleContextPicker, ToggleNavigationMenu, ToggleOptionsMenu,
+ active_thread::{self, ActiveThread, ActiveThreadEvent},
+ agent_configuration::{AgentConfiguration, AssistantConfigurationEvent},
+ agent_diff::AgentDiff,
+ message_editor::{MessageEditor, MessageEditorEvent},
+ slash_command::SlashCommandCompletionProvider,
+ text_thread_editor::{
+ AgentPanelDelegate, TextThreadEditor, humanize_token_count, make_lsp_adapter_delegate,
+ render_remaining_tokens,
+ },
+ thread_history::{HistoryEntryElement, ThreadHistory},
+ ui::AgentOnboardingModal,
+};
+use agent::{
+ Thread, ThreadError, ThreadEvent, ThreadId, ThreadSummary, TokenUsageRatio,
+ context_store::ContextStore,
+ history_store::{HistoryEntryId, HistoryStore},
+ thread_store::{TextThreadStore, ThreadStore},
+};
use agent_settings::{AgentDockPosition, AgentSettings, CompletionMode, DefaultView};
use anyhow::{Result, anyhow};
-use assistant_context_editor::{
- AgentPanelDelegate, AssistantContext, ContextEditor, ContextEvent, ContextSummary,
- SlashCommandCompletionProvider, humanize_token_count, make_lsp_adapter_delegate,
- render_remaining_tokens,
-};
+use assistant_context::{AssistantContext, ContextEvent, ContextSummary};
use assistant_slash_command::SlashCommandWorkingSet;
use assistant_tool::ToolWorkingSet;
-
-use assistant_context_editor::language_model_selector::ToggleModelSelector;
use client::{UserStore, zed_urls};
use editor::{Anchor, AnchorRangeExt as _, Editor, EditorEvent, MultiBuffer};
use fs::Fs;
@@ -56,25 +74,6 @@ use zed_actions::{
};
use zed_llm_client::{CompletionIntent, UsageLimit};
-use crate::{
- AddContextServer, AgentDiffPane, ContinueThread, ContinueWithBurnMode,
- DeleteRecentlyOpenThread, ExpandMessageEditor, Follow, InlineAssistant, NewTextThread,
- NewThread, OpenActiveThreadAsMarkdown, OpenAgentDiff, OpenHistory, ResetTrialEndUpsell,
- ResetTrialUpsell, ToggleBurnMode, ToggleContextPicker, ToggleNavigationMenu, ToggleOptionsMenu,
- active_thread::{self, ActiveThread, ActiveThreadEvent},
- agent_configuration::{AgentConfiguration, AssistantConfigurationEvent},
- agent_diff::AgentDiff,
- message_editor::{MessageEditor, MessageEditorEvent},
- thread_history::{HistoryEntryElement, ThreadHistory},
- ui::AgentOnboardingModal,
-};
-use agent::{
- Thread, ThreadError, ThreadEvent, ThreadId, ThreadSummary, TokenUsageRatio,
- context_store::ContextStore,
- history_store::{HistoryEntryId, HistoryStore},
- thread_store::{TextThreadStore, ThreadStore},
-};
-
const AGENT_PANEL_KEY: &str = "agent_panel";
#[derive(Serialize, Deserialize)]
@@ -179,7 +178,7 @@ enum ActiveView {
_subscriptions: Vec<gpui::Subscription>,
},
TextThread {
- context_editor: Entity<ContextEditor>,
+ context_editor: Entity<TextThreadEditor>,
title_editor: Entity<Editor>,
buffer_search_bar: Entity<BufferSearchBar>,
_subscriptions: Vec<gpui::Subscription>,
@@ -260,7 +259,7 @@ impl ActiveView {
}
pub fn prompt_editor(
- context_editor: Entity<ContextEditor>,
+ context_editor: Entity<TextThreadEditor>,
history_store: Entity<HistoryStore>,
language_registry: Arc<LanguageRegistry>,
window: &mut Window,
@@ -434,7 +433,7 @@ impl AgentPanel {
let context_store = workspace
.update(cx, |workspace, cx| {
let project = workspace.project().clone();
- assistant_context_editor::ContextStore::new(
+ assistant_context::ContextStore::new(
project,
prompt_builder.clone(),
slash_commands,
@@ -546,7 +545,7 @@ impl AgentPanel {
context_store.update(cx, |context_store, cx| context_store.create(cx));
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project.clone(), cx).unwrap();
let context_editor = cx.new(|cx| {
- let mut editor = ContextEditor::for_context(
+ let mut editor = TextThreadEditor::for_context(
context,
fs.clone(),
workspace.clone(),
@@ -841,7 +840,7 @@ impl AgentPanel {
.flatten();
let context_editor = cx.new(|cx| {
- let mut editor = ContextEditor::for_context(
+ let mut editor = TextThreadEditor::for_context(
context,
self.fs.clone(),
self.workspace.clone(),
@@ -933,7 +932,7 @@ impl AgentPanel {
.log_err()
.flatten();
let editor = cx.new(|cx| {
- ContextEditor::for_context(
+ TextThreadEditor::for_context(
context,
self.fs.clone(),
self.workspace.clone(),
@@ -1321,7 +1320,7 @@ impl AgentPanel {
});
}
- pub(crate) fn active_context_editor(&self) -> Option<Entity<ContextEditor>> {
+ pub(crate) fn active_context_editor(&self) -> Option<Entity<TextThreadEditor>> {
match &self.active_view {
ActiveView::TextThread { context_editor, .. } => Some(context_editor.clone()),
_ => None,
@@ -2899,7 +2898,7 @@ impl AgentPanel {
fn render_prompt_editor(
&self,
- context_editor: &Entity<ContextEditor>,
+ context_editor: &Entity<TextThreadEditor>,
buffer_search_bar: &Entity<BufferSearchBar>,
window: &mut Window,
cx: &mut Context<Self>,
@@ -3026,7 +3025,7 @@ impl AgentPanel {
}
ActiveView::TextThread { context_editor, .. } => {
context_editor.update(cx, |context_editor, cx| {
- ContextEditor::insert_dragged_files(
+ TextThreadEditor::insert_dragged_files(
context_editor,
paths,
added_worktrees,
@@ -3205,7 +3204,7 @@ impl AgentPanelDelegate for ConcreteAssistantPanelDelegate {
workspace: &mut Workspace,
_window: &mut Window,
cx: &mut Context<Workspace>,
- ) -> Option<Entity<ContextEditor>> {
+ ) -> Option<Entity<TextThreadEditor>> {
let panel = workspace.panel::<AgentPanel>(cx)?;
panel.read(cx).active_context_editor()
}
@@ -3229,10 +3228,10 @@ impl AgentPanelDelegate for ConcreteAssistantPanelDelegate {
fn open_remote_context(
&self,
_workspace: &mut Workspace,
- _context_id: assistant_context_editor::ContextId,
+ _context_id: assistant_context::ContextId,
_window: &mut Window,
_cx: &mut Context<Workspace>,
- ) -> Task<Result<Entity<ContextEditor>>> {
+ ) -> Task<Result<Entity<TextThreadEditor>>> {
Task::ready(Err(anyhow!("opening remote context not implemented")))
}
@@ -10,11 +10,16 @@ mod context_strip;
mod debug;
mod inline_assistant;
mod inline_prompt_editor;
+mod language_model_selector;
+mod max_mode_tooltip;
mod message_editor;
mod profile_selector;
+mod slash_command;
+mod slash_command_picker;
mod slash_command_settings;
mod terminal_codegen;
mod terminal_inline_assistant;
+mod text_thread_editor;
mod thread_history;
mod tool_compatibility;
mod ui;
@@ -43,6 +48,7 @@ pub use crate::agent_panel::{AgentPanel, ConcreteAssistantPanelDelegate};
pub use crate::inline_assistant::InlineAssistant;
use crate::slash_command_settings::SlashCommandSettings;
pub use agent_diff::{AgentDiffPane, AgentDiffToolbar};
+pub use text_thread_editor::AgentPanelDelegate;
pub use ui::preview::{all_agent_previews, get_agent_preview};
actions!(
@@ -140,7 +146,7 @@ pub fn init(
AgentSettings::register(cx);
SlashCommandSettings::register(cx);
- assistant_context_editor::init(client.clone(), cx);
+ assistant_context::init(client.clone(), cx);
rules_library::init(cx);
if !is_eval {
// Initializing the language model from the user settings messes with the eval, so we only initialize them when
@@ -73,7 +73,7 @@ fn search(
recent_entries: Vec<RecentEntry>,
prompt_store: Option<Entity<PromptStore>>,
thread_store: Option<WeakEntity<ThreadStore>>,
- text_thread_context_store: Option<WeakEntity<assistant_context_editor::ContextStore>>,
+ text_thread_context_store: Option<WeakEntity<assistant_context::ContextStore>>,
workspace: Entity<Workspace>,
cx: &mut App,
) -> Task<Vec<Match>> {
@@ -2,6 +2,7 @@ use crate::agent_model_selector::AgentModelSelector;
use crate::buffer_codegen::BufferCodegen;
use crate::context_picker::{ContextPicker, ContextPickerCompletionProvider};
use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
+use crate::language_model_selector::ToggleModelSelector;
use crate::message_editor::{ContextCreasesAddon, extract_message_creases, insert_message_creases};
use crate::terminal_codegen::TerminalCodegen;
use crate::{CycleNextInlineAssist, CyclePreviousInlineAssist, ModelUsageContext};
@@ -10,7 +11,6 @@ use agent::{
context_store::ContextStore,
thread_store::{TextThreadStore, ThreadStore},
};
-use assistant_context_editor::language_model_selector::ToggleModelSelector;
use client::ErrorExt;
use collections::VecDeque;
use db::kvp::Dismissable;
@@ -3,6 +3,7 @@ use std::rc::Rc;
use std::sync::Arc;
use crate::agent_model_selector::AgentModelSelector;
+use crate::language_model_selector::ToggleModelSelector;
use crate::tool_compatibility::{IncompatibleToolsState, IncompatibleToolsTooltip};
use crate::ui::{
MaxModeTooltip,
@@ -13,7 +14,6 @@ use agent::{
context_store::ContextStoreEvent,
};
use agent_settings::{AgentSettings, CompletionMode};
-use assistant_context_editor::language_model_selector::ToggleModelSelector;
use buffer_diff::BufferDiff;
use client::UserStore;
use collections::{HashMap, HashSet};
@@ -1,4 +1,4 @@
-use crate::context_editor::ContextEditor;
+use crate::text_thread_editor::TextThreadEditor;
use anyhow::Result;
pub use assistant_slash_command::SlashCommand;
use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};
@@ -21,14 +21,14 @@ use workspace::Workspace;
pub struct SlashCommandCompletionProvider {
cancel_flag: Mutex<Arc<AtomicBool>>,
slash_commands: Arc<SlashCommandWorkingSet>,
- editor: Option<WeakEntity<ContextEditor>>,
+ editor: Option<WeakEntity<TextThreadEditor>>,
workspace: Option<WeakEntity<Workspace>>,
}
impl SlashCommandCompletionProvider {
pub fn new(
slash_commands: Arc<SlashCommandWorkingSet>,
- editor: Option<WeakEntity<ContextEditor>>,
+ editor: Option<WeakEntity<TextThreadEditor>>,
workspace: Option<WeakEntity<Workspace>>,
) -> Self {
Self {
@@ -1,12 +1,10 @@
-use std::sync::Arc;
-
+use crate::text_thread_editor::TextThreadEditor;
use assistant_slash_command::SlashCommandWorkingSet;
use gpui::{AnyElement, AnyView, DismissEvent, SharedString, Task, WeakEntity};
use picker::{Picker, PickerDelegate, PickerEditorPosition};
+use std::sync::Arc;
use ui::{ListItem, ListItemSpacing, PopoverMenu, PopoverTrigger, Tooltip, prelude::*};
-use crate::context_editor::ContextEditor;
-
#[derive(IntoElement)]
pub(super) struct SlashCommandSelector<T, TT>
where
@@ -14,7 +12,7 @@ where
TT: Fn(&mut Window, &mut App) -> AnyView + 'static,
{
working_set: Arc<SlashCommandWorkingSet>,
- active_context_editor: WeakEntity<ContextEditor>,
+ active_context_editor: WeakEntity<TextThreadEditor>,
trigger: T,
tooltip: TT,
}
@@ -49,7 +47,7 @@ impl AsRef<str> for SlashCommandEntry {
pub(crate) struct SlashCommandDelegate {
all_commands: Vec<SlashCommandEntry>,
filtered_commands: Vec<SlashCommandEntry>,
- active_context_editor: WeakEntity<ContextEditor>,
+ active_context_editor: WeakEntity<TextThreadEditor>,
selected_index: usize,
}
@@ -60,7 +58,7 @@ where
{
pub(crate) fn new(
working_set: Arc<SlashCommandWorkingSet>,
- active_context_editor: WeakEntity<ContextEditor>,
+ active_context_editor: WeakEntity<TextThreadEditor>,
trigger: T,
tooltip: TT,
) -> Self {
@@ -76,14 +76,11 @@ use workspace::{
searchable::{SearchEvent, SearchableItem},
};
-use crate::{
+use crate::{slash_command::SlashCommandCompletionProvider, slash_command_picker};
+use assistant_context::{
AssistantContext, CacheStatus, Content, ContextEvent, ContextId, InvokedSlashCommandId,
InvokedSlashCommandStatus, Message, MessageId, MessageMetadata, MessageStatus,
- ParsedSlashCommand, PendingSlashCommandStatus,
-};
-use crate::{
- ThoughtProcessOutputSection, slash_command::SlashCommandCompletionProvider,
- slash_command_picker,
+ ParsedSlashCommand, PendingSlashCommandStatus, ThoughtProcessOutputSection,
};
actions!(
@@ -131,7 +128,7 @@ pub trait AgentPanelDelegate {
workspace: &mut Workspace,
window: &mut Window,
cx: &mut Context<Workspace>,
- ) -> Option<Entity<ContextEditor>>;
+ ) -> Option<Entity<TextThreadEditor>>;
fn open_saved_context(
&self,
@@ -147,7 +144,7 @@ pub trait AgentPanelDelegate {
context_id: ContextId,
window: &mut Window,
cx: &mut Context<Workspace>,
- ) -> Task<Result<Entity<ContextEditor>>>;
+ ) -> Task<Result<Entity<TextThreadEditor>>>;
fn quote_selection(
&self,
@@ -176,7 +173,7 @@ struct GlobalAssistantPanelDelegate(Arc<dyn AgentPanelDelegate>);
impl Global for GlobalAssistantPanelDelegate {}
-pub struct ContextEditor {
+pub struct TextThreadEditor {
context: Entity<AssistantContext>,
fs: Arc<dyn Fs>,
slash_commands: Arc<SlashCommandWorkingSet>,
@@ -206,10 +203,24 @@ pub struct ContextEditor {
language_model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
}
-pub const DEFAULT_TAB_TITLE: &str = "New Chat";
const MAX_TAB_TITLE_LEN: usize = 16;
-impl ContextEditor {
+impl TextThreadEditor {
+ pub fn init(cx: &mut App) {
+ workspace::FollowableViewRegistry::register::<TextThreadEditor>(cx);
+
+ cx.observe_new(
+ |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
+ workspace
+ .register_action(TextThreadEditor::quote_selection)
+ .register_action(TextThreadEditor::insert_selection)
+ .register_action(TextThreadEditor::copy_code)
+ .register_action(TextThreadEditor::handle_insert_dragged_files);
+ },
+ )
+ .detach();
+ }
+
pub fn for_context(
context: Entity<AssistantContext>,
fs: Arc<dyn Fs>,
@@ -1279,7 +1290,7 @@ impl ContextEditor {
/// Returns either the selected text, or the content of the Markdown code
/// block surrounding the cursor.
fn get_selection_or_code_block(
- context_editor_view: &Entity<ContextEditor>,
+ context_editor_view: &Entity<TextThreadEditor>,
cx: &mut Context<Workspace>,
) -> Option<(String, bool)> {
const CODE_FENCE_DELIMITER: &'static str = "```";
@@ -2029,7 +2040,7 @@ impl ContextEditor {
/// Whether or not we should allow messages to be sent.
/// Will return false if the selected provided has a configuration error or
/// if the user has not accepted the terms of service for this provider.
- fn sending_disabled(&self, cx: &mut Context<'_, ContextEditor>) -> bool {
+ fn sending_disabled(&self, cx: &mut Context<'_, TextThreadEditor>) -> bool {
let model_registry = LanguageModelRegistry::read_global(cx);
let Some(configuration_error) =
model_registry.configuration_error(model_registry.default_model(), cx)
@@ -2546,10 +2557,10 @@ struct SelectedCreaseMetadata {
crease: CreaseMetadata,
}
-impl EventEmitter<EditorEvent> for ContextEditor {}
-impl EventEmitter<SearchEvent> for ContextEditor {}
+impl EventEmitter<EditorEvent> for TextThreadEditor {}
+impl EventEmitter<SearchEvent> for TextThreadEditor {}
-impl Render for ContextEditor {
+impl Render for TextThreadEditor {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let provider = LanguageModelRegistry::read_global(cx)
.default_model()
@@ -2568,15 +2579,15 @@ impl Render for ContextEditor {
v_flex()
.key_context("ContextEditor")
- .capture_action(cx.listener(ContextEditor::cancel))
- .capture_action(cx.listener(ContextEditor::save))
- .capture_action(cx.listener(ContextEditor::copy))
- .capture_action(cx.listener(ContextEditor::cut))
- .capture_action(cx.listener(ContextEditor::paste))
- .capture_action(cx.listener(ContextEditor::cycle_message_role))
- .capture_action(cx.listener(ContextEditor::confirm_command))
- .on_action(cx.listener(ContextEditor::assist))
- .on_action(cx.listener(ContextEditor::split))
+ .capture_action(cx.listener(TextThreadEditor::cancel))
+ .capture_action(cx.listener(TextThreadEditor::save))
+ .capture_action(cx.listener(TextThreadEditor::copy))
+ .capture_action(cx.listener(TextThreadEditor::cut))
+ .capture_action(cx.listener(TextThreadEditor::paste))
+ .capture_action(cx.listener(TextThreadEditor::cycle_message_role))
+ .capture_action(cx.listener(TextThreadEditor::confirm_command))
+ .on_action(cx.listener(TextThreadEditor::assist))
+ .on_action(cx.listener(TextThreadEditor::split))
.on_action(move |_: &ToggleModelSelector, window, cx| {
language_model_selector.toggle(window, cx);
})
@@ -2631,13 +2642,13 @@ impl Render for ContextEditor {
}
}
-impl Focusable for ContextEditor {
+impl Focusable for TextThreadEditor {
fn focus_handle(&self, cx: &App) -> FocusHandle {
self.editor.focus_handle(cx)
}
}
-impl Item for ContextEditor {
+impl Item for TextThreadEditor {
type Event = editor::EditorEvent;
fn tab_content_text(&self, _detail: usize, cx: &App) -> SharedString {
@@ -2710,7 +2721,7 @@ impl Item for ContextEditor {
}
}
-impl SearchableItem for ContextEditor {
+impl SearchableItem for TextThreadEditor {
type Match = <Editor as SearchableItem>::Match;
fn clear_matches(&mut self, window: &mut Window, cx: &mut Context<Self>) {
@@ -2791,7 +2802,7 @@ impl SearchableItem for ContextEditor {
}
}
-impl FollowableItem for ContextEditor {
+impl FollowableItem for TextThreadEditor {
fn remote_id(&self) -> Option<workspace::ViewId> {
self.remote_id
}
@@ -2914,21 +2925,14 @@ impl FollowableItem for ContextEditor {
}
pub struct ContextEditorToolbarItem {
- active_context_editor: Option<WeakEntity<ContextEditor>>,
+ active_context_editor: Option<WeakEntity<TextThreadEditor>>,
model_summary_editor: Entity<Editor>,
}
-impl ContextEditorToolbarItem {
- pub fn new(model_summary_editor: Entity<Editor>) -> Self {
- Self {
- active_context_editor: None,
- model_summary_editor,
- }
- }
-}
+impl ContextEditorToolbarItem {}
pub fn render_remaining_tokens(
- context_editor: &Entity<ContextEditor>,
+ context_editor: &Entity<TextThreadEditor>,
cx: &App,
) -> Option<impl IntoElement + use<>> {
let context = &context_editor.read(cx).context;
@@ -3044,7 +3048,7 @@ impl ToolbarItemView for ContextEditorToolbarItem {
cx: &mut Context<Self>,
) -> ToolbarItemLocation {
self.active_context_editor = active_pane_item
- .and_then(|item| item.act_as::<ContextEditor>(cx))
+ .and_then(|item| item.act_as::<TextThreadEditor>(cx))
.map(|editor| editor.downgrade());
cx.notify();
if self.active_context_editor.is_none() {
@@ -3405,7 +3409,7 @@ mod tests {
cx: &mut TestAppContext,
) -> (
Entity<AssistantContext>,
- Entity<ContextEditor>,
+ Entity<TextThreadEditor>,
VisualTestContext,
) {
cx.update(init_test);
@@ -3421,7 +3425,7 @@ mod tests {
let context_editor = window
.update(&mut cx, |_, window, cx| {
cx.new(|cx| {
- let editor = ContextEditor::for_context(
+ let editor = TextThreadEditor::for_context(
context.clone(),
fs,
workspace.downgrade(),
@@ -3454,7 +3458,7 @@ mod tests {
}
fn assert_copy_paste_context_editor<T: editor::ToOffset>(
- context_editor: &Entity<ContextEditor>,
+ context_editor: &Entity<TextThreadEditor>,
range: Range<T>,
expected_text: &str,
cx: &mut VisualTestContext,
@@ -1,5 +1,5 @@
[package]
-name = "assistant_context_editor"
+name = "assistant_context"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
@@ -9,7 +9,7 @@ license = "GPL-3.0-or-later"
workspace = true
[lib]
-path = "src/assistant_context_editor.rs"
+path = "src/assistant_context.rs"
[dependencies]
agent_settings.workspace = true
@@ -21,27 +21,20 @@ client.workspace = true
clock.workspace = true
collections.workspace = true
context_server.workspace = true
-editor.workspace = true
-feature_flags.workspace = true
fs.workspace = true
futures.workspace = true
fuzzy.workspace = true
gpui.workspace = true
-indexed_docs.workspace = true
language.workspace = true
language_model.workspace = true
log.workspace = true
-multi_buffer.workspace = true
open_ai.workspace = true
-ordered-float.workspace = true
parking_lot.workspace = true
paths.workspace = true
-picker.workspace = true
project.workspace = true
prompt_store.workspace = true
proto.workspace = true
regex.workspace = true
-rope.workspace = true
rpc.workspace = true
serde.workspace = true
serde_json.workspace = true
@@ -50,21 +43,17 @@ smallvec.workspace = true
smol.workspace = true
telemetry_events.workspace = true
text.workspace = true
-theme.workspace = true
ui.workspace = true
util.workspace = true
uuid.workspace = true
workspace-hack.workspace = true
workspace.workspace = true
-zed_actions.workspace = true
zed_llm_client.workspace = true
[dev-dependencies]
indoc.workspace = true
language_model = { workspace = true, features = ["test-support"] }
-languages = { workspace = true, features = ["test-support"] }
pretty_assertions.workspace = true
rand.workspace = true
-tree-sitter-md.workspace = true
unindent.workspace = true
workspace = { workspace = true, features = ["test-support"] }
@@ -1,5 +1,6 @@
#[cfg(test)]
-mod context_tests;
+mod assistant_context_tests;
+mod context_store;
use agent_settings::AgentSettings;
use anyhow::{Context as _, Result, bail};
@@ -8,7 +9,7 @@ use assistant_slash_command::{
SlashCommandResult, SlashCommandWorkingSet,
};
use assistant_slash_commands::FileCommandMetadata;
-use client::{self, proto, telemetry::Telemetry};
+use client::{self, Client, proto, telemetry::Telemetry};
use clock::ReplicaId;
use collections::{HashMap, HashSet};
use fs::{Fs, RenameOptions};
@@ -47,6 +48,12 @@ use util::{ResultExt, TryFutureExt, post_inc};
use uuid::Uuid;
use zed_llm_client::CompletionIntent;
+pub use crate::context_store::*;
+
+pub fn init(client: Arc<Client>, _: &mut App) {
+ context_store::init(&client.into());
+}
+
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ContextId(String);
@@ -1,36 +0,0 @@
-mod context;
-mod context_editor;
-mod context_history;
-mod context_store;
-pub mod language_model_selector;
-mod max_mode_tooltip;
-mod slash_command;
-mod slash_command_picker;
-
-use std::sync::Arc;
-
-use client::Client;
-use gpui::{App, Context};
-use workspace::Workspace;
-
-pub use crate::context::*;
-pub use crate::context_editor::*;
-pub use crate::context_history::*;
-pub use crate::context_store::*;
-pub use crate::slash_command::*;
-
-pub fn init(client: Arc<Client>, cx: &mut App) {
- context_store::init(&client.into());
- workspace::FollowableViewRegistry::register::<ContextEditor>(cx);
-
- cx.observe_new(
- |workspace: &mut Workspace, _window, _cx: &mut Context<Workspace>| {
- workspace
- .register_action(ContextEditor::quote_selection)
- .register_action(ContextEditor::insert_selection)
- .register_action(ContextEditor::copy_code)
- .register_action(ContextEditor::handle_insert_dragged_files);
- },
- )
- .detach();
-}
@@ -1,271 +0,0 @@
-use std::sync::Arc;
-
-use gpui::{App, Entity, EventEmitter, FocusHandle, Focusable, Subscription, Task, WeakEntity};
-use picker::{Picker, PickerDelegate};
-use project::Project;
-use ui::utils::{DateTimeType, format_distance_from_now};
-use ui::{Avatar, ListItem, ListItemSpacing, prelude::*};
-use workspace::{Item, Workspace};
-
-use crate::{
- AgentPanelDelegate, ContextStore, DEFAULT_TAB_TITLE, RemoteContextMetadata,
- SavedContextMetadata,
-};
-
-#[derive(Clone)]
-pub enum ContextMetadata {
- Remote(RemoteContextMetadata),
- Saved(SavedContextMetadata),
-}
-
-enum SavedContextPickerEvent {
- Confirmed(ContextMetadata),
-}
-
-pub struct ContextHistory {
- picker: Entity<Picker<SavedContextPickerDelegate>>,
- _subscriptions: Vec<Subscription>,
- workspace: WeakEntity<Workspace>,
-}
-
-impl ContextHistory {
- pub fn new(
- project: Entity<Project>,
- context_store: Entity<ContextStore>,
- workspace: WeakEntity<Workspace>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> Self {
- let picker = cx.new(|cx| {
- Picker::uniform_list(
- SavedContextPickerDelegate::new(project, context_store.clone()),
- window,
- cx,
- )
- .modal(false)
- .max_height(None)
- });
-
- let subscriptions = vec![
- cx.observe_in(&context_store, window, |this, _, window, cx| {
- this.picker
- .update(cx, |picker, cx| picker.refresh(window, cx));
- }),
- cx.subscribe_in(&picker, window, Self::handle_picker_event),
- ];
-
- Self {
- picker,
- _subscriptions: subscriptions,
- workspace,
- }
- }
-
- fn handle_picker_event(
- &mut self,
- _: &Entity<Picker<SavedContextPickerDelegate>>,
- event: &SavedContextPickerEvent,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) {
- let SavedContextPickerEvent::Confirmed(context) = event;
-
- let Some(agent_panel_delegate) = <dyn AgentPanelDelegate>::try_global(cx) else {
- return;
- };
-
- self.workspace
- .update(cx, |workspace, cx| match context {
- ContextMetadata::Remote(metadata) => {
- agent_panel_delegate
- .open_remote_context(workspace, metadata.id.clone(), window, cx)
- .detach_and_log_err(cx);
- }
- ContextMetadata::Saved(metadata) => {
- agent_panel_delegate
- .open_saved_context(workspace, metadata.path.clone(), window, cx)
- .detach_and_log_err(cx);
- }
- })
- .ok();
- }
-}
-
-impl Render for ContextHistory {
- fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
- div().size_full().child(self.picker.clone())
- }
-}
-
-impl Focusable for ContextHistory {
- fn focus_handle(&self, cx: &App) -> FocusHandle {
- self.picker.focus_handle(cx)
- }
-}
-
-impl EventEmitter<()> for ContextHistory {}
-
-impl Item for ContextHistory {
- type Event = ();
-
- fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
- "History".into()
- }
-}
-
-struct SavedContextPickerDelegate {
- store: Entity<ContextStore>,
- project: Entity<Project>,
- matches: Vec<ContextMetadata>,
- selected_index: usize,
-}
-
-impl EventEmitter<SavedContextPickerEvent> for Picker<SavedContextPickerDelegate> {}
-
-impl SavedContextPickerDelegate {
- fn new(project: Entity<Project>, store: Entity<ContextStore>) -> Self {
- Self {
- project,
- store,
- matches: Vec::new(),
- selected_index: 0,
- }
- }
-}
-
-impl PickerDelegate for SavedContextPickerDelegate {
- type ListItem = ListItem;
-
- fn match_count(&self) -> usize {
- self.matches.len()
- }
-
- fn selected_index(&self) -> usize {
- self.selected_index
- }
-
- fn set_selected_index(
- &mut self,
- ix: usize,
- _window: &mut Window,
- _cx: &mut Context<Picker<Self>>,
- ) {
- self.selected_index = ix;
- }
-
- fn placeholder_text(&self, _window: &mut Window, _cx: &mut App) -> Arc<str> {
- "Search...".into()
- }
-
- fn update_matches(
- &mut self,
- query: String,
- _window: &mut Window,
- cx: &mut Context<Picker<Self>>,
- ) -> Task<()> {
- let search = self.store.read(cx).search(query, cx);
- cx.spawn(async move |this, cx| {
- let matches = search.await;
- this.update(cx, |this, cx| {
- let host_contexts = this.delegate.store.read(cx).host_contexts();
- this.delegate.matches = host_contexts
- .iter()
- .cloned()
- .map(ContextMetadata::Remote)
- .chain(matches.into_iter().map(ContextMetadata::Saved))
- .collect();
- this.delegate.selected_index = 0;
- cx.notify();
- })
- .ok();
- })
- }
-
- fn confirm(&mut self, _secondary: bool, _window: &mut Window, cx: &mut Context<Picker<Self>>) {
- if let Some(metadata) = self.matches.get(self.selected_index) {
- cx.emit(SavedContextPickerEvent::Confirmed(metadata.clone()));
- }
- }
-
- fn dismissed(&mut self, _window: &mut Window, _cx: &mut Context<Picker<Self>>) {}
-
- fn render_match(
- &self,
- ix: usize,
- selected: bool,
- _window: &mut Window,
- cx: &mut Context<Picker<Self>>,
- ) -> Option<Self::ListItem> {
- let context = self.matches.get(ix)?;
- let item = match context {
- ContextMetadata::Remote(context) => {
- let host_user = self.project.read(cx).host().and_then(|collaborator| {
- self.project
- .read(cx)
- .user_store()
- .read(cx)
- .get_cached_user(collaborator.user_id)
- });
- div()
- .flex()
- .w_full()
- .justify_between()
- .gap_2()
- .child(
- h_flex().flex_1().overflow_x_hidden().child(
- Label::new(context.summary.clone().unwrap_or(DEFAULT_TAB_TITLE.into()))
- .size(LabelSize::Small),
- ),
- )
- .child(
- h_flex()
- .gap_2()
- .children(if let Some(host_user) = host_user {
- vec![
- Avatar::new(host_user.avatar_uri.clone()).into_any_element(),
- Label::new(format!("Shared by @{}", host_user.github_login))
- .color(Color::Muted)
- .size(LabelSize::Small)
- .into_any_element(),
- ]
- } else {
- vec![
- Label::new("Shared by host")
- .color(Color::Muted)
- .size(LabelSize::Small)
- .into_any_element(),
- ]
- }),
- )
- }
- ContextMetadata::Saved(context) => div()
- .flex()
- .w_full()
- .justify_between()
- .gap_2()
- .child(
- h_flex()
- .flex_1()
- .child(Label::new(context.title.clone()).size(LabelSize::Small))
- .overflow_x_hidden(),
- )
- .child(
- Label::new(format_distance_from_now(
- DateTimeType::Local(context.mtime),
- false,
- true,
- true,
- ))
- .color(Color::Muted)
- .size(LabelSize::Small),
- ),
- };
- Some(
- ListItem::new(ix)
- .inset(true)
- .spacing(ListItemSpacing::Sparse)
- .toggle_state(selected)
- .child(item),
- )
- }
-}
@@ -78,7 +78,7 @@ zed_llm_client.workspace = true
[dev-dependencies]
agent_settings.workspace = true
-assistant_context_editor.workspace = true
+assistant_context.workspace = true
assistant_slash_command.workspace = true
async-trait.workspace = true
audio.workspace = true
@@ -6,7 +6,7 @@ use crate::{
},
};
use anyhow::{Result, anyhow};
-use assistant_context_editor::ContextStore;
+use assistant_context::ContextStore;
use assistant_slash_command::SlashCommandWorkingSet;
use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus, assert_hunks};
use call::{ActiveCall, ParticipantLocation, Room, room};
@@ -313,7 +313,7 @@ impl TestServer {
settings::KeymapFile::load_asset_allow_partial_failure(os_keymap, cx).unwrap(),
);
language_model::LanguageModelRegistry::test(cx);
- assistant_context_editor::init(client.clone(), cx);
+ assistant_context::init(client.clone(), cx);
agent_settings::init(cx);
});
@@ -26,7 +26,6 @@ agent_settings.workspace = true
anyhow.workspace = true
askpass.workspace = true
assets.workspace = true
-assistant_context_editor.workspace = true
assistant_tool.workspace = true
assistant_tools.workspace = true
audio.workspace = true
@@ -9,11 +9,10 @@ mod quick_action_bar;
#[cfg(target_os = "windows")]
pub(crate) mod windows_only_instance;
-use agent_ui::AgentDiffToolbar;
+use agent_ui::{AgentDiffToolbar, AgentPanelDelegate};
use anyhow::Context as _;
pub use app_menus::*;
use assets::Assets;
-use assistant_context_editor::AgentPanelDelegate;
use breadcrumbs::Breadcrumbs;
use client::zed_urls;
use collections::VecDeque;