Compare commits

...

9 Commits

Author SHA1 Message Date
Marshall Bowers
2f030e3b9a assistant: Add implementation for /delta argument completion (#19693)
This PR fixes a panic that could occur when trying to complete arguments
for the `/delta` slash command.

We were using `unimplemented!()` instead of providing a default no-op
implementation like we do for other slash commands that do not support
completing arguments.

Closes https://github.com/zed-industries/zed/issues/19686.

Release Notes:

- Fixed a panic that could occur when trying to complete arguments with
the `/delta` command.
2024-10-24 13:40:31 -04:00
Peter Tripp
391243da0a zed 0.159.1 2024-10-24 13:13:02 -04:00
Danilo Leal
80da78b450 ssh: Capitalize error and connection strings (#19675)
Another tiny PR for the sake of consistency :)

Release Notes:

- N/A
2024-10-24 11:00:05 -04:00
Thorsten Ball
3b3477c5a1 ssh remoting: Fix wrong working directory for SSH terminals (#19672)
Before this change, we would save the working directory *on the client*
of each shell that was running in a terminal.

While it's technically right, it's wrong in all of these cases where
`working_directory` was used:

- in inline assistant
- when resolving file paths in the terminal output
- when serializing the current working dir and deserializing it on
restart

Release Notes:

- Fixed terminals opened on remote hosts failing to deserialize with an
error message after restarting Zed.
2024-10-24 10:59:59 -04:00
Thorsten Ball
8e80ce8430 ssh remoting: Fix version check (#19668)
This snuck in when Bennet and I were debugging why our connection to the
SSH host would break. We suspected that somewhere something was logging
to STDOUT and, I guess, we changed all `println!` to `eprintln!`.

Now, two weeks later, I'm sitting here, wondering why the version check
doesn't work anymore. The server always reports a version of `""`.

Turns out we take the command's STDOUT and not STDERR, which is correct.

But it also turns out we started to print the version to STDERR, which
breaks the version check.

One-character bug & one-character fix.

Release Notes:

- N/A
2024-10-24 10:59:53 -04:00
Kirill Bulatov
1b1872666c Use zstd without dynamic linking due to musl usage (#19627)
Due to leaning towards `musl` builds, unit features for `zstd` and link
it statically too for Zed.


bfe1e34f59/zstd-safe/zstd-sys/build.rs (L260)
shows that `ZSTD_SYS_USE_PKG_CONFIG` env var can be used to return this
behavior.

Release Notes:

- N/A
2024-10-24 10:59:47 -04:00
Peter Tripp
ac5cb8b969 Switch to Anthropic -latest tags (#19615)
- Closes: https://github.com/zed-industries/zed/issues/19609

Switches us to using `-latest` tags with Anthropic models instead of
pinning to a specific date version.
See: [Anthropic Model
Docs](https://docs.anthropic.com/en/docs/about-claude/models)

This is a no-op for:
- Claude 3 Opus (`claude-3-opus-20240229`)
- Claude 3 Sonnet (`claude-3-sonnet-20240229`)
- Claude 3 Haiku (`claude-3-haiku-20240307`)

For Claude 3.5 Sonnet this will update us from
`claude-3-5-sonnet-20240620` to `claude-3-5-sonnet-20241022`. We will
also pickup any subsequent model updates automatically when Anthropic
updates the `latest` tag.

This matches the behavior for OpenAI where use `gpt-4o` as the
model_name and not `gpt-4o-2024-08-06`.
2024-10-24 10:52:39 -04:00
Antonio Scandurra
c4060fe075 Fix crash in collab when sending worktree updates (#19678)
This pull request does a couple of things:

- In 29c2df73e1, we introduced a safety
guard that prevents this crash from happening again in the future by
returning an error instead of panicking when the payload is too large.
- In 3e7a2e5c30, we introduced chunking
for updates coming from SSH servers (previously, we were sending the
whole changeset and initial set of paths in their entirety).
- In 122b5b4, we introduced a panic hook that sends panics to Axiom.

For posterity, this is how we figured out what the panic was:

```
kubectl logs current-pod-name --previous --namespace=production
```

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
Co-authored-by: Bennet <bennet@zed.dev>
Co-authored-by: Kirill <kirill@zed.dev>
2024-10-24 15:58:58 +02:00
Joseph T. Lyons
ca336567ef v0.159.x preview 2024-10-23 13:12:16 -04:00
17 changed files with 102 additions and 59 deletions

3
Cargo.lock generated
View File

@@ -14601,7 +14601,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.159.0"
version = "0.159.1"
dependencies = [
"activity_indicator",
"anyhow",
@@ -14709,7 +14709,6 @@ dependencies = [
"winresource",
"workspace",
"zed_actions",
"zstd",
]
[[package]]

View File

@@ -29,13 +29,13 @@ pub struct AnthropicModelCacheConfiguration {
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, EnumIter)]
pub enum Model {
#[default]
#[serde(rename = "claude-3-5-sonnet", alias = "claude-3-5-sonnet-20240620")]
#[serde(rename = "claude-3-5-sonnet", alias = "claude-3-5-sonnet-latest")]
Claude3_5Sonnet,
#[serde(rename = "claude-3-opus", alias = "claude-3-opus-20240229")]
#[serde(rename = "claude-3-opus", alias = "claude-3-opus-latest")]
Claude3Opus,
#[serde(rename = "claude-3-sonnet", alias = "claude-3-sonnet-20240229")]
#[serde(rename = "claude-3-sonnet", alias = "claude-3-sonnet-latest")]
Claude3Sonnet,
#[serde(rename = "claude-3-haiku", alias = "claude-3-haiku-20240307")]
#[serde(rename = "claude-3-haiku", alias = "claude-3-haiku-latest")]
Claude3Haiku,
#[serde(rename = "custom")]
Custom {
@@ -69,10 +69,10 @@ impl Model {
pub fn id(&self) -> &str {
match self {
Model::Claude3_5Sonnet => "claude-3-5-sonnet-20240620",
Model::Claude3Opus => "claude-3-opus-20240229",
Model::Claude3Sonnet => "claude-3-sonnet-20240229",
Model::Claude3Haiku => "claude-3-haiku-20240307",
Model::Claude3_5Sonnet => "claude-3-5-sonnet-latest",
Model::Claude3Opus => "claude-3-opus-latest",
Model::Claude3Sonnet => "claude-3-sonnet-latest",
Model::Claude3Haiku => "claude-3-haiku-latest",
Self::Custom { name, .. } => name,
}
}

View File

@@ -1,5 +1,5 @@
use crate::slash_command::file_command::{FileCommandMetadata, FileSlashCommand};
use anyhow::Result;
use anyhow::{anyhow, Result};
use assistant_slash_command::{
ArgumentCompletion, SlashCommand, SlashCommandOutput, SlashCommandOutputSection,
};
@@ -37,7 +37,7 @@ impl SlashCommand for DeltaSlashCommand {
_workspace: Option<WeakView<Workspace>>,
_cx: &mut WindowContext,
) -> Task<Result<Vec<ArgumentCompletion>>> {
unimplemented!()
Task::ready(Err(anyhow!("this command does not require argument")))
}
fn run(

View File

@@ -272,6 +272,16 @@ impl Database {
update: &proto::UpdateWorktree,
connection: ConnectionId,
) -> Result<TransactionGuard<Vec<ConnectionId>>> {
if update.removed_entries.len() > proto::MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE
|| update.updated_entries.len() > proto::MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE
{
return Err(anyhow!(
"invalid worktree update. removed entries: {}, updated entries: {}",
update.removed_entries.len(),
update.updated_entries.len()
))?;
}
let project_id = ProjectId::from_proto(update.project_id);
let worktree_id = update.worktree_id as i64;
self.project_transaction(project_id, |tx| async move {

View File

@@ -84,6 +84,8 @@ async fn main() -> Result<()> {
let config = envy::from_env::<Config>().expect("error loading config");
init_tracing(&config);
init_panic_hook();
let mut app = Router::new()
.route("/", get(handle_root))
.route("/healthz", get(handle_liveness_probe))
@@ -378,3 +380,20 @@ pub fn init_tracing(config: &Config) -> Option<()> {
None
}
fn init_panic_hook() {
std::panic::set_hook(Box::new(move |panic_info| {
let panic_message = match panic_info.payload().downcast_ref::<&'static str>() {
Some(message) => *message,
None => match panic_info.payload().downcast_ref::<String>() {
Some(message) => message.as_str(),
None => "Box<Any>",
},
};
let backtrace = std::backtrace::Backtrace::force_capture();
let location = panic_info
.location()
.map(|loc| format!("{}:{}", loc.file(), loc.line()));
tracing::error!(panic = true, ?location, %panic_message, %backtrace, "Server Panic");
}));
}

View File

@@ -1713,11 +1713,6 @@ fn notify_rejoined_projects(
for project in rejoined_projects {
for worktree in mem::take(&mut project.worktrees) {
#[cfg(any(test, feature = "test-support"))]
const MAX_CHUNK_SIZE: usize = 2;
#[cfg(not(any(test, feature = "test-support")))]
const MAX_CHUNK_SIZE: usize = 256;
// Stream this worktree's entries.
let message = proto::UpdateWorktree {
project_id: project.id.to_proto(),
@@ -1731,7 +1726,7 @@ fn notify_rejoined_projects(
updated_repositories: worktree.updated_repositories,
removed_repositories: worktree.removed_repositories,
};
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
for update in proto::split_worktree_update(message) {
session.peer.send(session.connection_id, update.clone())?;
}
@@ -2195,11 +2190,6 @@ fn join_project_internal(
})?;
for (worktree_id, worktree) in mem::take(&mut project.worktrees) {
#[cfg(any(test, feature = "test-support"))]
const MAX_CHUNK_SIZE: usize = 2;
#[cfg(not(any(test, feature = "test-support")))]
const MAX_CHUNK_SIZE: usize = 256;
// Stream this worktree's entries.
let message = proto::UpdateWorktree {
project_id: project_id.to_proto(),
@@ -2213,7 +2203,7 @@ fn join_project_internal(
updated_repositories: worktree.repository_entries.into_values().collect(),
removed_repositories: Default::default(),
};
for update in proto::split_worktree_update(message, MAX_CHUNK_SIZE) {
for update in proto::split_worktree_update(message) {
session.peer.send(session.connection_id, update.clone())?;
}

View File

@@ -40,7 +40,7 @@ pub struct AnthropicSettings {
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AvailableModel {
/// The model's name in the Anthropic API. e.g. claude-3-5-sonnet-20240620
/// The model's name in the Anthropic API. e.g. claude-3-5-sonnet-latest, claude-3-opus-20240229, etc
pub name: String,
/// The model's name in Zed's UI, such as in the model selector dropdown menu in the assistant panel.
pub display_name: Option<String>,

View File

@@ -240,6 +240,7 @@ impl Project {
settings.cursor_shape.unwrap_or_default(),
settings.alternate_scroll,
settings.max_scroll_history_lines,
ssh_details.is_some(),
window,
completion_tx,
cx,

View File

@@ -630,10 +630,12 @@ impl From<Nonce> for u128 {
}
}
pub fn split_worktree_update(
mut message: UpdateWorktree,
max_chunk_size: usize,
) -> impl Iterator<Item = UpdateWorktree> {
#[cfg(any(test, feature = "test-support"))]
pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 2;
#[cfg(not(any(test, feature = "test-support")))]
pub const MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE: usize = 256;
pub fn split_worktree_update(mut message: UpdateWorktree) -> impl Iterator<Item = UpdateWorktree> {
let mut done_files = false;
let mut repository_map = message
@@ -647,13 +649,19 @@ pub fn split_worktree_update(
return None;
}
let updated_entries_chunk_size = cmp::min(message.updated_entries.len(), max_chunk_size);
let updated_entries_chunk_size = cmp::min(
message.updated_entries.len(),
MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
);
let updated_entries: Vec<_> = message
.updated_entries
.drain(..updated_entries_chunk_size)
.collect();
let removed_entries_chunk_size = cmp::min(message.removed_entries.len(), max_chunk_size);
let removed_entries_chunk_size = cmp::min(
message.removed_entries.len(),
MAX_WORKTREE_UPDATE_MAX_CHUNK_SIZE,
);
let removed_entries = message
.removed_entries
.drain(..removed_entries_chunk_size)

View File

@@ -527,7 +527,7 @@ impl SshClientDelegate {
.await
.map_err(|e| {
anyhow!(
"failed to get remote server binary download url (os: {}, arch: {}): {}",
"Failed to get remote server binary download url (os: {}, arch: {}): {}",
platform.os,
platform.arch,
e
@@ -542,7 +542,7 @@ impl SshClientDelegate {
version,
))
} else {
self.update_status(Some("checking for latest version of remote server"), cx);
self.update_status(Some("Checking for latest version of remote server"), cx);
let binary_path = AutoUpdater::get_latest_remote_server_release(
platform.os,
platform.arch,
@@ -552,7 +552,7 @@ impl SshClientDelegate {
.await
.map_err(|e| {
anyhow!(
"failed to download remote server binary (os: {}, arch: {}): {}",
"Failed to download remote server binary (os: {}, arch: {}): {}",
platform.os,
platform.arch,
e
@@ -579,7 +579,7 @@ impl SshClientDelegate {
.output()
.await?;
if !output.status.success() {
Err(anyhow!("failed to run command: {:?}", command))?;
Err(anyhow!("Failed to run command: {:?}", command))?;
}
Ok(())
}

View File

@@ -72,7 +72,7 @@ fn main() {
}
},
Some(Commands::Version) => {
eprintln!("{}", env!("ZED_PKG_VERSION"));
println!("{}", env!("ZED_PKG_VERSION"));
std::process::exit(0);
}
None => {

View File

@@ -330,6 +330,7 @@ impl TerminalBuilder {
cursor_shape: CursorShape,
alternate_scroll: AlternateScroll,
max_scroll_history_lines: Option<usize>,
is_ssh_terminal: bool,
window: AnyWindowHandle,
completion_tx: Sender<()>,
cx: &AppContext,
@@ -469,6 +470,7 @@ impl TerminalBuilder {
url_regex: RegexSearch::new(URL_REGEX).unwrap(),
word_regex: RegexSearch::new(WORD_REGEX).unwrap(),
vi_mode_enabled: false,
is_ssh_terminal,
};
Ok(TerminalBuilder {
@@ -626,6 +628,7 @@ pub struct Terminal {
word_regex: RegexSearch,
task: Option<TaskState>,
vi_mode_enabled: bool,
is_ssh_terminal: bool,
}
pub struct TaskState {
@@ -734,10 +737,6 @@ impl Terminal {
self.selection_phase == SelectionPhase::Selecting
}
pub fn get_cwd(&self) -> Option<PathBuf> {
self.pty_info.current.as_ref().map(|info| info.cwd.clone())
}
///Takes events from Alacritty and translates them to behavior on this view
fn process_terminal_event(
&mut self,
@@ -951,7 +950,7 @@ impl Terminal {
} else {
MaybeNavigationTarget::PathLike(PathLikeTarget {
maybe_path: maybe_url_or_path,
terminal_dir: self.get_cwd(),
terminal_dir: self.working_directory(),
})
};
cx.emit(Event::Open(target));
@@ -1006,7 +1005,7 @@ impl Terminal {
} else {
MaybeNavigationTarget::PathLike(PathLikeTarget {
maybe_path: word,
terminal_dir: self.get_cwd(),
terminal_dir: self.working_directory(),
})
};
cx.emit(Event::NewNavigationTarget(Some(navigation_target)));
@@ -1636,6 +1635,23 @@ impl Terminal {
}
pub fn working_directory(&self) -> Option<PathBuf> {
if self.is_ssh_terminal {
// We can't yet reliably detect the working directory of a shell on the
// SSH host. Until we can do that, it doesn't make sense to display
// the working directory on the client and persist that.
None
} else {
self.client_side_working_directory()
}
}
/// Returns the working directory of the process that's connected to the PTY.
/// That means it returns the working directory of the local shell or program
/// that's running inside the terminal.
///
/// This does *not* return the working directory of the shell that runs on the
/// remote host, in case Zed is connected to a remote host.
fn client_side_working_directory(&self) -> Option<PathBuf> {
self.pty_info
.current
.as_ref()

View File

@@ -1192,7 +1192,7 @@ impl SerializableItem for TerminalView {
return None;
}
if let Some((cwd, workspace_id)) = terminal.get_cwd().zip(self.workspace_id) {
if let Some((cwd, workspace_id)) = terminal.working_directory().zip(self.workspace_id) {
Some(cx.background_executor().spawn(async move {
TERMINAL_DB
.save_working_directory(item_id, workspace_id, cwd)

View File

@@ -36,7 +36,10 @@ use postage::{
prelude::{Sink as _, Stream as _},
watch,
};
use rpc::{proto, AnyProtoClient};
use rpc::{
proto::{self, split_worktree_update},
AnyProtoClient,
};
pub use settings::WorktreeId;
use settings::{Settings, SettingsLocation, SettingsStore};
use smallvec::{smallvec, SmallVec};
@@ -1721,11 +1724,6 @@ impl LocalWorktree {
F: 'static + Send + Fn(proto::UpdateWorktree) -> Fut,
Fut: Send + Future<Output = bool>,
{
#[cfg(any(test, feature = "test-support"))]
const MAX_CHUNK_SIZE: usize = 2;
#[cfg(not(any(test, feature = "test-support")))]
const MAX_CHUNK_SIZE: usize = 256;
if let Some(observer) = self.update_observer.as_mut() {
*observer.resume_updates.borrow_mut() = ();
return;
@@ -1751,7 +1749,7 @@ impl LocalWorktree {
snapshot.build_update(project_id, worktree_id, entry_changes, repo_changes);
}
for update in proto::split_worktree_update(update, MAX_CHUNK_SIZE) {
for update in proto::split_worktree_update(update) {
let _ = resume_updates_rx.try_recv();
loop {
let result = callback(update.clone());
@@ -1817,13 +1815,17 @@ impl RemoteWorktree {
self.update_observer = Some(tx);
cx.spawn(|this, mut cx| async move {
let mut update = initial_update;
loop {
'outer: loop {
// SSH projects use a special project ID of 0, and we need to
// remap it to the correct one here.
update.project_id = project_id;
if !callback(update).await {
break;
for chunk in split_worktree_update(update) {
if !callback(chunk).await {
break 'outer;
}
}
if let Some(next_update) = rx.next().await {
update = next_update;
} else {

View File

@@ -2,7 +2,7 @@
description = "The fast, collaborative code editor."
edition = "2021"
name = "zed"
version = "0.159.0"
version = "0.159.1"
publish = false
license = "GPL-3.0-or-later"
authors = ["Zed Team <hi@zed.dev>"]
@@ -125,8 +125,6 @@ winresource = "0.1"
[target.'cfg(target_os = "linux")'.dependencies]
ashpd.workspace = true
# We don't use zstd in the zed crate, but we want to add this feature when compiling a desktop build of Zed
zstd = { workspace = true, features = [ "pkg-config" ] }
[dev-dependencies]
call = { workspace = true, features = ["test-support"] }

View File

@@ -1 +1 @@
dev
preview

View File

@@ -49,8 +49,8 @@ You can add custom models to the Anthropic provider by adding the following to y
"anthropic": {
"available_models": [
{
"name": "some-model",
"display_name": "some-model",
"name": "claude-3-5-sonnet-20240620",
"display_name": "Sonnet 2024-June",
"max_tokens": 128000,
"max_output_tokens": 2560,
"cache_configuration": {