Detailed changes
@@ -62,8 +62,6 @@
/crates/rules_library/ @zed-industries/ai-team
# SUGGESTED: Review needed - based on Richard Feldman (2 commits)
/crates/shell_command_parser/ @zed-industries/ai-team
-/crates/supermaven/ @zed-industries/ai-team
-/crates/supermaven_api/ @zed-industries/ai-team
/crates/vercel/ @zed-industries/ai-team
/crates/x_ai/ @zed-industries/ai-team
/crates/zeta_prompt/ @zed-industries/ai-team
@@ -5403,7 +5403,6 @@ dependencies = [
"semver",
"serde_json",
"settings",
- "supermaven",
"telemetry",
"text",
"theme",
@@ -16524,49 +16523,6 @@ dependencies = [
"ztracing",
]
-[[package]]
-name = "supermaven"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "client",
- "collections",
- "edit_prediction_types",
- "editor",
- "env_logger 0.11.8",
- "futures 0.3.31",
- "gpui",
- "http_client",
- "language",
- "log",
- "postage",
- "project",
- "serde",
- "serde_json",
- "settings",
- "smol",
- "supermaven_api",
- "text",
- "theme",
- "ui",
- "unicode-segmentation",
- "util",
-]
-
-[[package]]
-name = "supermaven_api"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "futures 0.3.31",
- "http_client",
- "paths",
- "serde",
- "serde_json",
- "smol",
- "util",
-]
-
[[package]]
name = "sval"
version = "2.15.0"
@@ -21861,7 +21817,6 @@ dependencies = [
"smol",
"snippet_provider",
"snippets_ui",
- "supermaven",
"svg_preview",
"sysinfo 0.37.2",
"system_specs",
@@ -182,8 +182,6 @@ members = [
"crates/storybook",
"crates/streaming_diff",
"crates/sum_tree",
- "crates/supermaven",
- "crates/supermaven_api",
"crates/svg_preview",
"crates/system_specs",
"crates/tab_switcher",
@@ -427,8 +425,6 @@ sqlez_macros = { path = "crates/sqlez_macros" }
story = { path = "crates/story" }
streaming_diff = { path = "crates/streaming_diff" }
sum_tree = { path = "crates/sum_tree" }
-supermaven = { path = "crates/supermaven" }
-supermaven_api = { path = "crates/supermaven_api" }
codestral = { path = "crates/codestral" }
system_specs = { path = "crates/system_specs" }
tab_switcher = { path = "crates/tab_switcher" }
@@ -900,7 +896,6 @@ sidebar = { codegen-units = 1 }
snippet = { codegen-units = 1 }
snippets_ui = { codegen-units = 1 }
story = { codegen-units = 1 }
-supermaven_api = { codegen-units = 1 }
telemetry_events = { codegen-units = 1 }
theme_selector = { codegen-units = 1 }
time_format = { codegen-units = 1 }
@@ -371,7 +371,6 @@ fn update_command_palette_filter(cx: &mut App) {
filter.hide_namespace("agents");
filter.hide_namespace("assistant");
filter.hide_namespace("copilot");
- filter.hide_namespace("supermaven");
filter.hide_namespace("zed_predict_onboarding");
filter.hide_namespace("edit_prediction");
@@ -392,19 +391,11 @@ fn update_command_palette_filter(cx: &mut App) {
EditPredictionProvider::None => {
filter.hide_namespace("edit_prediction");
filter.hide_namespace("copilot");
- filter.hide_namespace("supermaven");
filter.hide_action_types(&edit_prediction_actions);
}
EditPredictionProvider::Copilot => {
filter.show_namespace("edit_prediction");
filter.show_namespace("copilot");
- filter.hide_namespace("supermaven");
- filter.show_action_types(edit_prediction_actions.iter());
- }
- EditPredictionProvider::Supermaven => {
- filter.show_namespace("edit_prediction");
- filter.hide_namespace("copilot");
- filter.show_namespace("supermaven");
filter.show_action_types(edit_prediction_actions.iter());
}
EditPredictionProvider::Zed
@@ -416,7 +407,6 @@ fn update_command_palette_filter(cx: &mut App) {
| EditPredictionProvider::Experimental(_) => {
filter.show_namespace("edit_prediction");
filter.hide_namespace("copilot");
- filter.hide_namespace("supermaven");
filter.show_action_types(edit_prediction_actions.iter());
}
}
@@ -1836,7 +1836,6 @@ fn is_ep_store_provider(provider: EditPredictionProvider) -> bool {
| EditPredictionProvider::Experimental(_) => true,
EditPredictionProvider::None
| EditPredictionProvider::Copilot
- | EditPredictionProvider::Supermaven
| EditPredictionProvider::Codestral => false,
}
}
@@ -1877,7 +1876,6 @@ impl EditPredictionStore {
EditPredictionProvider::OpenAiCompatibleApi => (false, 2),
EditPredictionProvider::None
| EditPredictionProvider::Copilot
- | EditPredictionProvider::Supermaven
| EditPredictionProvider::Codestral => {
log::error!("queue_prediction_refresh called with non-store provider");
return;
@@ -40,7 +40,6 @@ paths.workspace = true
project.workspace = true
regex.workspace = true
settings.workspace = true
-supermaven.workspace = true
telemetry.workspace = true
text.workspace = true
theme.workspace = true
@@ -30,7 +30,6 @@ use std::{
sync::{Arc, LazyLock},
time::Duration,
};
-use supermaven::{AccountStatus, Supermaven};
use ui::{
Clickable, ContextMenu, ContextMenuEntry, DocumentationSide, IconButton, IconButtonShape,
Indicator, PopoverMenu, PopoverMenuHandle, ProgressBar, Tooltip, prelude::*,
@@ -75,13 +74,6 @@ pub struct EditPredictionButton {
project: WeakEntity<Project>,
}
-enum SupermavenButtonStatus {
- Ready,
- Errored(String),
- NeedsActivation(String),
- Initializing,
-}
-
impl Render for EditPredictionButton {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
// Return empty div if AI is disabled
@@ -188,101 +180,6 @@ impl Render for EditPredictionButton {
.with_handle(self.popover_menu_handle.clone()),
)
}
- EditPredictionProvider::Supermaven => {
- let Some(supermaven) = Supermaven::global(cx) else {
- return div();
- };
-
- let supermaven = supermaven.read(cx);
-
- let status = match supermaven {
- Supermaven::Starting => SupermavenButtonStatus::Initializing,
- Supermaven::FailedDownload { error } => {
- SupermavenButtonStatus::Errored(error.to_string())
- }
- Supermaven::Spawned(agent) => {
- let account_status = agent.account_status.clone();
- match account_status {
- AccountStatus::NeedsActivation { activate_url } => {
- SupermavenButtonStatus::NeedsActivation(activate_url)
- }
- AccountStatus::Unknown => SupermavenButtonStatus::Initializing,
- AccountStatus::Ready => SupermavenButtonStatus::Ready,
- }
- }
- Supermaven::Error { error } => {
- SupermavenButtonStatus::Errored(error.to_string())
- }
- };
-
- let icon = status.to_icon();
- let tooltip_text = status.to_tooltip();
- let has_menu = status.has_menu();
- let this = cx.weak_entity();
- let fs = self.fs.clone();
- let file = self.file.clone();
- let language = self.language.clone();
- let project = self.project.clone();
-
- div().child(
- PopoverMenu::new("supermaven")
- .on_open({
- let file = file.clone();
- let language = language;
- let project = project;
- Rc::new(move |_window, cx| {
- emit_edit_prediction_menu_opened(
- "supermaven",
- &file,
- &language,
- &project,
- cx,
- );
- })
- })
- .menu(move |window, cx| match &status {
- SupermavenButtonStatus::NeedsActivation(activate_url) => {
- Some(ContextMenu::build(window, cx, |menu, _, _| {
- let fs = fs.clone();
- let activate_url = activate_url.clone();
-
- menu.entry("Sign In", None, move |_, cx| {
- cx.open_url(activate_url.as_str())
- })
- .entry(
- "Use Zed AI",
- None,
- move |_, cx| {
- set_completion_provider(
- fs.clone(),
- cx,
- EditPredictionProvider::Zed,
- )
- },
- )
- }))
- }
- SupermavenButtonStatus::Ready => this
- .update(cx, |this, cx| {
- this.build_supermaven_context_menu(window, cx)
- })
- .ok(),
- _ => None,
- })
- .anchor(Corner::BottomRight)
- .trigger_with_tooltip(
- IconButton::new("supermaven-icon", icon),
- move |window, cx| {
- if has_menu {
- Tooltip::for_action(tooltip_text.clone(), &ToggleMenu, cx)
- } else {
- Tooltip::text(tooltip_text.clone())(window, cx)
- }
- },
- )
- .with_handle(self.popover_menu_handle.clone()),
- )
- }
EditPredictionProvider::Codestral => {
let enabled = self.editor_enabled.unwrap_or(true);
let has_api_key = codestral::codestral_api_key(cx).is_some();
@@ -1120,21 +1017,6 @@ impl EditPredictionButton {
})
}
- fn build_supermaven_context_menu(
- &self,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> Entity<ContextMenu> {
- ContextMenu::build(window, cx, |menu, window, cx| {
- let menu = self.build_language_settings_menu(menu, window, cx);
- let menu =
- self.add_provider_switching_section(menu, EditPredictionProvider::Supermaven, cx);
-
- menu.separator()
- .action("Sign Out", supermaven::SignOut.boxed_clone())
- })
- }
-
fn build_codestral_context_menu(
&self,
window: &mut Window,
@@ -1384,33 +1266,6 @@ impl StatusItemView for EditPredictionButton {
}
}
-impl SupermavenButtonStatus {
- fn to_icon(&self) -> IconName {
- match self {
- SupermavenButtonStatus::Ready => IconName::Supermaven,
- SupermavenButtonStatus::Errored(_) => IconName::SupermavenError,
- SupermavenButtonStatus::NeedsActivation(_) => IconName::SupermavenInit,
- SupermavenButtonStatus::Initializing => IconName::SupermavenInit,
- }
- }
-
- fn to_tooltip(&self) -> String {
- match self {
- SupermavenButtonStatus::Ready => "Supermaven is ready".to_string(),
- SupermavenButtonStatus::Errored(error) => format!("Supermaven error: {}", error),
- SupermavenButtonStatus::NeedsActivation(_) => "Supermaven needs activation".to_string(),
- SupermavenButtonStatus::Initializing => "Supermaven initializing".to_string(),
- }
- }
-
- fn has_menu(&self) -> bool {
- match self {
- SupermavenButtonStatus::Ready | SupermavenButtonStatus::NeedsActivation(_) => true,
- SupermavenButtonStatus::Errored(_) | SupermavenButtonStatus::Initializing => false,
- }
- }
-}
-
async fn open_disabled_globs_setting_in_editor(
workspace: WeakEntity<Workspace>,
cx: &mut AsyncWindowContext,
@@ -1507,14 +1362,6 @@ pub fn get_available_providers(cx: &mut App) -> Vec<EditPredictionProvider> {
providers.push(EditPredictionProvider::Copilot);
};
- if let Some(supermaven) = Supermaven::global(cx) {
- if let Supermaven::Spawned(agent) = supermaven.read(cx) {
- if matches!(agent.account_status, AccountStatus::Ready) {
- providers.push(EditPredictionProvider::Supermaven);
- }
- }
- }
-
if codestral::codestral_api_key(cx).is_some() {
providers.push(EditPredictionProvider::Codestral);
}
@@ -28579,7 +28579,7 @@ fn edit_prediction_edit_text(
}
fn edit_prediction_fallback_text(edits: &[(Range<Anchor>, Arc<str>)], cx: &App) -> HighlightedText {
- // Fallback for providers that don't provide edit_preview (like Copilot/Supermaven)
+ // Fallback for providers that don't provide edit_preview (like Copilot)
// Just show the raw edit text with basic styling
let mut text = String::new();
let mut highlights = Vec::new();
@@ -225,10 +225,6 @@ pub enum IconName {
Star,
StarFilled,
Stop,
- Supermaven,
- SupermavenDisabled,
- SupermavenError,
- SupermavenInit,
SwatchBook,
SweepAi,
SweepAiDisabled,
@@ -396,8 +396,7 @@ impl InlayHintSettings {
}
}
-/// The settings for edit predictions, such as [GitHub Copilot](https://github.com/features/copilot)
-/// or [Supermaven](https://supermaven.com).
+/// The settings for edit predictions, such as [GitHub Copilot](https://github.com/features/copilot).
#[derive(Clone, Debug, Default)]
pub struct EditPredictionSettings {
/// The provider that supplies edit predictions.
@@ -419,12 +419,6 @@ pub fn copilot_dir() -> &'static PathBuf {
COPILOT_DIR.get_or_init(|| data_dir().join("copilot"))
}
-/// Returns the path to the Supermaven directory.
-pub fn supermaven_dir() -> &'static PathBuf {
- static SUPERMAVEN_DIR: OnceLock<PathBuf> = OnceLock::new();
- SUPERMAVEN_DIR.get_or_init(|| data_dir().join("supermaven"))
-}
-
/// Returns the path to the default Prettier directory.
pub fn default_prettier_dir() -> &'static PathBuf {
static DEFAULT_PRETTIER_DIR: OnceLock<PathBuf> = OnceLock::new();
@@ -81,7 +81,6 @@ pub enum EditPredictionProvider {
None,
#[default]
Copilot,
- Supermaven,
Zed,
Codestral,
Ollama,
@@ -103,7 +102,6 @@ impl<'de> Deserialize<'de> for EditPredictionProvider {
pub enum Content {
None,
Copilot,
- Supermaven,
Zed,
Codestral,
Ollama,
@@ -116,7 +114,6 @@ impl<'de> Deserialize<'de> for EditPredictionProvider {
Ok(match Content::deserialize(deserializer)? {
Content::None => EditPredictionProvider::None,
Content::Copilot => EditPredictionProvider::Copilot,
- Content::Supermaven => EditPredictionProvider::Supermaven,
Content::Zed => EditPredictionProvider::Zed,
Content::Codestral => EditPredictionProvider::Codestral,
Content::Ollama => EditPredictionProvider::Ollama,
@@ -146,7 +143,6 @@ impl EditPredictionProvider {
EditPredictionProvider::Zed => true,
EditPredictionProvider::None
| EditPredictionProvider::Copilot
- | EditPredictionProvider::Supermaven
| EditPredictionProvider::Codestral
| EditPredictionProvider::Ollama
| EditPredictionProvider::OpenAiCompatibleApi
@@ -160,7 +156,6 @@ impl EditPredictionProvider {
match self {
EditPredictionProvider::Zed => Some("Zed AI"),
EditPredictionProvider::Copilot => Some("GitHub Copilot"),
- EditPredictionProvider::Supermaven => Some("Supermaven"),
EditPredictionProvider::Codestral => Some("Codestral"),
EditPredictionProvider::Sweep => Some("Sweep"),
EditPredictionProvider::Mercury => Some("Mercury"),
@@ -1,44 +0,0 @@
-[package]
-name = "supermaven"
-version = "0.1.0"
-edition.workspace = true
-publish.workspace = true
-license = "GPL-3.0-or-later"
-
-[lints]
-workspace = true
-
-[lib]
-path = "src/supermaven.rs"
-doctest = false
-
-[dependencies]
-anyhow.workspace = true
-client.workspace = true
-collections.workspace = true
-edit_prediction_types.workspace = true
-futures.workspace = true
-gpui.workspace = true
-language.workspace = true
-log.workspace = true
-postage.workspace = true
-serde.workspace = true
-serde_json.workspace = true
-settings.workspace = true
-smol.workspace = true
-supermaven_api.workspace = true
-text.workspace = true
-ui.workspace = true
-unicode-segmentation.workspace = true
-util.workspace = true
-
-[dev-dependencies]
-editor = { workspace = true, features = ["test-support"] }
-env_logger.workspace = true
-gpui = { workspace = true, features = ["test-support"] }
-language = { workspace = true, features = ["test-support"] }
-project = { workspace = true, features = ["test-support"] }
-settings = { workspace = true, features = ["test-support"] }
-theme = { workspace = true, features = ["test-support"] }
-util = { workspace = true, features = ["test-support"] }
-http_client = { workspace = true, features = ["test-support"] }
@@ -1 +0,0 @@
-../../LICENSE-GPL
@@ -1,146 +0,0 @@
-use serde::{Deserialize, Serialize};
-
-// Outbound messages
-#[derive(Debug, Serialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum OutboundMessage {
- StateUpdate(StateUpdateMessage),
- #[allow(dead_code)]
- UseFreeVersion,
- Logout,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct StateUpdateMessage {
- pub new_id: String,
- pub updates: Vec<StateUpdate>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum StateUpdate {
- FileUpdate(FileUpdateMessage),
- CursorUpdate(CursorPositionUpdateMessage),
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct FileUpdateMessage {
- pub path: String,
- pub content: String,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct CursorPositionUpdateMessage {
- pub path: String,
- pub offset: usize,
-}
-
-// Inbound messages coming in on stdout
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum ResponseItem {
- // A completion
- Text { text: String },
- // Vestigial message type from old versions -- safe to ignore
- Del { text: String },
- // Be able to delete whitespace prior to the cursor, likely for the rest of the completion
- Dedent { text: String },
- // When the completion is over
- End,
- // Got the closing parentheses and shouldn't show any more after
- Barrier,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SupermavenResponse {
- pub state_id: String,
- pub items: Vec<ResponseItem>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-pub struct SupermavenMetadataMessage {
- pub dust_strings: Option<Vec<String>>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-pub struct SupermavenTaskUpdateMessage {
- pub task: String,
- pub status: TaskStatus,
- pub percent_complete: Option<f32>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub enum TaskStatus {
- InProgress,
- Complete,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-pub struct SupermavenActiveRepoMessage {
- pub repo_simple_name: Option<String>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum SupermavenPopupAction {
- OpenUrl { label: String, url: String },
- NoOp { label: String },
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "snake_case")]
-pub struct SupermavenPopupMessage {
- pub message: String,
- pub actions: Vec<SupermavenPopupAction>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "camelCase")]
-pub struct ActivationRequest {
- pub activate_url: Option<String>,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SupermavenSetMessage {
- pub key: String,
- pub value: serde_json::Value,
-}
-
-#[derive(Clone, Debug, Serialize, Deserialize)]
-pub enum ServiceTier {
- FreeNoLicense,
- #[serde(other)]
- Unknown,
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(tag = "kind", rename_all = "snake_case")]
-pub enum SupermavenMessage {
- Response(SupermavenResponse),
- Metadata(SupermavenMetadataMessage),
- Apology {
- message: Option<String>,
- },
- ActivationRequest(ActivationRequest),
- ActivationSuccess,
- Passthrough {
- passthrough: Box<SupermavenMessage>,
- },
- Popup(SupermavenPopupMessage),
- TaskStatus(SupermavenTaskUpdateMessage),
- ActiveRepo(SupermavenActiveRepoMessage),
- ServiceTier {
- service_tier: ServiceTier,
- },
-
- Set(SupermavenSetMessage),
- #[serde(other)]
- Unknown,
-}
@@ -1,485 +0,0 @@
-mod messages;
-mod supermaven_edit_prediction_delegate;
-
-pub use supermaven_edit_prediction_delegate::*;
-
-use anyhow::{Context as _, Result};
-#[allow(unused_imports)]
-use client::{Client, proto};
-use collections::BTreeMap;
-
-use futures::{AsyncBufReadExt, StreamExt, channel::mpsc, io::BufReader};
-use gpui::{App, AsyncApp, Context, Entity, EntityId, Global, Task, WeakEntity, actions};
-use language::{
- Anchor, Buffer, BufferSnapshot, ToOffset, language_settings::all_language_settings,
-};
-use messages::*;
-use postage::watch;
-use serde::{Deserialize, Serialize};
-use settings::SettingsStore;
-use smol::io::AsyncWriteExt;
-use std::{path::PathBuf, sync::Arc};
-use ui::prelude::*;
-use util::ResultExt;
-use util::command::Child;
-use util::command::Stdio;
-
-actions!(
- supermaven,
- [
- /// Signs out of Supermaven.
- SignOut
- ]
-);
-
-pub fn init(client: Arc<Client>, cx: &mut App) {
- let supermaven = cx.new(|_| Supermaven::Starting);
- Supermaven::set_global(supermaven.clone(), cx);
-
- let mut provider = all_language_settings(None, cx).edit_predictions.provider;
- if provider == language::language_settings::EditPredictionProvider::Supermaven {
- supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
- }
-
- cx.observe_global::<SettingsStore>(move |cx| {
- let new_provider = all_language_settings(None, cx).edit_predictions.provider;
- if new_provider != provider {
- provider = new_provider;
- if provider == language::language_settings::EditPredictionProvider::Supermaven {
- supermaven.update(cx, |supermaven, cx| supermaven.start(client.clone(), cx));
- } else {
- supermaven.update(cx, |supermaven, _cx| supermaven.stop());
- }
- }
- })
- .detach();
-
- cx.on_action(|_: &SignOut, cx| {
- if let Some(supermaven) = Supermaven::global(cx) {
- supermaven.update(cx, |supermaven, _cx| supermaven.sign_out());
- }
- });
-}
-
-pub enum Supermaven {
- Starting,
- FailedDownload { error: anyhow::Error },
- Spawned(SupermavenAgent),
- Error { error: anyhow::Error },
-}
-
-#[derive(Clone)]
-pub enum AccountStatus {
- Unknown,
- NeedsActivation { activate_url: String },
- Ready,
-}
-
-#[derive(Clone)]
-struct SupermavenGlobal(Entity<Supermaven>);
-
-impl Global for SupermavenGlobal {}
-
-impl Supermaven {
- pub fn global(cx: &App) -> Option<Entity<Self>> {
- cx.try_global::<SupermavenGlobal>()
- .map(|model| model.0.clone())
- }
-
- pub fn set_global(supermaven: Entity<Self>, cx: &mut App) {
- cx.set_global(SupermavenGlobal(supermaven));
- }
-
- pub fn start(&mut self, client: Arc<Client>, cx: &mut Context<Self>) {
- if let Self::Starting = self {
- cx.spawn(async move |this, cx| {
- let binary_path =
- supermaven_api::get_supermaven_agent_path(client.http_client()).await?;
-
- this.update(cx, |this, cx| {
- if let Self::Starting = this {
- *this =
- Self::Spawned(SupermavenAgent::new(binary_path, client.clone(), cx)?);
- }
- anyhow::Ok(())
- })
- })
- .detach_and_log_err(cx)
- }
- }
-
- pub fn stop(&mut self) {
- *self = Self::Starting;
- }
-
- pub fn is_enabled(&self) -> bool {
- matches!(self, Self::Spawned { .. })
- }
-
- pub fn complete(
- &mut self,
- buffer: &Entity<Buffer>,
- cursor_position: Anchor,
- cx: &App,
- ) -> Option<SupermavenCompletion> {
- if let Self::Spawned(agent) = self {
- let buffer_id = buffer.entity_id();
- let buffer = buffer.read(cx);
- let path = buffer
- .file()
- .and_then(|file| Some(file.as_local()?.abs_path(cx)))
- .unwrap_or_else(|| PathBuf::from("untitled"))
- .to_string_lossy()
- .to_string();
- let content = buffer.text();
- let offset = cursor_position.to_offset(buffer);
- let state_id = agent.next_state_id;
- agent.next_state_id.0 += 1;
-
- let (updates_tx, mut updates_rx) = watch::channel();
- postage::stream::Stream::try_recv(&mut updates_rx).unwrap();
-
- agent.states.insert(
- state_id,
- SupermavenCompletionState {
- buffer_id,
- prefix_anchor: cursor_position,
- prefix_offset: offset,
- text: String::new(),
- dedent: String::new(),
- updates_tx,
- },
- );
- // ensure the states map is max 1000 elements
- if agent.states.len() > 1000 {
- // state id is monotonic so it's sufficient to remove the first element
- agent
- .states
- .remove(&agent.states.keys().next().unwrap().clone());
- }
-
- let _ = agent
- .outgoing_tx
- .unbounded_send(OutboundMessage::StateUpdate(StateUpdateMessage {
- new_id: state_id.0.to_string(),
- updates: vec![
- StateUpdate::FileUpdate(FileUpdateMessage {
- path: path.clone(),
- content,
- }),
- StateUpdate::CursorUpdate(CursorPositionUpdateMessage { path, offset }),
- ],
- }));
-
- Some(SupermavenCompletion {
- id: state_id,
- updates: updates_rx,
- })
- } else {
- None
- }
- }
-
- pub fn completion(
- &self,
- buffer: &Entity<Buffer>,
- cursor_position: Anchor,
- cx: &App,
- ) -> Option<&str> {
- if let Self::Spawned(agent) = self {
- find_relevant_completion(
- &agent.states,
- buffer.entity_id(),
- &buffer.read(cx).snapshot(),
- cursor_position,
- )
- } else {
- None
- }
- }
-
- pub fn sign_out(&mut self) {
- if let Self::Spawned(agent) = self {
- agent
- .outgoing_tx
- .unbounded_send(OutboundMessage::Logout)
- .ok();
- // The account status will get set to RequiresActivation or Ready when the next
- // message from the agent comes in. Until that happens, set the status to Unknown
- // to disable the button.
- agent.account_status = AccountStatus::Unknown;
- }
- }
-}
-
-fn find_relevant_completion<'a>(
- states: &'a BTreeMap<SupermavenCompletionStateId, SupermavenCompletionState>,
- buffer_id: EntityId,
- buffer: &BufferSnapshot,
- cursor_position: Anchor,
-) -> Option<&'a str> {
- let mut best_completion: Option<&str> = None;
- 'completions: for state in states.values() {
- if state.buffer_id != buffer_id {
- continue;
- }
- let Some(state_completion) = state.text.strip_prefix(&state.dedent) else {
- continue;
- };
-
- let current_cursor_offset = cursor_position.to_offset(buffer);
- if current_cursor_offset < state.prefix_offset {
- continue;
- }
-
- let original_cursor_offset = buffer.clip_offset(state.prefix_offset, text::Bias::Left);
- let text_inserted_since_completion_request: String = buffer
- .text_for_range(original_cursor_offset..current_cursor_offset)
- .collect();
- let trimmed_completion =
- match state_completion.strip_prefix(&text_inserted_since_completion_request) {
- Some(suffix) => suffix,
- None => continue 'completions,
- };
-
- if best_completion.is_some_and(|best| best.len() > trimmed_completion.len()) {
- continue;
- }
-
- best_completion = Some(trimmed_completion);
- }
- best_completion
-}
-
-pub struct SupermavenAgent {
- _process: Child,
- next_state_id: SupermavenCompletionStateId,
- states: BTreeMap<SupermavenCompletionStateId, SupermavenCompletionState>,
- outgoing_tx: mpsc::UnboundedSender<OutboundMessage>,
- _handle_outgoing_messages: Task<Result<()>>,
- _handle_incoming_messages: Task<Result<()>>,
- pub account_status: AccountStatus,
- service_tier: Option<ServiceTier>,
- #[allow(dead_code)]
- client: Arc<Client>,
-}
-
-impl SupermavenAgent {
- fn new(
- binary_path: PathBuf,
- client: Arc<Client>,
- cx: &mut Context<Supermaven>,
- ) -> Result<Self> {
- let mut process = util::command::new_command(&binary_path)
- .arg("stdio")
- .stdin(Stdio::piped())
- .stdout(Stdio::piped())
- .stderr(Stdio::piped())
- .kill_on_drop(true)
- .spawn()
- .context("failed to start the binary")?;
-
- let stdin = process
- .stdin
- .take()
- .context("failed to get stdin for process")?;
- let stdout = process
- .stdout
- .take()
- .context("failed to get stdout for process")?;
-
- let (outgoing_tx, outgoing_rx) = mpsc::unbounded();
-
- Ok(Self {
- _process: process,
- next_state_id: SupermavenCompletionStateId::default(),
- states: BTreeMap::default(),
- outgoing_tx,
- _handle_outgoing_messages: cx.spawn(async move |_, _cx| {
- Self::handle_outgoing_messages(outgoing_rx, stdin).await
- }),
- _handle_incoming_messages: cx.spawn(async move |this, cx| {
- Self::handle_incoming_messages(this, stdout, cx).await
- }),
- account_status: AccountStatus::Unknown,
- service_tier: None,
- client,
- })
- }
-
- async fn handle_outgoing_messages<W: smol::io::AsyncWrite + Unpin>(
- mut outgoing: mpsc::UnboundedReceiver<OutboundMessage>,
- mut stdin: W,
- ) -> Result<()> {
- while let Some(message) = outgoing.next().await {
- let bytes = serde_json::to_vec(&message)?;
- stdin.write_all(&bytes).await?;
- stdin.write_all(&[b'\n']).await?;
- }
- Ok(())
- }
-
- async fn handle_incoming_messages<R: smol::io::AsyncRead + Unpin>(
- this: WeakEntity<Supermaven>,
- stdout: R,
- cx: &mut AsyncApp,
- ) -> Result<()> {
- const MESSAGE_PREFIX: &str = "SM-MESSAGE ";
-
- let stdout = BufReader::new(stdout);
- let mut lines = stdout.lines();
- while let Some(line) = lines.next().await {
- let Some(line) = line.context("failed to read line from stdout").log_err() else {
- continue;
- };
- let Some(line) = line.strip_prefix(MESSAGE_PREFIX) else {
- continue;
- };
- let Some(message) = serde_json::from_str::<SupermavenMessage>(line)
- .with_context(|| format!("failed to deserialize line from stdout: {:?}", line))
- .log_err()
- else {
- continue;
- };
-
- this.update(cx, |this, _cx| {
- if let Supermaven::Spawned(this) = this {
- this.handle_message(message);
- }
- Task::ready(anyhow::Ok(()))
- })?
- .await?;
- }
-
- Ok(())
- }
-
- fn handle_message(&mut self, message: SupermavenMessage) {
- match message {
- SupermavenMessage::ActivationRequest(request) => {
- self.account_status = match request.activate_url {
- Some(activate_url) => AccountStatus::NeedsActivation { activate_url },
- None => AccountStatus::Ready,
- };
- }
- SupermavenMessage::ActivationSuccess => {
- self.account_status = AccountStatus::Ready;
- }
- SupermavenMessage::ServiceTier { service_tier } => {
- self.account_status = AccountStatus::Ready;
- self.service_tier = Some(service_tier);
- }
- SupermavenMessage::Response(response) => {
- let state_id = SupermavenCompletionStateId(response.state_id.parse().unwrap());
- if let Some(state) = self.states.get_mut(&state_id) {
- for item in &response.items {
- match item {
- ResponseItem::Text { text } => state.text.push_str(text),
- ResponseItem::Dedent { text } => state.dedent.push_str(text),
- _ => {}
- }
- }
- *state.updates_tx.borrow_mut() = ();
- }
- }
- SupermavenMessage::Passthrough { passthrough } => self.handle_message(*passthrough),
- _ => {
- log::warn!("unhandled message: {:?}", message);
- }
- }
- }
-}
-
-#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
-pub struct SupermavenCompletionStateId(usize);
-
-#[allow(dead_code)]
-pub struct SupermavenCompletionState {
- buffer_id: EntityId,
- prefix_anchor: Anchor,
- // prefix_offset is tracked independently because the anchor biases left which
- // doesn't allow us to determine if the prior text has been deleted.
- prefix_offset: usize,
- text: String,
- dedent: String,
- updates_tx: watch::Sender<()>,
-}
-
-pub struct SupermavenCompletion {
- pub id: SupermavenCompletionStateId,
- pub updates: watch::Receiver<()>,
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use collections::BTreeMap;
- use gpui::TestAppContext;
- use language::Buffer;
-
- #[gpui::test]
- async fn test_find_relevant_completion_no_first_letter_skip(cx: &mut TestAppContext) {
- let buffer = cx.new(|cx| Buffer::local("hello world", cx));
- let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
-
- let mut states = BTreeMap::new();
- let state_id = SupermavenCompletionStateId(1);
- let (updates_tx, _) = watch::channel();
-
- states.insert(
- state_id,
- SupermavenCompletionState {
- buffer_id: buffer.entity_id(),
- prefix_anchor: buffer_snapshot.anchor_before(0), // Start of buffer
- prefix_offset: 0,
- text: "hello".to_string(),
- dedent: String::new(),
- updates_tx,
- },
- );
-
- let cursor_position = buffer_snapshot.anchor_after(1);
-
- let result = find_relevant_completion(
- &states,
- buffer.entity_id(),
- &buffer_snapshot,
- cursor_position,
- );
-
- assert_eq!(result, Some("ello"));
- }
-
- #[gpui::test]
- async fn test_find_relevant_completion_with_multiple_chars(cx: &mut TestAppContext) {
- let buffer = cx.new(|cx| Buffer::local("hello world", cx));
- let buffer_snapshot = buffer.read_with(cx, |buffer, _| buffer.snapshot());
-
- let mut states = BTreeMap::new();
- let state_id = SupermavenCompletionStateId(1);
- let (updates_tx, _) = watch::channel();
-
- states.insert(
- state_id,
- SupermavenCompletionState {
- buffer_id: buffer.entity_id(),
- prefix_anchor: buffer_snapshot.anchor_before(0), // Start of buffer
- prefix_offset: 0,
- text: "hello".to_string(),
- dedent: String::new(),
- updates_tx,
- },
- );
-
- let cursor_position = buffer_snapshot.anchor_after(3);
-
- let result = find_relevant_completion(
- &states,
- buffer.entity_id(),
- &buffer_snapshot,
- cursor_position,
- );
-
- assert_eq!(result, Some("lo"));
- }
-}
@@ -1,303 +0,0 @@
-use crate::{Supermaven, SupermavenCompletionStateId};
-use anyhow::Result;
-use edit_prediction_types::{
- EditPrediction, EditPredictionDelegate, EditPredictionDiscardReason, EditPredictionIconSet,
-};
-use futures::StreamExt as _;
-use gpui::{App, Context, Entity, EntityId, Task};
-use language::{Anchor, Buffer, BufferSnapshot};
-use std::{
- ops::{AddAssign, Range},
- path::Path,
- sync::Arc,
- time::Duration,
-};
-use text::{ToOffset, ToPoint};
-use ui::prelude::*;
-use unicode_segmentation::UnicodeSegmentation;
-
-pub const DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
-
-pub struct SupermavenEditPredictionDelegate {
- supermaven: Entity<Supermaven>,
- buffer_id: Option<EntityId>,
- completion_id: Option<SupermavenCompletionStateId>,
- completion_text: Option<String>,
- file_extension: Option<String>,
- pending_refresh: Option<Task<Result<()>>>,
- completion_position: Option<language::Anchor>,
-}
-
-impl SupermavenEditPredictionDelegate {
- pub fn new(supermaven: Entity<Supermaven>) -> Self {
- Self {
- supermaven,
- buffer_id: None,
- completion_id: None,
- completion_text: None,
- file_extension: None,
- pending_refresh: None,
- completion_position: None,
- }
- }
-}
-
-// Computes the edit prediction from the difference between the completion text.
-// This is defined by greedily matching the buffer text against the completion text.
-// Inlays are inserted for parts of the completion text that are not present in the buffer text.
-// For example, given the completion text "axbyc" and the buffer text "xy", the rendered output in the editor would be "[a]x[b]y[c]".
-// The parts in brackets are the inlays.
-fn completion_from_diff(
- snapshot: BufferSnapshot,
- completion_text: &str,
- position: Anchor,
- delete_range: Range<Anchor>,
-) -> EditPrediction {
- let buffer_text = snapshot.text_for_range(delete_range).collect::<String>();
-
- let mut edits: Vec<(Range<language::Anchor>, Arc<str>)> = Vec::new();
-
- let completion_graphemes: Vec<&str> = completion_text.graphemes(true).collect();
- let buffer_graphemes: Vec<&str> = buffer_text.graphemes(true).collect();
-
- let mut offset = position.to_offset(&snapshot);
-
- let mut i = 0;
- let mut j = 0;
- while i < completion_graphemes.len() && j < buffer_graphemes.len() {
- // find the next instance of the buffer text in the completion text.
- let k = completion_graphemes[i..]
- .iter()
- .position(|c| *c == buffer_graphemes[j]);
- match k {
- Some(k) => {
- if k != 0 {
- let offset = snapshot.anchor_after(offset);
- // the range from the current position to item is an inlay.
- let edit = (
- offset..offset,
- completion_graphemes[i..i + k].join("").into(),
- );
- edits.push(edit);
- }
- i += k + 1;
- j += 1;
- offset.add_assign(buffer_graphemes[j - 1].len());
- }
- None => {
- // there are no more matching completions, so drop the remaining
- // completion text as an inlay.
- break;
- }
- }
- }
-
- if j == buffer_graphemes.len() && i < completion_graphemes.len() {
- let offset = snapshot.anchor_after(offset);
- // there is leftover completion text, so drop it as an inlay.
- let edit_range = offset..offset;
- let edit_text = completion_graphemes[i..].join("");
- edits.push((edit_range, edit_text.into()));
- }
-
- EditPrediction::Local {
- id: None,
- edits,
- cursor_position: None,
- edit_preview: None,
- }
-}
-
-impl EditPredictionDelegate for SupermavenEditPredictionDelegate {
- fn name() -> &'static str {
- "supermaven"
- }
-
- fn display_name() -> &'static str {
- "Supermaven"
- }
-
- fn show_predictions_in_menu() -> bool {
- true
- }
-
- fn show_tab_accept_marker() -> bool {
- true
- }
-
- fn supports_jump_to_edit() -> bool {
- false
- }
-
- fn icons(&self, _cx: &App) -> EditPredictionIconSet {
- EditPredictionIconSet::new(IconName::Supermaven)
- .with_disabled(IconName::SupermavenDisabled)
- .with_error(IconName::SupermavenError)
- }
-
- fn is_enabled(&self, _buffer: &Entity<Buffer>, _cursor_position: Anchor, cx: &App) -> bool {
- self.supermaven.read(cx).is_enabled()
- }
-
- fn is_refreshing(&self, _cx: &App) -> bool {
- self.pending_refresh.is_some() && self.completion_id.is_none()
- }
-
- fn refresh(
- &mut self,
- buffer_handle: Entity<Buffer>,
- cursor_position: Anchor,
- debounce: bool,
- cx: &mut Context<Self>,
- ) {
- // Only make new completion requests when debounce is true (i.e., when text is typed)
- // When debounce is false (i.e., cursor movement), we should not make new requests
- if !debounce {
- return;
- }
-
- reset_completion_cache(self, cx);
-
- let Some(mut completion) = self.supermaven.update(cx, |supermaven, cx| {
- supermaven.complete(&buffer_handle, cursor_position, cx)
- }) else {
- return;
- };
-
- self.pending_refresh = Some(cx.spawn(async move |this, cx| {
- if debounce {
- cx.background_executor().timer(DEBOUNCE_TIMEOUT).await;
- }
-
- while let Some(()) = completion.updates.next().await {
- this.update(cx, |this, cx| {
- // Get the completion text and cache it
- if let Some(text) =
- this.supermaven
- .read(cx)
- .completion(&buffer_handle, cursor_position, cx)
- {
- this.completion_text = Some(text.to_string());
-
- this.completion_position = Some(cursor_position);
- }
-
- this.completion_id = Some(completion.id);
- this.buffer_id = Some(buffer_handle.entity_id());
- this.file_extension = buffer_handle.read(cx).file().and_then(|file| {
- Some(
- Path::new(file.file_name(cx))
- .extension()?
- .to_str()?
- .to_string(),
- )
- });
- cx.notify();
- })?;
- }
- Ok(())
- }));
- }
-
- fn accept(&mut self, _cx: &mut Context<Self>) {
- reset_completion_cache(self, _cx);
- }
-
- fn discard(&mut self, _reason: EditPredictionDiscardReason, _cx: &mut Context<Self>) {
- reset_completion_cache(self, _cx);
- }
-
- fn suggest(
- &mut self,
- buffer: &Entity<Buffer>,
- cursor_position: Anchor,
- cx: &mut Context<Self>,
- ) -> Option<EditPrediction> {
- if self.buffer_id != Some(buffer.entity_id()) {
- return None;
- }
-
- if self.completion_id.is_none() {
- return None;
- }
-
- let completion_text = if let Some(cached_text) = &self.completion_text {
- cached_text.as_str()
- } else {
- let text = self
- .supermaven
- .read(cx)
- .completion(buffer, cursor_position, cx)?;
- self.completion_text = Some(text.to_string());
- text
- };
-
- // Check if the cursor is still at the same position as the completion request
- // If we don't have a completion position stored, don't show the completion
- if let Some(completion_position) = self.completion_position {
- if cursor_position != completion_position {
- return None;
- }
- } else {
- return None;
- }
-
- let completion_text = trim_to_end_of_line_unless_leading_newline(completion_text);
-
- let completion_text = completion_text.trim_end();
-
- if !completion_text.trim().is_empty() {
- let snapshot = buffer.read(cx).snapshot();
-
- // Calculate the range from cursor to end of line correctly
- let cursor_point = cursor_position.to_point(&snapshot);
- let end_of_line = snapshot.anchor_after(language::Point::new(
- cursor_point.row,
- snapshot.line_len(cursor_point.row),
- ));
- let delete_range = cursor_position..end_of_line;
-
- Some(completion_from_diff(
- snapshot,
- completion_text,
- cursor_position,
- delete_range,
- ))
- } else {
- None
- }
- }
-}
-
-fn reset_completion_cache(
- provider: &mut SupermavenEditPredictionDelegate,
- _cx: &mut Context<SupermavenEditPredictionDelegate>,
-) {
- provider.pending_refresh = None;
- provider.completion_id = None;
- provider.completion_text = None;
- provider.completion_position = None;
- provider.buffer_id = None;
-}
-
-fn trim_to_end_of_line_unless_leading_newline(text: &str) -> &str {
- if has_leading_newline(text) {
- text
- } else if let Some(i) = text.find('\n') {
- &text[..i]
- } else {
- text
- }
-}
-
-fn has_leading_newline(text: &str) -> bool {
- for c in text.chars() {
- if c == '\n' {
- return true;
- }
- if !c.is_whitespace() {
- return false;
- }
- }
- false
-}
@@ -1,23 +0,0 @@
-[package]
-name = "supermaven_api"
-version = "0.1.0"
-edition.workspace = true
-publish.workspace = true
-license = "GPL-3.0-or-later"
-
-[lints]
-workspace = true
-
-[lib]
-path = "src/supermaven_api.rs"
-doctest = false
-
-[dependencies]
-anyhow.workspace = true
-futures.workspace = true
-http_client.workspace = true
-paths.workspace = true
-serde.workspace = true
-serde_json.workspace = true
-smol.workspace = true
-util.workspace = true
@@ -1 +0,0 @@
-../../LICENSE-GPL
@@ -1,125 +0,0 @@
-use anyhow::{Context as _, Result};
-use futures::AsyncReadExt;
-use futures::io::BufReader;
-use http_client::{AsyncBody, HttpClient, Request as HttpRequest};
-use paths::supermaven_dir;
-use serde::Deserialize;
-use smol::fs::{self, File};
-use std::path::{Path, PathBuf};
-use std::sync::Arc;
-
-use util::fs::{make_file_executable, remove_matching};
-
-#[derive(Deserialize)]
-pub struct SupermavenApiError {
- pub message: String,
-}
-
-#[derive(Debug, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SupermavenDownloadResponse {
- pub download_url: String,
- pub version: u64,
- pub sha256_hash: String,
-}
-
-pub async fn latest_release(
- client: Arc<dyn HttpClient>,
- platform: &str,
- arch: &str,
-) -> Result<SupermavenDownloadResponse> {
- let uri = format!(
- "https://supermaven.com/api/download-path?platform={}&arch={}",
- platform, arch
- );
-
- // Download is not authenticated
- let request = HttpRequest::get(&uri);
-
- let mut response = client
- .send(request.body(AsyncBody::default())?)
- .await
- .with_context(|| "Unable to acquire Supermaven Agent".to_string())?;
-
- let mut body = Vec::new();
- response.body_mut().read_to_end(&mut body).await?;
-
- if response.status().is_client_error() || response.status().is_server_error() {
- let body_str = std::str::from_utf8(&body)?;
- let error: SupermavenApiError = serde_json::from_str(body_str)?;
- anyhow::bail!("Supermaven API error: {}", error.message);
- }
-
- serde_json::from_slice::<SupermavenDownloadResponse>(&body)
- .with_context(|| "Unable to parse Supermaven Agent response".to_string())
-}
-
-pub fn version_path(version: u64) -> PathBuf {
- supermaven_dir().join(format!(
- "sm-agent-{}{}",
- version,
- std::env::consts::EXE_SUFFIX
- ))
-}
-
-pub async fn has_version(version_path: &Path) -> bool {
- fs::metadata(version_path).await.is_ok_and(|m| m.is_file())
-}
-
-pub async fn get_supermaven_agent_path(client: Arc<dyn HttpClient>) -> Result<PathBuf> {
- fs::create_dir_all(supermaven_dir())
- .await
- .with_context(|| {
- format!(
- "Could not create Supermaven Agent Directory at {:?}",
- supermaven_dir()
- )
- })?;
-
- let platform = match std::env::consts::OS {
- "macos" => "darwin",
- "windows" => "windows",
- "linux" => "linux",
- unsupported => anyhow::bail!("unsupported platform {unsupported}"),
- };
-
- let arch = match std::env::consts::ARCH {
- "x86_64" => "amd64",
- "aarch64" => "arm64",
- unsupported => anyhow::bail!("unsupported architecture {unsupported}"),
- };
-
- let download_info = latest_release(client.clone(), platform, arch).await?;
-
- let binary_path = version_path(download_info.version);
-
- if has_version(&binary_path).await {
- // Due to an issue with the Supermaven binary not being made executable on
- // earlier Zed versions and Supermaven releases not occurring that frequently,
- // we ensure here that the found binary is actually executable.
- make_file_executable(&binary_path).await?;
-
- return Ok(binary_path);
- }
-
- let request = HttpRequest::get(&download_info.download_url);
-
- let mut response = client
- .send(request.body(AsyncBody::default())?)
- .await
- .with_context(|| "Unable to download Supermaven Agent".to_string())?;
-
- let mut file = File::create(&binary_path)
- .await
- .with_context(|| format!("Unable to create file at {:?}", binary_path))?;
-
- futures::io::copy(BufReader::new(response.body_mut()), &mut file)
- .await
- .with_context(|| format!("Unable to write binary to file at {:?}", binary_path))?;
-
- make_file_executable(&binary_path).await?;
-
- remove_matching(supermaven_dir(), |file| file != binary_path).await;
-
- Ok(binary_path)
-}
@@ -189,7 +189,6 @@ sidebar.workspace = true
smol.workspace = true
snippet_provider.workspace = true
snippets_ui.workspace = true
-supermaven.workspace = true
svg_preview.workspace = true
sysinfo.workspace = true
tab_switcher.workspace = true
@@ -638,7 +638,6 @@ fn main() {
);
copilot_ui::init(&app_state, cx);
- supermaven::init(app_state.client.clone(), cx);
language_model::init(app_state.client.clone(), cx);
language_models::init(app_state.user_store.clone(), app_state.client.clone(), cx);
acp_tools::init(cx);
@@ -4860,7 +4860,6 @@ mod tests {
"settings_profile_selector",
"snippets",
"stash_picker",
- "supermaven",
"svg",
"syntax_tree_view",
"tab_switcher",
@@ -12,7 +12,6 @@ use settings::{
EXPERIMENTAL_ZETA2_EDIT_PREDICTION_PROVIDER_NAME, EditPredictionPromptFormat, SettingsStore,
};
use std::{cell::RefCell, rc::Rc, sync::Arc};
-use supermaven::{Supermaven, SupermavenEditPredictionDelegate};
use ui::Window;
pub fn init(client: Arc<Client>, user_store: Entity<UserStore>, cx: &mut App) {
@@ -132,7 +131,6 @@ fn edit_prediction_provider_config_for_settings(cx: &App) -> Option<EditPredicti
match provider {
EditPredictionProvider::None => None,
EditPredictionProvider::Copilot => Some(EditPredictionProviderConfig::Copilot),
- EditPredictionProvider::Supermaven => Some(EditPredictionProviderConfig::Supermaven),
EditPredictionProvider::Zed => Some(EditPredictionProviderConfig::Zed(
EditPredictionModel::Zeta1,
)),
@@ -204,7 +202,6 @@ fn infer_prompt_format(model: &str) -> Option<EditPredictionPromptFormat> {
#[derive(Copy, Clone, PartialEq, Eq)]
enum EditPredictionProviderConfig {
Copilot,
- Supermaven,
Codestral,
Zed(EditPredictionModel),
}
@@ -213,7 +210,6 @@ impl EditPredictionProviderConfig {
fn name(&self) -> &'static str {
match self {
EditPredictionProviderConfig::Copilot => "Copilot",
- EditPredictionProviderConfig::Supermaven => "Supermaven",
EditPredictionProviderConfig::Codestral => "Codestral",
EditPredictionProviderConfig::Zed(model) => match model {
EditPredictionModel::Zeta1 => "Zeta1",
@@ -306,12 +302,6 @@ fn assign_edit_prediction_provider(
editor.set_edit_prediction_provider(Some(provider), window, cx);
}
}
- Some(EditPredictionProviderConfig::Supermaven) => {
- if let Some(supermaven) = Supermaven::global(cx) {
- let provider = cx.new(|_| SupermavenEditPredictionDelegate::new(supermaven));
- editor.set_edit_prediction_provider(Some(provider), window, cx);
- }
- }
Some(EditPredictionProviderConfig::Codestral) => {
let http_client = client.http_client();
let provider = cx.new(|_| CodestralEditPredictionDelegate::new(http_client));
@@ -28,7 +28,7 @@ The [Inline Assistant](./inline-assistant.md) works differently: select code or
[Edit Prediction](./edit-prediction.md) provides AI code completions on every keystroke. Each keypress sends a request to the prediction provider, which returns single or multi-line suggestions you accept with `tab`.
-The default provider is Zeta, Zed's open-source model trained on open data. You can also use GitHub Copilot, Supermaven, or Codestral.
+The default provider is Zeta, Zed's open-source model trained on open data. You can also use GitHub Copilot, or Codestral.
## Text threads
@@ -8,7 +8,7 @@ description: Zed's code completions from language servers and edit predictions.
Zed supports two sources for completions:
1. "Code Completions" provided by Language Servers (LSPs) automatically installed by Zed or via [Zed Language Extensions](languages.md).
-2. "Edit Predictions" provided by Zed's own Zeta model or by external providers like [GitHub Copilot](#github-copilot) or [Supermaven](#supermaven).
+2. "Edit Predictions" provided by Zed's own Zeta model or by external providers like [GitHub Copilot](#github-copilot).
## Language Server Code Completions {#code-completions}
@@ -1800,17 +1800,7 @@ While other options may be changed at a runtime and should be placed under `sett
}
```
-3. Use Supermaven as the edit prediction provider:
-
-```json [settings]
-{
- "edit_predictions": {
- "provider": "supermaven"
- }
-}
-```
-
-4. Turn off edit predictions across all providers
+3. Turn off edit predictions across all providers
```json [settings]
{