Detailed changes
@@ -372,14 +372,13 @@ name = "assistant"
version = "0.1.0"
dependencies = [
"anyhow",
+ "assistant_context_editor",
"assistant_settings",
"assistant_slash_command",
"assistant_slash_commands",
"assistant_tool",
"async-watch",
- "chrono",
"client",
- "clock",
"collections",
"command_palette_hooks",
"context_server",
@@ -403,7 +402,6 @@ dependencies = [
"lsp",
"menu",
"multi_buffer",
- "open_ai",
"parking_lot",
"paths",
"picker",
@@ -412,21 +410,16 @@ dependencies = [
"prompt_library",
"proto",
"rand 0.8.5",
- "regex",
"rope",
- "rpc",
"schemars",
"search",
"semantic_index",
"serde",
- "serde_json",
"serde_json_lenient",
"settings",
"similar",
- "smallvec",
"smol",
"streaming_diff",
- "strum",
"telemetry",
"telemetry_events",
"terminal",
@@ -437,7 +430,6 @@ dependencies = [
"ui",
"unindent",
"util",
- "uuid",
"workspace",
"zed_actions",
]
@@ -505,6 +497,53 @@ dependencies = [
"zed_actions",
]
+[[package]]
+name = "assistant_context_editor"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "assistant_slash_command",
+ "assistant_slash_commands",
+ "assistant_tool",
+ "chrono",
+ "client",
+ "clock",
+ "collections",
+ "context_server",
+ "editor",
+ "feature_flags",
+ "fs",
+ "futures 0.3.31",
+ "fuzzy",
+ "gpui",
+ "language",
+ "language_model",
+ "language_models",
+ "log",
+ "open_ai",
+ "parking_lot",
+ "paths",
+ "pretty_assertions",
+ "project",
+ "prompt_library",
+ "rand 0.8.5",
+ "regex",
+ "rpc",
+ "serde",
+ "serde_json",
+ "settings",
+ "smallvec",
+ "smol",
+ "strum",
+ "telemetry_events",
+ "text",
+ "ui",
+ "unindent",
+ "util",
+ "uuid",
+ "workspace",
+]
+
[[package]]
name = "assistant_settings"
version = "0.1.0"
@@ -2640,6 +2679,7 @@ dependencies = [
"anthropic",
"anyhow",
"assistant",
+ "assistant_context_editor",
"assistant_slash_command",
"assistant_tool",
"async-stripe",
@@ -7,6 +7,7 @@ members = [
"crates/assets",
"crates/assistant",
"crates/assistant2",
+ "crates/assistant_context_editor",
"crates/assistant_settings",
"crates/assistant_slash_command",
"crates/assistant_slash_commands",
@@ -204,6 +205,7 @@ anthropic = { path = "crates/anthropic" }
assets = { path = "crates/assets" }
assistant = { path = "crates/assistant" }
assistant2 = { path = "crates/assistant2" }
+assistant_context_editor = { path = "crates/assistant_context_editor" }
assistant_settings = { path = "crates/assistant_settings" }
assistant_slash_command = { path = "crates/assistant_slash_command" }
assistant_slash_commands = { path = "crates/assistant_slash_commands" }
@@ -22,14 +22,13 @@ test-support = [
[dependencies]
anyhow.workspace = true
+assistant_context_editor.workspace = true
assistant_settings.workspace = true
assistant_slash_command.workspace = true
assistant_slash_commands.workspace = true
assistant_tool.workspace = true
async-watch.workspace = true
-chrono.workspace = true
client.workspace = true
-clock.workspace = true
collections.workspace = true
command_palette_hooks.workspace = true
context_server.workspace = true
@@ -50,27 +49,21 @@ log.workspace = true
lsp.workspace = true
menu.workspace = true
multi_buffer.workspace = true
-open_ai = { workspace = true, features = ["schemars"] }
parking_lot.workspace = true
paths.workspace = true
picker.workspace = true
project.workspace = true
prompt_library.workspace = true
proto.workspace = true
-regex.workspace = true
rope.workspace = true
-rpc.workspace = true
schemars.workspace = true
search.workspace = true
semantic_index.workspace = true
serde.workspace = true
-serde_json.workspace = true
settings.workspace = true
similar.workspace = true
-smallvec.workspace = true
smol.workspace = true
streaming_diff.workspace = true
-strum.workspace = true
telemetry.workspace = true
telemetry_events.workspace = true
terminal.workspace = true
@@ -79,7 +72,6 @@ text.workspace = true
theme.workspace = true
ui.workspace = true
util.workspace = true
-uuid.workspace = true
workspace.workspace = true
zed_actions.workspace = true
@@ -1,12 +1,9 @@
#![cfg_attr(target_os = "windows", allow(unused, dead_code))]
pub mod assistant_panel;
-mod context;
mod context_editor;
mod context_history;
-pub mod context_store;
mod inline_assistant;
-mod patch;
mod slash_command;
pub(crate) mod slash_command_picker;
pub mod slash_command_settings;
@@ -18,26 +15,23 @@ use std::sync::Arc;
use assistant_settings::AssistantSettings;
use assistant_slash_command::SlashCommandRegistry;
use assistant_slash_commands::{ProjectSlashCommandFeatureFlag, SearchSlashCommandFeatureFlag};
-use client::{proto, Client};
+use client::Client;
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::FeatureFlagAppExt;
use fs::Fs;
use gpui::impl_internal_actions;
-use gpui::{actions, AppContext, Global, SharedString, UpdateGlobal};
+use gpui::{actions, AppContext, Global, UpdateGlobal};
use language_model::{
LanguageModelId, LanguageModelProviderId, LanguageModelRegistry, LanguageModelResponseMessage,
};
use prompt_library::{PromptBuilder, PromptLoadingParams};
use semantic_index::{CloudEmbeddingProvider, SemanticDb};
-use serde::{Deserialize, Serialize};
+use serde::Deserialize;
use settings::{Settings, SettingsStore};
use util::ResultExt;
pub use crate::assistant_panel::{AssistantPanel, AssistantPanelEvent};
-pub use crate::context::*;
-pub use crate::context_store::*;
pub(crate) use crate::inline_assistant::*;
-pub use crate::patch::*;
use crate::slash_command_settings::SlashCommandSettings;
actions!(
@@ -72,15 +66,6 @@ impl_internal_actions!(assistant, [InsertDraggedFiles]);
const DEFAULT_CONTEXT_LINES: usize = 50;
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
-pub struct MessageId(clock::Lamport);
-
-impl MessageId {
- pub fn as_u64(self) -> u64 {
- self.0.as_u64()
- }
-}
-
#[derive(Deserialize, Debug)]
pub struct LanguageModelUsage {
pub prompt_tokens: u32,
@@ -95,55 +80,6 @@ pub struct LanguageModelChoiceDelta {
pub finish_reason: Option<String>,
}
-#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
-pub enum MessageStatus {
- Pending,
- Done,
- Error(SharedString),
- Canceled,
-}
-
-impl MessageStatus {
- pub fn from_proto(status: proto::ContextMessageStatus) -> MessageStatus {
- match status.variant {
- Some(proto::context_message_status::Variant::Pending(_)) => MessageStatus::Pending,
- Some(proto::context_message_status::Variant::Done(_)) => MessageStatus::Done,
- Some(proto::context_message_status::Variant::Error(error)) => {
- MessageStatus::Error(error.message.into())
- }
- Some(proto::context_message_status::Variant::Canceled(_)) => MessageStatus::Canceled,
- None => MessageStatus::Pending,
- }
- }
-
- pub fn to_proto(&self) -> proto::ContextMessageStatus {
- match self {
- MessageStatus::Pending => proto::ContextMessageStatus {
- variant: Some(proto::context_message_status::Variant::Pending(
- proto::context_message_status::Pending {},
- )),
- },
- MessageStatus::Done => proto::ContextMessageStatus {
- variant: Some(proto::context_message_status::Variant::Done(
- proto::context_message_status::Done {},
- )),
- },
- MessageStatus::Error(message) => proto::ContextMessageStatus {
- variant: Some(proto::context_message_status::Variant::Error(
- proto::context_message_status::Error {
- message: message.to_string(),
- },
- )),
- },
- MessageStatus::Canceled => proto::ContextMessageStatus {
- variant: Some(proto::context_message_status::Variant::Canceled(
- proto::context_message_status::Canceled {},
- )),
- },
- }
- }
-}
-
/// The state pertaining to the Assistant.
#[derive(Default)]
struct Assistant {
@@ -214,7 +150,7 @@ pub fn init(
})
.detach();
- context_store::init(&client.clone().into());
+ assistant_context_editor::init(client.clone(), cx);
prompt_library::init(cx);
init_language_model_settings(cx);
assistant_slash_command::init(cx);
@@ -4,11 +4,11 @@ use crate::context_editor::{
use crate::context_history::ContextHistory;
use crate::{
slash_command::SlashCommandCompletionProvider,
- terminal_inline_assistant::TerminalInlineAssistant, Context, ContextId, ContextStore,
- ContextStoreEvent, DeployHistory, DeployPromptLibrary, InlineAssistant, InsertDraggedFiles,
- NewContext, ToggleFocus, ToggleModelSelector,
+ terminal_inline_assistant::TerminalInlineAssistant, DeployHistory, DeployPromptLibrary,
+ InlineAssistant, InsertDraggedFiles, NewContext, ToggleFocus, ToggleModelSelector,
};
use anyhow::Result;
+use assistant_context_editor::{Context, ContextId, ContextStore, ContextStoreEvent};
use assistant_settings::{AssistantDockPosition, AssistantSettings};
use assistant_slash_command::SlashCommandWorkingSet;
use assistant_tool::ToolWorkingSet;
@@ -1,4 +1,9 @@
use anyhow::Result;
+use assistant_context_editor::{
+ AssistantPatch, AssistantPatchStatus, CacheStatus, Content, Context, ContextEvent, ContextId,
+ InvokedSlashCommandId, InvokedSlashCommandStatus, Message, MessageId, MessageMetadata,
+ MessageStatus, ParsedSlashCommand, PendingSlashCommandStatus, RequestType,
+};
use assistant_settings::AssistantSettings;
use assistant_slash_command::{SlashCommand, SlashCommandOutputSection, SlashCommandWorkingSet};
use assistant_slash_commands::{
@@ -58,11 +63,8 @@ use workspace::{
use crate::{
humanize_token_count, slash_command::SlashCommandCompletionProvider, slash_command_picker,
- Assist, AssistantPanel, AssistantPatch, AssistantPatchStatus, CacheStatus, ConfirmCommand,
- Content, Context, ContextEvent, ContextId, CopyCode, CycleMessageRole, Edit,
- InsertDraggedFiles, InsertIntoEditor, InvokedSlashCommandId, InvokedSlashCommandStatus,
- Message, MessageId, MessageMetadata, MessageStatus, ParsedSlashCommand,
- PendingSlashCommandStatus, QuoteSelection, RequestType, Split, ToggleModelSelector,
+ Assist, AssistantPanel, ConfirmCommand, CopyCode, CycleMessageRole, Edit, InsertDraggedFiles,
+ InsertIntoEditor, QuoteSelection, Split, ToggleModelSelector,
};
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -138,7 +140,7 @@ impl ContextEditor {
cx: &mut ViewContext<Self>,
) -> Self {
let completion_provider = SlashCommandCompletionProvider::new(
- context.read(cx).slash_commands.clone(),
+ context.read(cx).slash_commands().clone(),
Some(cx.view().downgrade()),
Some(workspace.clone()),
);
@@ -167,8 +169,8 @@ impl ContextEditor {
let sections = context.read(cx).slash_command_output_sections().to_vec();
let patch_ranges = context.read(cx).patch_ranges().collect::<Vec<_>>();
- let slash_commands = context.read(cx).slash_commands.clone();
- let tools = context.read(cx).tools.clone();
+ let slash_commands = context.read(cx).slash_commands().clone();
+ let tools = context.read(cx).tools().clone();
let mut this = Self {
context,
slash_commands,
@@ -1,5 +1,6 @@
use std::sync::Arc;
+use assistant_context_editor::{ContextStore, RemoteContextMetadata, SavedContextMetadata};
use gpui::{
AppContext, EventEmitter, FocusHandle, FocusableView, Model, Subscription, Task, View, WeakView,
};
@@ -10,7 +11,7 @@ use ui::{prelude::*, Avatar, ListItem, ListItemSpacing};
use workspace::Item;
use crate::context_editor::DEFAULT_TAB_TITLE;
-use crate::{AssistantPanel, ContextStore, RemoteContextMetadata, SavedContextMetadata};
+use crate::AssistantPanel;
#[derive(Clone)]
pub enum ContextMetadata {
@@ -1,8 +1,9 @@
use crate::{
humanize_token_count, AssistantPanel, AssistantPanelEvent, CycleNextInlineAssist,
- CyclePreviousInlineAssist, RequestType,
+ CyclePreviousInlineAssist,
};
use anyhow::{anyhow, Context as _, Result};
+use assistant_context_editor::RequestType;
use assistant_settings::AssistantSettings;
use client::{telemetry::Telemetry, ErrorExt};
use collections::{hash_map, HashMap, HashSet, VecDeque};
@@ -1,8 +1,7 @@
use crate::context_editor::ContextEditor;
use anyhow::Result;
-use assistant_slash_command::AfterCompletion;
pub use assistant_slash_command::SlashCommand;
-use assistant_slash_command::SlashCommandWorkingSet;
+use assistant_slash_command::{AfterCompletion, SlashCommandLine, SlashCommandWorkingSet};
use editor::{CompletionProvider, Editor};
use fuzzy::{match_strings, StringMatchCandidate};
use gpui::{Model, Task, ViewContext, WeakView, WindowContext};
@@ -28,13 +27,6 @@ pub(crate) struct SlashCommandCompletionProvider {
workspace: Option<WeakView<Workspace>>,
}
-pub(crate) struct SlashCommandLine {
- /// The range within the line containing the command name.
- pub name: Range<usize>,
- /// Ranges within the line containing the command arguments.
- pub arguments: Vec<Range<usize>>,
-}
-
impl SlashCommandCompletionProvider {
pub fn new(
slash_commands: Arc<SlashCommandWorkingSet>,
@@ -336,57 +328,3 @@ impl CompletionProvider for SlashCommandCompletionProvider {
false
}
}
-
-impl SlashCommandLine {
- pub(crate) fn parse(line: &str) -> Option<Self> {
- let mut call: Option<Self> = None;
- let mut ix = 0;
- for c in line.chars() {
- let next_ix = ix + c.len_utf8();
- if let Some(call) = &mut call {
- // The command arguments start at the first non-whitespace character
- // after the command name, and continue until the end of the line.
- if let Some(argument) = call.arguments.last_mut() {
- if c.is_whitespace() {
- if (*argument).is_empty() {
- argument.start = next_ix;
- argument.end = next_ix;
- } else {
- argument.end = ix;
- call.arguments.push(next_ix..next_ix);
- }
- } else {
- argument.end = next_ix;
- }
- }
- // The command name ends at the first whitespace character.
- else if !call.name.is_empty() {
- if c.is_whitespace() {
- call.arguments = vec![next_ix..next_ix];
- } else {
- call.name.end = next_ix;
- }
- }
- // The command name must begin with a letter.
- else if c.is_alphabetic() {
- call.name.end = next_ix;
- } else {
- return None;
- }
- }
- // Commands start with a slash.
- else if c == '/' {
- call = Some(SlashCommandLine {
- name: next_ix..next_ix,
- arguments: Vec::new(),
- });
- }
- // The line can't contain anything before the slash except for whitespace.
- else if !c.is_whitespace() {
- return None;
- }
- ix = next_ix;
- }
- call
- }
-}
@@ -1,7 +1,6 @@
-use crate::{
- humanize_token_count, AssistantPanel, AssistantPanelEvent, RequestType, DEFAULT_CONTEXT_LINES,
-};
+use crate::{humanize_token_count, AssistantPanel, AssistantPanelEvent, DEFAULT_CONTEXT_LINES};
use anyhow::{Context as _, Result};
+use assistant_context_editor::RequestType;
use assistant_settings::AssistantSettings;
use client::telemetry::Telemetry;
use collections::{HashMap, VecDeque};
@@ -0,0 +1,58 @@
+[package]
+name = "assistant_context_editor"
+version = "0.1.0"
+edition.workspace = true
+publish.workspace = true
+license = "GPL-3.0-or-later"
+
+[lints]
+workspace = true
+
+[lib]
+path = "src/assistant_context_editor.rs"
+
+[dependencies]
+anyhow.workspace = true
+assistant_slash_command.workspace = true
+assistant_slash_commands.workspace = true
+assistant_tool.workspace = true
+chrono.workspace = true
+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
+language.workspace = true
+language_model.workspace = true
+language_models.workspace = true
+log.workspace = true
+open_ai.workspace = true
+paths.workspace = true
+project.workspace = true
+prompt_library.workspace = true
+regex.workspace = true
+rpc.workspace = true
+serde.workspace = true
+serde_json.workspace = true
+smallvec.workspace = true
+smol.workspace = true
+strum.workspace = true
+telemetry_events.workspace = true
+text.workspace = true
+ui.workspace = true
+util.workspace = true
+uuid.workspace = true
+
+[dev-dependencies]
+language_model = { workspace = true, features = ["test-support"] }
+parking_lot.workspace = true
+pretty_assertions.workspace = true
+rand.workspace = true
+settings.workspace = true
+unindent.workspace = true
+workspace = { workspace = true, features = ["test-support"] }
@@ -0,0 +1 @@
+../../LICENSE-GPL
@@ -0,0 +1,16 @@
+mod context;
+mod context_store;
+mod patch;
+
+use std::sync::Arc;
+
+use client::Client;
+use gpui::AppContext;
+
+pub use crate::context::*;
+pub use crate::context_store::*;
+pub use crate::patch::*;
+
+pub fn init(client: Arc<Client>, _cx: &mut AppContext) {
+ context_store::init(&client.into());
+}
@@ -1,14 +1,11 @@
#[cfg(test)]
mod context_tests;
-use crate::{
- slash_command::SlashCommandLine, AssistantEdit, AssistantPatch, AssistantPatchStatus,
- MessageId, MessageStatus,
-};
+use crate::patch::{AssistantEdit, AssistantPatch, AssistantPatchStatus};
use anyhow::{anyhow, Context as _, Result};
use assistant_slash_command::{
- SlashCommandContent, SlashCommandEvent, SlashCommandOutputSection, SlashCommandResult,
- SlashCommandWorkingSet,
+ SlashCommandContent, SlashCommandEvent, SlashCommandLine, SlashCommandOutputSection,
+ SlashCommandResult, SlashCommandWorkingSet,
};
use assistant_slash_commands::FileCommandMetadata;
use assistant_tool::ToolWorkingSet;
@@ -22,8 +19,6 @@ use gpui::{
AppContext, Context as _, EventEmitter, Model, ModelContext, RenderImage, SharedString,
Subscription, Task,
};
-use prompt_library::PromptBuilder;
-
use language::{AnchorRangeExt, Bias, Buffer, LanguageRegistry, OffsetRangeExt, Point, ToOffset};
use language_model::{
LanguageModel, LanguageModelCacheConfiguration, LanguageModelCompletionEvent,
@@ -38,6 +33,7 @@ use language_models::{
use open_ai::Model as OpenAiModel;
use paths::contexts_dir;
use project::Project;
+use prompt_library::PromptBuilder;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use std::{
@@ -52,9 +48,9 @@ use std::{
};
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use text::{BufferSnapshot, ToPoint};
+use ui::IconName;
use util::{post_inc, ResultExt, TryFutureExt};
use uuid::Uuid;
-use workspace::ui::IconName;
#[derive(Clone, Eq, PartialEq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
pub struct ContextId(String);
@@ -73,6 +69,64 @@ impl ContextId {
}
}
+#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
+pub struct MessageId(pub clock::Lamport);
+
+impl MessageId {
+ pub fn as_u64(self) -> u64 {
+ self.0.as_u64()
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
+pub enum MessageStatus {
+ Pending,
+ Done,
+ Error(SharedString),
+ Canceled,
+}
+
+impl MessageStatus {
+ pub fn from_proto(status: proto::ContextMessageStatus) -> MessageStatus {
+ match status.variant {
+ Some(proto::context_message_status::Variant::Pending(_)) => MessageStatus::Pending,
+ Some(proto::context_message_status::Variant::Done(_)) => MessageStatus::Done,
+ Some(proto::context_message_status::Variant::Error(error)) => {
+ MessageStatus::Error(error.message.into())
+ }
+ Some(proto::context_message_status::Variant::Canceled(_)) => MessageStatus::Canceled,
+ None => MessageStatus::Pending,
+ }
+ }
+
+ pub fn to_proto(&self) -> proto::ContextMessageStatus {
+ match self {
+ MessageStatus::Pending => proto::ContextMessageStatus {
+ variant: Some(proto::context_message_status::Variant::Pending(
+ proto::context_message_status::Pending {},
+ )),
+ },
+ MessageStatus::Done => proto::ContextMessageStatus {
+ variant: Some(proto::context_message_status::Variant::Done(
+ proto::context_message_status::Done {},
+ )),
+ },
+ MessageStatus::Error(message) => proto::ContextMessageStatus {
+ variant: Some(proto::context_message_status::Variant::Error(
+ proto::context_message_status::Error {
+ message: message.to_string(),
+ },
+ )),
+ },
+ MessageStatus::Canceled => proto::ContextMessageStatus {
+ variant: Some(proto::context_message_status::Variant::Canceled(
+ proto::context_message_status::Canceled {},
+ )),
+ },
+ }
+ }
+}
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RequestType {
/// Request a normal chat response from the model.
@@ -423,7 +477,7 @@ pub struct MessageCacheMetadata {
pub struct MessageMetadata {
pub role: Role,
pub status: MessageStatus,
- pub(crate) timestamp: clock::Lamport,
+ pub timestamp: clock::Lamport,
#[serde(skip)]
pub cache: Option<MessageCacheMetadata>,
}
@@ -544,8 +598,8 @@ pub struct Context {
parsed_slash_commands: Vec<ParsedSlashCommand>,
invoked_slash_commands: HashMap<InvokedSlashCommandId, InvokedSlashCommand>,
edits_since_last_parse: language::Subscription,
- pub(crate) slash_commands: Arc<SlashCommandWorkingSet>,
- pub(crate) tools: Arc<ToolWorkingSet>,
+ slash_commands: Arc<SlashCommandWorkingSet>,
+ tools: Arc<ToolWorkingSet>,
slash_command_output_sections: Vec<SlashCommandOutputSection<language::Anchor>>,
pending_tool_uses_by_id: HashMap<LanguageModelToolUseId, PendingToolUse>,
message_anchors: Vec<MessageAnchor>,
@@ -790,6 +844,14 @@ impl Context {
}
}
+ pub fn slash_commands(&self) -> &Arc<SlashCommandWorkingSet> {
+ &self.slash_commands
+ }
+
+ pub fn tools(&self) -> &Arc<ToolWorkingSet> {
+ &self.tools
+ }
+
pub fn set_capability(
&mut self,
capability: language::Capability,
@@ -1048,11 +1110,7 @@ impl Context {
self.summary.as_ref()
}
- pub(crate) fn patch_containing(
- &self,
- position: Point,
- cx: &AppContext,
- ) -> Option<&AssistantPatch> {
+ pub fn patch_containing(&self, position: Point, cx: &AppContext) -> Option<&AssistantPatch> {
let buffer = self.buffer.read(cx);
let index = self.patches.binary_search_by(|patch| {
let patch_range = patch.range.to_point(&buffer);
@@ -1075,7 +1133,7 @@ impl Context {
self.patches.iter().map(|patch| patch.range.clone())
}
- pub(crate) fn patch_for_range(
+ pub fn patch_for_range(
&self,
range: &Range<language::Anchor>,
cx: &AppContext,
@@ -1165,7 +1223,7 @@ impl Context {
}
}
- pub(crate) fn token_count(&self) -> Option<usize> {
+ pub fn token_count(&self) -> Option<usize> {
self.token_count
}
@@ -2879,7 +2937,7 @@ impl Context {
self.message_anchors.insert(insertion_ix, new_anchor);
}
- pub(super) fn summarize(&mut self, replace_old: bool, cx: &mut ModelContext<Self>) {
+ pub fn summarize(&mut self, replace_old: bool, cx: &mut ModelContext<Self>) {
let Some(provider) = LanguageModelRegistry::read_global(cx).active_provider() else {
return;
};
@@ -3118,7 +3176,7 @@ impl Context {
});
}
- pub(crate) fn custom_summary(&mut self, custom_summary: String, cx: &mut ModelContext<Self>) {
+ pub fn custom_summary(&mut self, custom_summary: String, cx: &mut ModelContext<Self>) {
let timestamp = self.next_timestamp();
let summary = self.summary.get_or_insert(ContextSummary::default());
summary.timestamp = timestamp;
@@ -1,7 +1,6 @@
-use super::{AssistantEdit, MessageCacheMetadata};
use crate::{
- assistant_panel, AssistantEditKind, CacheStatus, Context, ContextEvent, ContextId,
- ContextOperation, InvokedSlashCommandId, MessageId, MessageStatus,
+ AssistantEdit, AssistantEditKind, CacheStatus, Context, ContextEvent, ContextId,
+ ContextOperation, InvokedSlashCommandId, MessageCacheMetadata, MessageId, MessageStatus,
};
use anyhow::Result;
use assistant_slash_command::{
@@ -48,7 +47,6 @@ fn test_inserting_and_removing_messages(cx: &mut AppContext) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
- assistant_panel::init(cx);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
let context = cx.new_model(|cx| {
@@ -189,7 +187,6 @@ fn test_message_splitting(cx: &mut AppContext) {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
LanguageModelRegistry::test(cx);
- assistant_panel::init(cx);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
@@ -294,7 +291,6 @@ fn test_messages_for_offsets(cx: &mut AppContext) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
- assistant_panel::init(cx);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
let context = cx.new_model(|cx| {
@@ -390,7 +386,6 @@ async fn test_slash_commands(cx: &mut TestAppContext) {
cx.set_global(settings_store);
cx.update(LanguageModelRegistry::test);
cx.update(Project::init_settings);
- cx.update(assistant_panel::init);
let fs = FakeFs::new(cx.background_executor.clone());
fs.insert_tree(
@@ -698,7 +693,6 @@ async fn test_workflow_step_parsing(cx: &mut TestAppContext) {
let project = Project::test(fs, [Path::new("/root")], cx).await;
cx.update(LanguageModelRegistry::test);
- cx.update(assistant_panel::init);
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
// Create a new context
@@ -1081,7 +1075,6 @@ async fn test_serialization(cx: &mut TestAppContext) {
let settings_store = cx.update(SettingsStore::test);
cx.set_global(settings_store);
cx.update(LanguageModelRegistry::test);
- cx.update(assistant_panel::init);
let registry = Arc::new(LanguageRegistry::test(cx.executor()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
let context = cx.new_model(|cx| {
@@ -1173,7 +1166,6 @@ async fn test_random_context_collaboration(cx: &mut TestAppContext, mut rng: Std
cx.set_global(settings_store);
cx.update(LanguageModelRegistry::test);
- cx.update(assistant_panel::init);
let slash_commands = cx.update(SlashCommandRegistry::default_global);
slash_commands.register_command(FakeSlashCommand("cmd-1".into()), false);
slash_commands.register_command(FakeSlashCommand("cmd-2".into()), false);
@@ -1446,7 +1438,6 @@ fn test_mark_cache_anchors(cx: &mut AppContext) {
let settings_store = SettingsStore::test(cx);
LanguageModelRegistry::test(cx);
cx.set_global(settings_store);
- assistant_panel::init(cx);
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let prompt_builder = Arc::new(PromptBuilder::new(None).unwrap());
let context = cx.new_model(|cx| {
@@ -33,7 +33,7 @@ use std::{
};
use util::{ResultExt, TryFutureExt};
-pub fn init(client: &AnyProtoClient) {
+pub(crate) fn init(client: &AnyProtoClient) {
client.add_model_message_handler(ContextStore::handle_advertise_contexts);
client.add_model_request_handler(ContextStore::handle_open_context);
client.add_model_request_handler(ContextStore::handle_create_context);
@@ -497,11 +497,7 @@ impl ContextStore {
})
}
- pub(super) fn loaded_context_for_id(
- &self,
- id: &ContextId,
- cx: &AppContext,
- ) -> Option<Model<Context>> {
+ pub fn loaded_context_for_id(&self, id: &ContextId, cx: &AppContext) -> Option<Model<Context>> {
self.contexts.iter().find_map(|context| {
let context = context.upgrade()?;
if context.read(cx).id() == id {
@@ -9,7 +9,7 @@ use std::{cmp, ops::Range, path::Path, sync::Arc};
use text::{AnchorRangeExt as _, Bias, OffsetRangeExt as _, Point};
#[derive(Clone, Debug)]
-pub(crate) struct AssistantPatch {
+pub struct AssistantPatch {
pub range: Range<language::Anchor>,
pub title: SharedString,
pub edits: Arc<[Result<AssistantEdit>]>,
@@ -17,13 +17,13 @@ pub(crate) struct AssistantPatch {
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub(crate) enum AssistantPatchStatus {
+pub enum AssistantPatchStatus {
Pending,
Ready,
}
#[derive(Clone, Debug, PartialEq, Eq)]
-pub(crate) struct AssistantEdit {
+pub struct AssistantEdit {
pub path: String,
pub kind: AssistantEditKind,
}
@@ -55,7 +55,7 @@ pub enum AssistantEditKind {
}
#[derive(Clone, Debug, Eq, PartialEq)]
-pub(crate) struct ResolvedPatch {
+pub struct ResolvedPatch {
pub edit_groups: HashMap<Model<Buffer>, Vec<ResolvedEditGroup>>,
pub errors: Vec<AssistantPatchResolutionError>,
}
@@ -74,7 +74,7 @@ pub struct ResolvedEdit {
}
#[derive(Clone, Debug, Eq, PartialEq)]
-pub(crate) struct AssistantPatchResolutionError {
+pub struct AssistantPatchResolutionError {
pub edit_ix: usize,
pub message: String,
}
@@ -425,7 +425,7 @@ impl AssistantEditKind {
}
impl AssistantPatch {
- pub(crate) async fn resolve(
+ pub async fn resolve(
&self,
project: Model<Project>,
cx: &mut AsyncAppContext,
@@ -262,6 +262,67 @@ impl SlashCommandOutputSection<language::Anchor> {
}
}
+pub struct SlashCommandLine {
+ /// The range within the line containing the command name.
+ pub name: Range<usize>,
+ /// Ranges within the line containing the command arguments.
+ pub arguments: Vec<Range<usize>>,
+}
+
+impl SlashCommandLine {
+ pub fn parse(line: &str) -> Option<Self> {
+ let mut call: Option<Self> = None;
+ let mut ix = 0;
+ for c in line.chars() {
+ let next_ix = ix + c.len_utf8();
+ if let Some(call) = &mut call {
+ // The command arguments start at the first non-whitespace character
+ // after the command name, and continue until the end of the line.
+ if let Some(argument) = call.arguments.last_mut() {
+ if c.is_whitespace() {
+ if (*argument).is_empty() {
+ argument.start = next_ix;
+ argument.end = next_ix;
+ } else {
+ argument.end = ix;
+ call.arguments.push(next_ix..next_ix);
+ }
+ } else {
+ argument.end = next_ix;
+ }
+ }
+ // The command name ends at the first whitespace character.
+ else if !call.name.is_empty() {
+ if c.is_whitespace() {
+ call.arguments = vec![next_ix..next_ix];
+ } else {
+ call.name.end = next_ix;
+ }
+ }
+ // The command name must begin with a letter.
+ else if c.is_alphabetic() {
+ call.name.end = next_ix;
+ } else {
+ return None;
+ }
+ }
+ // Commands start with a slash.
+ else if c == '/' {
+ call = Some(SlashCommandLine {
+ name: next_ix..next_ix,
+ arguments: Vec::new(),
+ });
+ }
+ // The line can't contain anything before the slash except for whitespace.
+ else if !c.is_whitespace() {
+ return None;
+ }
+ ix = next_ix;
+ }
+ call
+ }
+}
+
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
@@ -79,6 +79,7 @@ uuid.workspace = true
[dev-dependencies]
assistant = { workspace = true, features = ["test-support"] }
+assistant_context_editor.workspace = true
assistant_slash_command.workspace = true
assistant_tool.workspace = true
async-trait.workspace = true
@@ -6,7 +6,7 @@ use crate::{
},
};
use anyhow::{anyhow, Result};
-use assistant::ContextStore;
+use assistant_context_editor::ContextStore;
use assistant_slash_command::SlashCommandWorkingSet;
use assistant_tool::ToolWorkingSet;
use call::{room, ActiveCall, ParticipantLocation, Room};
@@ -308,7 +308,7 @@ impl TestServer {
settings::KeymapFile::load_asset_allow_partial_failure(os_keymap, cx).unwrap(),
);
language_model::LanguageModelRegistry::test(cx);
- assistant::context_store::init(&client.clone().into());
+ assistant_context_editor::init(client.clone(), cx);
});
client