diff --git a/Cargo.lock b/Cargo.lock
index 02b27566e42f29eccd5b4a0ca145567e885cf36b..fc9e73aa110eef6820581a547ca8d14c8b1207f2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1113,7 +1113,6 @@ dependencies = [
"futures 0.3.25",
"gpui",
"image",
- "isahc",
"lazy_static",
"log",
"parking_lot 0.11.2",
@@ -1332,6 +1331,48 @@ dependencies = [
"theme",
]
+[[package]]
+name = "copilot"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-compression",
+ "async-tar",
+ "client",
+ "collections",
+ "context_menu",
+ "futures 0.3.25",
+ "gpui",
+ "language",
+ "log",
+ "lsp",
+ "node_runtime",
+ "serde",
+ "serde_derive",
+ "settings",
+ "smol",
+ "theme",
+ "util",
+ "workspace",
+]
+
+[[package]]
+name = "copilot_button"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "context_menu",
+ "copilot",
+ "editor",
+ "futures 0.3.25",
+ "gpui",
+ "settings",
+ "smol",
+ "theme",
+ "util",
+ "workspace",
+]
+
[[package]]
name = "core-foundation"
version = "0.9.3"
@@ -1932,6 +1973,7 @@ dependencies = [
"clock",
"collections",
"context_menu",
+ "copilot",
"ctor",
"db",
"drag_and_drop",
@@ -3910,6 +3952,23 @@ dependencies = [
"memoffset 0.6.5",
]
+[[package]]
+name = "node_runtime"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "async-compression",
+ "async-tar",
+ "futures 0.3.25",
+ "gpui",
+ "parking_lot 0.11.2",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "smol",
+ "util",
+]
+
[[package]]
name = "nom"
version = "7.1.1"
@@ -5882,6 +5941,7 @@ dependencies = [
"gpui",
"json_comments",
"postage",
+ "pretty_assertions",
"schemars",
"serde",
"serde_derive",
@@ -7500,11 +7560,15 @@ dependencies = [
"dirs 3.0.2",
"futures 0.3.25",
"git2",
+ "isahc",
"lazy_static",
"log",
"rand 0.8.5",
+ "serde",
"serde_json",
+ "smol",
"tempdir",
+ "url",
]
[[package]]
@@ -8460,6 +8524,8 @@ dependencies = [
"collections",
"command_palette",
"context_menu",
+ "copilot",
+ "copilot_button",
"ctor",
"db",
"diagnostics",
@@ -8486,6 +8552,7 @@ dependencies = [
"libc",
"log",
"lsp",
+ "node_runtime",
"num_cpus",
"outline",
"parking_lot 0.11.2",
diff --git a/Cargo.toml b/Cargo.toml
index 9f795992d5888d24ef083abe231ed1a4edd1a950..8fad52c8f4d9f2906baf4a3aa72a16e1a848f959 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -13,6 +13,8 @@ members = [
"crates/collections",
"crates/command_palette",
"crates/context_menu",
+ "crates/copilot",
+ "crates/copilot_button",
"crates/db",
"crates/diagnostics",
"crates/drag_and_drop",
@@ -35,6 +37,7 @@ members = [
"crates/lsp",
"crates/media",
"crates/menu",
+ "crates/node_runtime",
"crates/outline",
"crates/picker",
"crates/plugin",
diff --git a/assets/icons/copilot_16.svg b/assets/icons/copilot_16.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e14b61ce8bc73cc09242256706283e7e2831f8fb
--- /dev/null
+++ b/assets/icons/copilot_16.svg
@@ -0,0 +1,12 @@
+
diff --git a/assets/icons/copilot_disabled_16.svg b/assets/icons/copilot_disabled_16.svg
new file mode 100644
index 0000000000000000000000000000000000000000..eba36a2b692aca5841d5f3a8d131df980004fd9b
--- /dev/null
+++ b/assets/icons/copilot_disabled_16.svg
@@ -0,0 +1,9 @@
+
diff --git a/assets/icons/copilot_error_16.svg b/assets/icons/copilot_error_16.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6069c554f1da71202b57a541a7b15195287723c9
--- /dev/null
+++ b/assets/icons/copilot_error_16.svg
@@ -0,0 +1,7 @@
+
diff --git a/assets/icons/copilot_init_16.svg b/assets/icons/copilot_init_16.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6cbf63fb49324409a096df8d4c60e5ba6bd7a87d
--- /dev/null
+++ b/assets/icons/copilot_init_16.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/github-copilot-dummy.svg b/assets/icons/github-copilot-dummy.svg
new file mode 100644
index 0000000000000000000000000000000000000000..4a7ded397623c25fa0c5dda08d639230cd1327b6
--- /dev/null
+++ b/assets/icons/github-copilot-dummy.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/link_out_12.svg b/assets/icons/link_out_12.svg
new file mode 100644
index 0000000000000000000000000000000000000000..561f012452cd5a7a76ecbbc4cd608f6fe0912d06
--- /dev/null
+++ b/assets/icons/link_out_12.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/icons/zed_plus_copilot_32.svg b/assets/icons/zed_plus_copilot_32.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d024678c500640dc53eadeea0987e9c20070629b
--- /dev/null
+++ b/assets/icons/zed_plus_copilot_32.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/keymaps/default.json b/assets/keymaps/default.json
index adda80d9edbd19ff4021d3ee91b8d3b2acc7778a..1a8350bb536a6fb5a09f977e36de831e7e8745a2 100644
--- a/assets/keymaps/default.json
+++ b/assets/keymaps/default.json
@@ -176,7 +176,10 @@
{
"focus": false
}
- ]
+ ],
+ "alt-]": "copilot::NextSuggestion",
+ "alt-[": "copilot::PreviousSuggestion",
+ "alt-\\": "copilot::Toggle"
}
},
{
diff --git a/assets/settings/default.json b/assets/settings/default.json
index 7b775d6309d66b53784db02a428729c8aea25981..fbb52e00dca9f2ebc83e6eea42864a1dfb269d58 100644
--- a/assets/settings/default.json
+++ b/assets/settings/default.json
@@ -13,6 +13,11 @@
// The factor to grow the active pane by. Defaults to 1.0
// which gives the same size as all other panes.
"active_pane_magnification": 1.0,
+ // Enable / disable copilot integration.
+ "enable_copilot_integration": true,
+ // Controls whether copilot provides suggestion immediately
+ // or waits for a `copilot::Toggle`
+ "copilot": "on",
// Whether to enable vim modes and key bindings
"vim_mode": false,
// Whether to show the informational hover box when moving the mouse
@@ -120,7 +125,7 @@
// Settings specific to the terminal
"terminal": {
// What shell to use when opening a terminal. May take 3 values:
- // 1. Use the system's default terminal configuration (e.g. $TERM).
+ // 1. Use the system's default terminal configuration in /etc/passwd
// "shell": "system"
// 2. A program:
// "shell": {
@@ -200,7 +205,9 @@
// Different settings for specific languages.
"languages": {
"Plain Text": {
- "soft_wrap": "preferred_line_length"
+ "soft_wrap": "preferred_line_length",
+ // Copilot can be a little strange on non-code files
+ "copilot": "off"
},
"Elixir": {
"tab_size": 2
@@ -210,7 +217,9 @@
"hard_tabs": true
},
"Markdown": {
- "soft_wrap": "preferred_line_length"
+ "soft_wrap": "preferred_line_length",
+ // Copilot can be a little strange on non-code files
+ "copilot": "off"
},
"JavaScript": {
"tab_size": 2
@@ -223,6 +232,9 @@
},
"YAML": {
"tab_size": 2
+ },
+ "JSON": {
+ "copilot": "off"
}
},
// LSP Specific settings.
diff --git a/crates/auto_update/Cargo.toml b/crates/auto_update/Cargo.toml
index 8edb1957afcf13b0e01c078d27ad75335ad09a3d..6b11f5ddbc19672f4c90fc6687b17a53425f1ae4 100644
--- a/crates/auto_update/Cargo.toml
+++ b/crates/auto_update/Cargo.toml
@@ -22,8 +22,8 @@ anyhow = "1.0.38"
isahc = "1.7"
lazy_static = "1.4"
log = "0.4"
-serde = { version = "1.0", features = ["derive", "rc"] }
-serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
-serde_json = { version = "1.0", features = ["preserve_order"] }
+serde = { workspace = true }
+serde_derive = { workspace = true }
+serde_json = { workspace = true }
smol = "1.2.5"
tempdir = "0.3.7"
diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs
index 4272d7b1afa82ea1449fbd7f55ed79f2e3585a26..3ad3380d2619f1b562af9b4594919f6ce6ec20c6 100644
--- a/crates/auto_update/src/auto_update.rs
+++ b/crates/auto_update/src/auto_update.rs
@@ -1,8 +1,7 @@
mod update_notification;
use anyhow::{anyhow, Context, Result};
-use client::{http::HttpClient, ZED_SECRET_CLIENT_TOKEN};
-use client::{ZED_APP_PATH, ZED_APP_VERSION};
+use client::{ZED_APP_PATH, ZED_APP_VERSION, ZED_SECRET_CLIENT_TOKEN};
use db::kvp::KEY_VALUE_STORE;
use gpui::{
actions, platform::AppVersion, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
@@ -14,6 +13,7 @@ use smol::{fs::File, io::AsyncReadExt, process::Command};
use std::{ffi::OsString, sync::Arc, time::Duration};
use update_notification::UpdateNotification;
use util::channel::ReleaseChannel;
+use util::http::HttpClient;
use workspace::Workspace;
const SHOULD_SHOW_UPDATE_NOTIFICATION_KEY: &str = "auto-updater-should-show-updated-notification";
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index bf2e583d2cd56a6f49b07b3cb1f84d68be03fdcc..6b814941b8a25ef061dfba58a0ad47816b759036 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -17,8 +17,8 @@ anyhow = "1.0"
clap = { version = "3.1", features = ["derive"] }
dirs = "3.0"
ipc-channel = "0.16"
-serde = { version = "1.0", features = ["derive", "rc"] }
-serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
+serde = { workspace = true }
+serde_derive = { workspace = true }
[target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.9"
diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml
index cb6f29a42e5855d8d142c90fcadf5e5d5e5fe1c7..c75adf5bfa9857c06a80ad205cae22ee2603d634 100644
--- a/crates/client/Cargo.toml
+++ b/crates/client/Cargo.toml
@@ -23,7 +23,6 @@ async-recursion = "0.3"
async-tungstenite = { version = "0.16", features = ["async-tls"] }
futures = "0.3"
image = "0.23"
-isahc = "1.7"
lazy_static = "1.4.0"
log = { version = "0.4.16", features = ["kv_unstable_serde"] }
parking_lot = "0.11.1"
@@ -35,8 +34,8 @@ time = { version = "0.3", features = ["serde", "serde-well-known"] }
tiny_http = "0.8"
uuid = { version = "1.1.2", features = ["v4"] }
url = "2.2"
-serde = { version = "*", features = ["derive", "rc"] }
-serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
+serde = { workspace = true }
+serde_derive = { workspace = true }
settings = { path = "../settings" }
tempfile = "3"
diff --git a/crates/client/src/client.rs b/crates/client/src/client.rs
index 86d6bc9912c74e1e8f2efcaec0fc0b5532bcdaa9..bb39b0669989d55b121bc455d891f72a20dbd480 100644
--- a/crates/client/src/client.rs
+++ b/crates/client/src/client.rs
@@ -1,7 +1,6 @@
#[cfg(any(test, feature = "test-support"))]
pub mod test;
-pub mod http;
pub mod telemetry;
pub mod user;
@@ -18,7 +17,6 @@ use gpui::{
AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AnyWeakViewHandle, AppContext, AppVersion,
AsyncAppContext, Entity, ModelHandle, MutableAppContext, Task, View, ViewContext, ViewHandle,
};
-use http::HttpClient;
use lazy_static::lazy_static;
use parking_lot::RwLock;
use postage::watch;
@@ -41,6 +39,7 @@ use telemetry::Telemetry;
use thiserror::Error;
use url::Url;
use util::channel::ReleaseChannel;
+use util::http::HttpClient;
use util::{ResultExt, TryFutureExt};
pub use rpc::*;
@@ -130,7 +129,7 @@ pub enum EstablishConnectionError {
#[error("{0}")]
Other(#[from] anyhow::Error),
#[error("{0}")]
- Http(#[from] http::Error),
+ Http(#[from] util::http::Error),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
@@ -1396,10 +1395,11 @@ pub fn decode_worktree_url(url: &str) -> Option<(u64, String)> {
#[cfg(test)]
mod tests {
use super::*;
- use crate::test::{FakeHttpClient, FakeServer};
+ use crate::test::FakeServer;
use gpui::{executor::Deterministic, TestAppContext};
use parking_lot::Mutex;
use std::future;
+ use util::http::FakeHttpClient;
#[gpui::test(iterations = 10)]
async fn test_reconnection(cx: &mut TestAppContext) {
diff --git a/crates/client/src/http.rs b/crates/client/src/http.rs
deleted file mode 100644
index 0757cebf3ad5d836edbd59f47a03cbab02c0c211..0000000000000000000000000000000000000000
--- a/crates/client/src/http.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-pub use anyhow::{anyhow, Result};
-use futures::future::BoxFuture;
-use isahc::{
- config::{Configurable, RedirectPolicy},
- AsyncBody,
-};
-pub use isahc::{
- http::{Method, Uri},
- Error,
-};
-use smol::future::FutureExt;
-use std::{sync::Arc, time::Duration};
-pub use url::Url;
-
-pub type Request = isahc::Request;
-pub type Response = isahc::Response;
-
-pub trait HttpClient: Send + Sync {
- fn send(&self, req: Request) -> BoxFuture>;
-
- fn get<'a>(
- &'a self,
- uri: &str,
- body: AsyncBody,
- follow_redirects: bool,
- ) -> BoxFuture<'a, Result> {
- let request = isahc::Request::builder()
- .redirect_policy(if follow_redirects {
- RedirectPolicy::Follow
- } else {
- RedirectPolicy::None
- })
- .method(Method::GET)
- .uri(uri)
- .body(body);
- match request {
- Ok(request) => self.send(request),
- Err(error) => async move { Err(error.into()) }.boxed(),
- }
- }
-}
-
-pub fn client() -> Arc {
- Arc::new(
- isahc::HttpClient::builder()
- .connect_timeout(Duration::from_secs(5))
- .low_speed_timeout(100, Duration::from_secs(5))
- .build()
- .unwrap(),
- )
-}
-
-impl HttpClient for isahc::HttpClient {
- fn send(&self, req: Request) -> BoxFuture> {
- Box::pin(async move { self.send_async(req).await })
- }
-}
diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs
index 9d486619d255dd7ab214a145f7f31162dd4a9c36..7ee099dfabf8f67256e7cd945ff7981c4cd5d3e7 100644
--- a/crates/client/src/telemetry.rs
+++ b/crates/client/src/telemetry.rs
@@ -1,11 +1,9 @@
-use crate::http::HttpClient;
use db::kvp::KEY_VALUE_STORE;
use gpui::{
executor::Background,
serde_json::{self, value::Map, Value},
AppContext, Task,
};
-use isahc::Request;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use serde::Serialize;
@@ -19,6 +17,7 @@ use std::{
time::{Duration, SystemTime, UNIX_EPOCH},
};
use tempfile::NamedTempFile;
+use util::http::HttpClient;
use util::{channel::ReleaseChannel, post_inc, ResultExt, TryFutureExt};
use uuid::Uuid;
@@ -220,10 +219,10 @@ impl Telemetry {
"App": true
}),
}])?;
- let request = Request::post(MIXPANEL_ENGAGE_URL)
- .header("Content-Type", "application/json")
- .body(json_bytes.into())?;
- this.http_client.send(request).await?;
+
+ this.http_client
+ .post_json(MIXPANEL_ENGAGE_URL, json_bytes.into())
+ .await?;
anyhow::Ok(())
}
.log_err(),
@@ -316,10 +315,9 @@ impl Telemetry {
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, &events)?;
- let request = Request::post(MIXPANEL_EVENTS_URL)
- .header("Content-Type", "application/json")
- .body(json_bytes.into())?;
- this.http_client.send(request).await?;
+ this.http_client
+ .post_json(MIXPANEL_EVENTS_URL, json_bytes.into())
+ .await?;
anyhow::Ok(())
}
.log_err(),
diff --git a/crates/client/src/test.rs b/crates/client/src/test.rs
index db9e0d8c487b27a7474373af9d2c25a29e04b9d7..4c12a205660f7932a6a7b412c6ee686a6199372c 100644
--- a/crates/client/src/test.rs
+++ b/crates/client/src/test.rs
@@ -1,16 +1,14 @@
-use crate::{
- http::{self, HttpClient, Request, Response},
- Client, Connection, Credentials, EstablishConnectionError, UserStore,
-};
+use crate::{Client, Connection, Credentials, EstablishConnectionError, UserStore};
use anyhow::{anyhow, Result};
-use futures::{future::BoxFuture, stream::BoxStream, Future, StreamExt};
+use futures::{stream::BoxStream, StreamExt};
use gpui::{executor, ModelHandle, TestAppContext};
use parking_lot::Mutex;
use rpc::{
proto::{self, GetPrivateUserInfo, GetPrivateUserInfoResponse},
ConnectionId, Peer, Receipt, TypedEnvelope,
};
-use std::{fmt, rc::Rc, sync::Arc};
+use std::{rc::Rc, sync::Arc};
+use util::http::FakeHttpClient;
pub struct FakeServer {
peer: Arc,
@@ -219,46 +217,3 @@ impl Drop for FakeServer {
self.disconnect();
}
}
-
-pub struct FakeHttpClient {
- handler: Box<
- dyn 'static
- + Send
- + Sync
- + Fn(Request) -> BoxFuture<'static, Result>,
- >,
-}
-
-impl FakeHttpClient {
- pub fn create(handler: F) -> Arc
- where
- Fut: 'static + Send + Future