Compare commits

...

235 Commits

Author SHA1 Message Date
Nate Butler
5caf6eb041 Clean up unused 2024-10-15 17:02:38 -04:00
Nate Butler
879f850f4f tidy 2024-10-15 16:01:49 -04:00
Nate Butler
e6e72f9f2d rename dismiss 2024-10-15 15:20:33 -04:00
Nate Butler
30d91429e7 IT WORKS 2024-10-15 15:09:14 -04:00
Nate Butler
e255389cbe DON'T MERGE THIS 2024-10-13 21:05:39 -04:00
Nate Butler
eeba056b84 wip - panic! 2024-10-13 21:05:29 -04:00
Nate Butler
f2338025b7 ui_feedback -> alert_dialog 2024-10-13 20:15:52 -04:00
Nate Butler
e29f4e6632 wip 2024-10-11 22:28:05 -04:00
Nate Butler
dd6f0dfc04 📎
Co-Authored-By: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2024-10-11 12:28:09 -04:00
Nate Butler
a84eb44564 Allow showing dialog in a modal
Co-Authored-By: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-Authored-By: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2024-10-11 12:25:37 -04:00
Nate Butler
bd1e57bd4a Update typography.rs 2024-10-11 12:24:20 -04:00
Nate Butler
cd811a2014 Remove checkbox for now 2024-10-11 09:59:02 -04:00
Nate Butler
74a5f6a464 Implement Display for Selection
Useful for debugging selected states
2024-10-11 09:53:48 -04:00
Nate Butler
c916f5d476 wip 2024-10-11 09:47:39 -04:00
Nate Butler
43ddcdef84 Pass on_click through alert dialog actions 2024-10-11 08:35:45 -04:00
Nate Butler
be6d13b6d8 Add alert_dialog 2024-10-10 21:31:14 -04:00
Henry Chu
eea600ecc3 Fix macOS App shortcut (#18921)
- The App Shortcuts in macOS System Settings does not work for Zed since the menu items titles were not set.
- Previously you could set a shortcut for `Zoom`.
- This add support for `Window->Zoom` as well.
2024-10-10 13:08:46 -04:00
Peter Tripp
3c6989323f docs: Add XML (#19026)
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-10 12:56:39 -04:00
renovate[bot]
596d8b2fe3 Update Rust crate wasmtime to v24.0.1 [SECURITY] (#18944)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [wasmtime](https://redirect.github.com/bytecodealliance/wasmtime) |
workspace.dependencies | patch | `24.0.0` -> `24.0.1` |

### GitHub Vulnerability Alerts

####
[CVE-2024-47763](https://redirect.github.com/bytecodealliance/wasmtime/security/advisories/GHSA-q8hx-mm92-4wvg)

### Impact

Wasmtime's implementation of WebAssembly tail calls combined with stack
traces can result in a runtime crash in certain WebAssembly modules. The
runtime crash may be undefined behavior if Wasmtime was compiled with
Rust 1.80 or prior. The runtime crash is a deterministic process abort
when Wasmtime is compiled with Rust 1.81 and later.

[WebAssembly tail
calls](https://redirect.github.com/webassembly/tail-call) are a proposal
which relatively recently reached stage 4 in the [standardization
process](https://redirect.github.com/WebAssembly/proposals/). Wasmtime
first enabled support for tail calls by default [in Wasmtime
21.0.0](https://redirect.github.com/bytecodealliance/wasmtime/pull/8540),
although that release contained a bug where it was only on-by-default
for some configurations. In [Wasmtime
22.0.0](https://redirect.github.com/bytecodealliance/wasmtime/pull/8682)
tail calls were enabled by default for all configurations.

The specific crash happens when an exported function in a WebAssembly
module (or component) performs a `return_call` (or
`return_call_indirect` or `return_call_ref`) to an imported host
function which captures a stack trace (for example, the host function
raises a trap). In this situation, the stack-walking code previously
assumed there was always at least one WebAssembly frame on the stack but
with tail calls that is no longer true. With the tail-call proposal it's
possible to have an entry trampoline appear as if it directly called the
exit trampoline. This situation triggers an internal assert in the
stack-walking code which raises a Rust `panic!()`.

When Wasmtime is compiled with Rust versions 1.80 and prior this means
that an `extern "C"` function in Rust is raising a `panic!()`. This is
technically undefined behavior and typically manifests as a process
abort when the unwinder fails to unwind Cranelift-generated frames. When
Wasmtime is compiled with Rust versions 1.81 and later this panic
becomes a deterministic process abort.

Overall the impact of this issue is that this is a denial-of-service
vector where a malicious WebAssembly module or component can cause the
host to crash. There is no other impact at this time other than
availability of a service as the result of the crash is always a crash
and no more.

This issue was discovered by routine fuzzing performed by the Wasmtime
project via Google's OSS-Fuzz infrastructure. We have no evidence that
it has ever been exploited by an attacker in the wild.

### Patches

All versions of Wasmtime which have tail calls enabled by default have
been patched:

* 21.0.x - patched in 21.0.2
* 22.0.x - patched in 22.0.1
* 23.0.x - patched in 23.0.3 
* 24.0.x - patched in 24.0.1
* 25.0.x - patched in 25.0.2

Wasmtime versions from 12.0.x (the first release with experimental tail
call support) to 20.0.x (the last release with tail-calls
off-by-default) have support for tail calls but the support is disabled
by default. These versions are not affected in their default
configurations, but users who explicitly enabled tail call support will
need to either disable tail call support or upgrade to a patched version
of Wasmtime.

### Workarounds

The main workaround for this issue is to disable tail support for tail
calls in Wasmtime, for example with
[`Config::wasm_tail_call(false)`](https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#method.wasm_tail_call).
Users are otherwise encouraged to upgrade to patched versions.

### References

* [Wasmtime's initial implementation of tail
calls](https://redirect.github.com/bytecodealliance/wasmtime/pull/6774)
* [Enabling of tail calls in
21.0.0](https://redirect.github.com/bytecodealliance/wasmtime/pull/8540)
* [Fully enabling tail calls in
22.0.0](https://redirect.github.com/bytecodealliance/wasmtime/pull/8682)
* [The WebAssembly's `tail-call`
proposal](https://redirect.github.com/webassembly/tail-call)

####
[CVE-2024-47813](https://redirect.github.com/bytecodealliance/wasmtime/security/advisories/GHSA-7qmx-3fpx-r45m)

### Impact

Under certain concurrent event orderings, a `wasmtime::Engine`'s
internal type registry was susceptible to double-unregistration bugs due
to a race condition, leading to panics and potentially type registry
corruption. That registry corruption could, following an additional and
particular sequence of concurrent events, lead to violations of
WebAssembly's control-flow integrity (CFI) and type safety. Users that
do not use `wasmtime::Engine` across multiple threads are not affected.
Users that only create new modules across threads over time are
additionally not affected.

Reproducing this bug requires creating and dropping multiple type
instances (such as `wasmtime::FuncType` or `wasmtime::ArrayType`)
concurrently on multiple threads, where all types are associated with
the same `wasmtime::Engine`. **Wasm guests cannot trigger this bug.**
See the "References" section below for a list of Wasmtime types-related
APIs that are affected.

Wasmtime maintains an internal registry of types within a
`wasmtime::Engine` and an engine is shareable across threads. Types can
be created and referenced through creation of a `wasmtime::Module`,
creation of `wasmtime::FuncType`, or a number of other APIs where the
host creates a function (see "References" below). Each of these cases
interacts with an engine to deduplicate type information and manage type
indices that are used to implement type checks in WebAssembly's
`call_indirect` function, for example. This bug is a race condition in
this management where the internal type registry could be corrupted to
trigger an assert or contain invalid state.

Wasmtime's internal representation of a type has individual types (e.g.
one-per-host-function) maintain a registration count of how many time
it's been used. Types additionally have state within an engine behind a
read-write lock such as lookup/deduplication information. The race here
is a time-of-check versus time-of-use (TOCTOU) bug where one thread
atomically decrements a type entry's registration count, observes zero
registrations, and then acquires a lock in order to unregister that
entry. However, between when this first thread observed the
zero-registration count and when it acquires that lock, another thread
could perform the following sequence of events: re-register another copy
of the type, which deduplicates to that same entry, resurrecting it and
incrementing its registration count; then drop the type and decrement
its registration count; observe that the registration count is now zero;
acquire the type registry lock; and finally unregister the type. Now,
when the original thread finally acquires the lock and unregisters the
entry, it is the second time this entry has been unregistered.

| Thread A                          | Thread B                       |
|-----------------------------------|--------------------------------|
| `acquire(type registry lock)`     |                                |
|                                   | `decref(E) --> 0`              |
|                                   | `block_on(type registry lock)` |
| `register(E') == incref(E) --> 1` |                                |
| `release(type registry lock)`     |                                |
| `decref(E) --> 0`                 |                                |
| `acquire(type registry lock)`     |                                |
| `unregister(E)`                   |                                |
| `release(type registry lock)`     |                                |
|                                   | `acquire(type registry lock)`  |
|                                   | `unregister(E)`          |

This double-unregistration could then lead to a WebAssembly CFI
violation under the following conditions: a new WebAssembly module `X`
was loaded into the engine before the second, buggy unregistration
occurs; `X` defined a function type `F` that was allocated in the same
type registry slot where the original entry was allocated; the second,
buggy unregistration incorrectly unregistered `F`; another new
WebAssembly module `Y` was loaded into the engine; `Y` defined a
function type `G`, different from `F`, but which is also allocated in
the same type registry slot; a `funcref` of type `G` is created, either
by the host or by Wasm; that `funcref` is passed to a WebAssembly
instance of module `X`; that instance performs a `call_indirect` to that
`funcref`; the `call_indirect`'s dynamic type check, which preserves
CFI, could incorrectly pass in this case, because `F` and `G` were
assigned the same type registry slot. This would, ultimately, allow
calling a function with too many, too few, or wrongly-typed arguments,
violating CFI and type safety.

We were not able to reproduce this CFI violation in a vanilla Wasmtime
build, although it remains theoretically possible. However, by modifying
Wasmtime's source code to make losing the races described above more
likely (by disabling certain assertions, inserting panic catches, and
adding retry loops in a few places if we did *not* lose the race) we
were able to incorrectly get a `funcref` to pass a type check that it
should have failed, which would allow the CFI violation.

### Patches

This bug was originally introduced in Wasmtime 19's development of the
WebAssembly GC proposal. This bug affects users who are not using the GC
proposal, however, and affects Wasmtime in its default configuration
even when the GC proposal is disabled. Wasmtime users using 19.0.0 and
after are all affected by this issue. We have released the following
Wasmtime versions, all of which have a fix for this bug:

* 21.0.2
* 22.0.1
* 23.0.3
* 24.0.1
* 25.0.2

### Workarounds

If your application creates and drops Wasmtime types on multiple threads
concurrently, there are no known workarounds. Users are encouraged to
upgrade to a patched release.

### References

The following APIs create or drop types, and therefore are affected by
this race condition if performed on multiple threads concurrently and
are all associated with the same `wasmtime::Engine`:

*
[`wasmtime::FuncType::new`](https://docs.rs/wasmtime/latest/wasmtime/struct.FuncType.html#method.new)
* Also reachable from creation of
[`wasmtime::Func`](https://docs.rs/wasmtime/latest/wasmtime/struct.Func.html)
* Also reachable from
[`wasmtime::Linker::func_*`](https://docs.rs/wasmtime/latest/wasmtime/struct.Linker.html#method.func_new)
*
[`wasmtime::ArrayType::new`](https://docs.rs/wasmtime/latest/wasmtime/struct.ArrayType.html#method.new)
*
[`wasmtime::StructType::new`](https://docs.rs/wasmtime/latest/wasmtime/struct.StructType.html#method.new)
*
[`wasmtime::Func::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Func.html#method.ty)
*
[`wasmtime::Global::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Global.html#method.ty)
*
[`wasmtime::Table::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Table.html#method.ty)
*
[`wasmtime::Extern::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Extern.html#method.ty)
*
[`wasmtime::Export::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Export.html#method.ty)
*
[`wasmtime::UnknownImportError::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.UnknownImportError.html#method.ty)
*
[`wasmtime::ImportType::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.ImportType.html#method.ty)
*
[`wasmtime::ExportType::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.ExportType.html#method.ty)
*
[`wasmtime::Val::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Val.html#method.ty)
*
[`wasmtime::Ref::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.Ref.html#method.ty)
*
[`wasmtime::AnyRef::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.AnyRef.html#method.ty)
*
[`wasmtime::EqRef::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.EqRef.html#method.ty)
*
[`wasmtime::ArrayRef::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.ArrayRef.html#method.ty)
*
[`wasmtime::StructRef::ty`](https://docs.rs/wasmtime/latest/wasmtime/struct.StructRef.html#method.ty)
* Dropping a
[`wasmtime::FuncType`](https://docs.rs/wasmtime/latest/wasmtime/struct.FuncType.html)
* Dropping a
[`wasmtime::ArrayType`](https://docs.rs/wasmtime/latest/wasmtime/struct.ArrayType.html)
* Dropping a
[`wasmtime::StructType`](https://docs.rs/wasmtime/latest/wasmtime/struct.StructType.html)
* Dropping a
[`wasmtime::ExternType`](https://docs.rs/wasmtime/latest/wasmtime/struct.ExternType.html)
* Dropping a
[`wasmtime::GlobalType`](https://docs.rs/wasmtime/latest/wasmtime/struct.GlobalType.html)
* Dropping a
[`wasmtime::TableType`](https://docs.rs/wasmtime/latest/wasmtime/struct.TableType.html)
* Dropping a
[`wasmtime::ValType`](https://docs.rs/wasmtime/latest/wasmtime/struct.ValType.html)
* Dropping a
[`wasmtime::RefType`](https://docs.rs/wasmtime/latest/wasmtime/struct.RefType.html)
* Dropping a
[`wasmtime::HeapType`](https://docs.rs/wasmtime/latest/wasmtime/struct.HeapType.html)
* Dropping a
[`wasmtime::UnknownImportError`](https://docs.rs/wasmtime/latest/wasmtime/struct.UnknownImportError.html)
* Dropping a
[`wasmtime::Linker`](https://docs.rs/wasmtime/latest/wasmtime/struct.Linker.html)

The change which introduced this bug was
[#&#8203;7969](https://redirect.github.com/bytecodealliance/wasmtime/pull/7969)

---

### Release Notes

<details>
<summary>bytecodealliance/wasmtime (wasmtime)</summary>

###
[`v24.0.1`](https://redirect.github.com/bytecodealliance/wasmtime/releases/tag/v24.0.1)

[Compare
Source](https://redirect.github.com/bytecodealliance/wasmtime/compare/v24.0.0...v24.0.1)

#### 24.0.1

Released 2024-10-09.

##### Fixed

- Fix a runtime crash when combining tail-calls with host imports that
capture a
    stack trace or trap.

[GHSA-q8hx-mm92-4wvg](https://redirect.github.com/bytecodealliance/wasmtime/security/advisories/GHSA-q8hx-mm92-4wvg)

- Fix a race condition could lead to WebAssembly control-flow integrity
and type
    safety violations.

[GHSA-7qmx-3fpx-r45m](https://redirect.github.com/bytecodealliance/wasmtime/security/advisories/GHSA-7qmx-3fpx-r45m)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "" in timezone America/New_York,
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 09:48:02 -04:00
Kirill Bulatov
9bc4e3b4ae Do not resolve more completion fields (#19021)
As Zed instantly shows completion items in the completion menu, and the
resolve will cause the details to appear, flickering.
We can safely resolve the `documentation`, `additionalTextEdits` and
`command` fields, the rest should be resolved eagerly for now.

Release Notes:

- Fixed completion menu rendering
2024-10-10 16:10:18 +03:00
Peter Schilling
972886c29e Automatically indent JSX (#18816)
indents jsx in a way that is [consistent with
html](https://github.com/zed-industries/zed/blob/main/extensions/html/languages/html/indents.scm)

before, no automatic indentation would apply and it would even dedent
you when you add a line above the cursor (shift-o in vim mode)


https://github.com/user-attachments/assets/470fbdb2-3e31-42c4-b535-bb26ae1706ab


after, it applies automatic indentation when you hit return


https://github.com/user-attachments/assets/e86c739d-370d-490d-8c6f-d0190e65f832



Closes #16127

Release Notes:

- Improved automatic indentation behavior in JSX
([#16127](https://github.com/zed-industries/zed/issues/16127))
2024-10-10 15:15:12 +03:00
renovate[bot]
d2b4fa20ef Update actions/upload-artifact digest to 604373d (#18941)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[actions/upload-artifact](https://redirect.github.com/actions/upload-artifact)
| action | digest | `5076954` -> `604373d` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:50:52 +03:00
Kevin Wang
21c27cecba Track cursor offset before bias in Supermaven completion provider (#18858)
Track the cursor offset before biasing in the Supermaven completion
provider to better determine if the text should be suggested. The
underlying issue here is due to the way anchor biasing works, the
completion provider is not able to determine if a given suggestion's
cursor location no longer exists as it is always coalesced to a correct
location (specifically, the end of the line).

This change updates that logic so the offset is stored independently of
the buffer so it can be used to represent a location that may not exist
in the buffer anymore to represent locations that have been deleted.

The net effect is that suggestions can be backspaced much more cleanly
with Supermaven.


![image](https://github.com/user-attachments/assets/ff61aa09-54ea-4cad-b1ca-633a08bcdd96)


![image](https://github.com/user-attachments/assets/b49e2d6b-f1d3-41a1-9b75-c4bc3ac5f85b)

Release Notes:

- Improves https://github.com/zed-industries/zed/issues/17981 to prevent
suggesting completions based on out-of-date cursor locations.
2024-10-10 14:39:20 +03:00
renovate[bot]
4de05d18ed Update Rust crate ashpd to v0.9.2 (#18950)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ashpd](https://redirect.github.com/bilelmoussaoui/ashpd) |
workspace.dependencies | patch | `0.9.1` -> `0.9.2` |

---

### Release Notes

<details>
<summary>bilelmoussaoui/ashpd (ashpd)</summary>

###
[`v0.9.2`](https://redirect.github.com/bilelmoussaoui/ashpd/releases/tag/0.9.2)

[Compare
Source](https://redirect.github.com/bilelmoussaoui/ashpd/compare/0.9.1...0.9.2)

#### What's Changed

- [desktop: Make trait SessionPortal
public](0d2dad594e)
- [lib: Add Pid
type](96b27e7069)
- [desktop/game_mode: Use i32 for
pid](336917a4ed)
- [desktop/device: Use Pid type for
pids](c05b3c17f8)
- [flatpak: Use Pid type for
pids](55a6ea0c9d)
- [is_sandboxed: Don't unwrap OnceCell
set](5d3cb41707)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:15:59 +03:00
renovate[bot]
8c9a05b2a8 Update Rust crate proc-macro2 to v1.0.87 (#18957)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [proc-macro2](https://redirect.github.com/dtolnay/proc-macro2) |
dependencies | patch | `1.0.86` -> `1.0.87` |

---

### Release Notes

<details>
<summary>dtolnay/proc-macro2 (proc-macro2)</summary>

###
[`v1.0.87`](https://redirect.github.com/dtolnay/proc-macro2/releases/tag/1.0.87)

[Compare
Source](https://redirect.github.com/dtolnay/proc-macro2/compare/1.0.86...1.0.87)

- Check valid punctuation character in `Punct::new`
([#&#8203;470](https://redirect.github.com/dtolnay/proc-macro2/issues/470))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:11:32 +03:00
renovate[bot]
348e317695 Update Rust crate ipc-channel to v0.18.3 (#18663)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [ipc-channel](https://redirect.github.com/servo/ipc-channel) |
dependencies | patch | `0.18.2` -> `0.18.3` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:10:56 +03:00
renovate[bot]
281c60f12d Update Rust crate async-compression to v0.4.13 (#18655)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[async-compression](https://redirect.github.com/Nullus157/async-compression)
| workspace.dependencies | patch | `0.4.12` -> `0.4.13` |

---

### Release Notes

<details>
<summary>Nullus157/async-compression (async-compression)</summary>

###
[`v0.4.13`](https://redirect.github.com/Nullus157/async-compression/blob/HEAD/CHANGELOG.md#0413---2024-10-02)

[Compare
Source](https://redirect.github.com/Nullus157/async-compression/compare/v0.4.12...v0.4.13)

##### Feature

-   Update `brotli` dependency to to `7`.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:10:45 +03:00
renovate[bot]
6859482020 Update Rust crate emojis to v0.6.4 (#18661)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [emojis](https://redirect.github.com/rossmacarthur/emojis) |
workspace.dependencies | patch | `0.6.3` -> `0.6.4` |

---

### Release Notes

<details>
<summary>rossmacarthur/emojis (emojis)</summary>

###
[`v0.6.4`](https://redirect.github.com/rossmacarthur/emojis/compare/0.6.3...0.6.4)

[Compare
Source](https://redirect.github.com/rossmacarthur/emojis/compare/0.6.3...0.6.4)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-10 14:10:35 +03:00
张小白
7c306a5a0e gpui: Fix window display on Windows (#18705)
- Closes #18610


This PR addresses the same issue as PR #18578. After a full day of
research and testing, I believe I’ve found the best solution to resolve
this issue. With this PR, the window creation behavior on Windows
becomes more consistent with macOS:

- When `params.show` is `true`: The window is created and immediately
displayed.
- When `params.show` is `false`: The window is created but remains
hidden until the first call to `activate_window`.

As I mentioned in #18578, `winit` creates hidden windows by setting the
window's `exstyle` to `WS_EX_NOACTIVATE | WS_EX_TRANSPARENT |
WS_EX_LAYERED | WS_EX_TOOLWINDOW`, which is different from the method
used in this PR. Here, the window is created with normal parameters, but
we do not call `ShowWindow` so the window is not shown.

I'm not sure why `winit` doesn't use a smilliar approach like this PR to
create hidden windows. My guess is that `winit` is creating this hidden
window to function as a "DispatchWindow" — serving a purpose similar to
`WindowsPlatform` in `zed`. To ensure the window stays hidden even if
`ShowWindow` is called, they use the `exstyle` approach.

With the method used in this PR, my initial tests haven't revealed any
issues.



Release Notes:

- N/A
2024-10-10 14:09:50 +03:00
Thorsten Ball
b75532fad7 ssh remote: Handle disconnect on project and show overlay (#19014)
Demo:



https://github.com/user-attachments/assets/e5edf8f3-8c15-482e-a792-6eb619f83de4


Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
2024-10-10 12:59:09 +02:00
Shish
e3ff2ced79 [terminal] Consider "main.cs(20,5)" to be a single clickable word (#19004)
[terminal] Consider "main.cs(20,5)" to be a single clickable word

First, adding unit tests for the regexes because I'm not certain how
these regexes are _intended_ to work, and unit tests work nicely as
demonstrations of intended behaviour.

The comment string, and the regex itself, seem to imply that
"main.cs(20,5)" is supposed be a single "word" (for the purposes of
being clicked on)... but the regex doesn't actually work like that. This
PR makes it work :)

(I don't know _why_ "word with an optional `(\d+,\d+)` on the end"
doesn't match the full string, while "word with a required `(\d+,\d+)`
on the end" _does_ match the full string - aren't regexes supposed to
match as much as possible, so it should take the optional extra whenever
the extra exists? Either way, "word with a required (\d+,\d+), or word
by itself" has the correct behaviour, as demonstrated by the unit test)

Release Notes:

- N/A
2024-10-10 13:56:48 +03:00
Kirill Bulatov
5841ac406d Fix the completions being too slow (#19013)
Closes https://github.com/zed-industries/zed/issues/19005

Release Notes:

- Fixed completion items inserted with a delay
([#19005](https://github.com/zed-industries/zed/issues/19005))

---------

Co-authored-by: Antonio Scandurra <antonio@zed.dev>
2024-10-10 12:53:02 +03:00
Piotr Osiewicz
f6f5ad138d project panel: Make intermediate folded directories clickable (#18956)
- Closes: https://github.com/zed-industries/zed/issues/18770


Release Notes:

- Intermediate auto-folded project panel entries are now clickable.
2024-10-10 11:15:46 +02:00
Thorsten Ball
db50467bbc remote ssh: Show connection status in tooltip (#19006)
Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2024-10-10 10:49:02 +02:00
Cody
fe1078ef68 Add basic vi motion support for terminal (#18715)
Closes #7417

Release Notes:

- Added basic support for Alacritty's [vi
mode](https://github.com/alacritty/alacritty/blob/master/docs/features.md#vi-mode)
to the built-in terminal (which is using Alacritty under the hood.) The
vi mode can be activated with `ctrl-shift-space` and then supports some
basic motions to navigate through the terminal's scrollback buffer.

## Details

Leverages existing selection functionality from mouse_drag and the
ViMotion API of alacritty to add basic vi motions in the terminal.
Please note, this is only basic functionality (move, select, and yank to
system clipboard) and not a fully functional vim environment (e.g.
search, configurable keybindings, and paste). I figured this would be an
interim solution to the long term, more fleshed out, solution proposed
by @mrnugget.

Ctrl+Shift+Space to enter Vi mode while in the terminal (Same default
binding in alacritty)
2024-10-10 07:50:12 +02:00
Max Brunsfeld
5cf4ac16d6 Don't disable auto-indent when typing in multi buffers (#18984)
Release Notes:

- Fixed a bug where auto-indent was not enabled while typing in
multi-buffers
2024-10-09 20:41:58 -07:00
Joseph T Lyons
05b2010db5 Use uv 2024-10-09 23:02:41 -04:00
Joseph T. Lyons
d8484c57e1 Use uv (#18997)
Release Notes:

- N/A
2024-10-09 22:53:01 -04:00
Joseph T Lyons
fcfd769b39 Delete close_unlabeled_issues.yml
I'm going to write something more robust using PyGitHub.
2024-10-09 22:27:10 -04:00
Joseph T Lyons
285fb51771 Move label data to a data file so multiple scripts can reference them 2024-10-09 22:11:04 -04:00
Joseph T. Lyons
ed484ecf5f Run action to close unlabeled issues every hour (#18995)
Release Notes:

- N/A
2024-10-09 21:39:30 -04:00
Joseph T. Lyons
ab34342664 Close unlabeled issues (#18992)
Release Notes:

- N/A
2024-10-09 21:35:20 -04:00
Max Brunsfeld
53cc82b132 Fix some issues with branch buffers (#18945)
* `Open Excerpts` command always opens the locations in the base buffer
* LSP features like document-highlights, go-to-def, and inlay hints work
correctly in branch buffers
* Other LSP features like completions, code actions, and rename are
disabled in branch buffers

Release Notes:

- N/A
2024-10-09 16:55:25 -07:00
Marshall Bowers
cae548a50d collab: Fix issues with syncing LLM usage to Stripe (#18970)
This PR fixes some issues with our previous approach to synching LLM
usage over to Stripe.

We now have a separate LLM access price in Stripe that is a marker price
to allow us to create the initial subscription with that as its
subscription item

We then dynamically set the LLM usage price during the reconciliation
sync based on the usage for the current month.

Release Notes:

- N/A

---------

Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Richard <richard@zed.dev>
2024-10-09 19:15:38 -04:00
Marshall Bowers
69711660ab collab: Make LLM billing fields required in LlmTokenClaims (#18959)
This PR makes the `has_llm_subscription` and
`max_monthly_spend_in_cents` fields in the `LlmTokenClaims` required.

This change will be safe to deploy in ~45 minutes.

Release Notes:

- N/A
2024-10-09 18:42:22 -04:00
renovate[bot]
b2e1572820 Update actions/checkout digest to eef6144 (#18940)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [actions/checkout](https://redirect.github.com/actions/checkout) |
action | digest | `692973e` -> `eef6144` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 18:24:10 -04:00
renovate[bot]
66ea96839a Update Rust crate clap to v4.5.20 (#18953)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.19` -> `4.5.20` |

---

### Release Notes

<details>
<summary>clap-rs/clap (clap)</summary>

###
[`v4.5.20`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4520---2024-10-08)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.19...v4.5.20)

##### Features

-   *(unstable)* Add `CommandExt`

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 17:49:21 -04:00
Marshall Bowers
3db789ed90 collab: Include max monthly spend preference in LLM token (#18955)
This PR updates the LLM token claims to include the maximum monthly
spend.

Release Notes:

- N/A
2024-10-09 17:39:34 -04:00
renovate[bot]
99a6a3d5e3 Update cloudflare/wrangler-action digest to 9681c29 (#18949)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cloudflare/wrangler-action](https://redirect.github.com/cloudflare/wrangler-action)
| action | digest | `168bc28` -> `9681c29` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xMTQuMCIsInVwZGF0ZWRJblZlciI6IjM4LjExNC4wIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-09 17:19:11 -04:00
Marshall Bowers
d316577fd5 collab: Add billing preferences for maximum LLM monthly spend (#18948)
This PR adds a new `billing_preferences` table.

Right now there is a single preference: the maximum monthly spend for
LLM usage.

Release Notes:

- N/A

---------

Co-authored-by: Richard <richard@zed.dev>
2024-10-09 16:29:07 -04:00
Kirill Bulatov
711180981b Tone down model summarization logs (#18943)
Release Notes:

- N/A
2024-10-09 22:39:54 +03:00
Kirill Bulatov
49c75eb062 Rework remote task synchronization (#18746)
Reworks the way tasks are stored, accessed and synchronized in the
`project`.
Now both collab and ssh remote projects use the same TaskStorage kind to
get the task context from the remote host, and worktree task templates
are synchronized along with other worktree settings.

Release Notes:

- Adds ssh support to tasks, improves collab-remote projects' tasks sync
2024-10-09 22:28:42 +03:00
Marshall Bowers
f1053ff525 collab: Clarify naming around free tier spending limits (#18936)
This PR renames the `MONTHLY_SPENDING_LIMIT` constant to
`FREE_TIER_MONTHLY_SPENDING_LIMIT` to clarify it.

This will help distinguish it from the user's specified limit on their
paid monthly spending.

Release Notes:

- N/A
2024-10-09 15:05:53 -04:00
Marshall Bowers
817a41c4dc collab: Add a Cents type (#18935)
This PR adds a new `Cents` type that can be used to represent a monetary
value in cents.

This cuts down on the primitive obsession we were using when dealing
with money in the billing code.

Release Notes:

- N/A
2024-10-09 14:22:32 -04:00
Peter Tripp
bc23d1e666 docs: Add gopls install instructions (#18919) 2024-10-09 14:05:35 -04:00
Thorsten Ball
bc4abd2b29 ssh session: Fix hang when doing state update in reconnect (#18934)
This snuck in last-minute.

Release Notes:

- Fixed a potential hang and panic when an SSH project goes through a
slow reconnect.
2024-10-09 19:40:09 +02:00
Ömer Sinan Ağacan
71f4ca67c2 Use WHOLE_WORD search option in vim mode's whole-word search (#18725)
Instead of wrapping the search term with `\<...\>`, enable the
`WHOLE_WORD` search option.

The advantage of the search option is that it can be toggled with one
click/key press (alt+w by default), and it doesn't require regex mode.

Release Notes:

- Vim mode's whole word search now uses the search bar's "Match whole
words" option, instead of wrapping the search term with `\<...\>`. This
allows easier toggling of whole-word search, and it also works without
enabling the regex mode.
2024-10-09 19:26:28 +02:00
狐狸
f05b440572 Improve syntax highlights (#18728)
Closes #18722

- Replace the `@escape` capture name with `@string.escape` for escape
sequences in Go, Python, Regex, Racket, Ruby, and Scheme.
- Rust
  - Add syntax highlighting for escape sequences. Close #18722
- Fix the issue where `@punctuation.delimiter` is being overwritten by
`@operator`.
  - Add the period (".") to `@punctuation.delimiter`.

Release Notes:

- N/A
2024-10-09 19:25:46 +02:00
Joseph T. Lyons
1cbaca667f Remove historical_event column in editor events (#18932)
We have a lot of data in Clickhouse. This column was used when migrating
the events dataset between analytics databases and has no purpose today.

Naive maths: 257,170,993 editor event rows * 1 byte per boolean =
257,170,993 bytes, or ~0.24 GB

I'll drop the column after deploying a new collab.

Going forward, I'd like to remove more data that we never touch, to try
to keep things more focused. We should discuss some TTL at some point.

Release Notes:

- N/A
2024-10-09 13:19:13 -04:00
Kirill Bulatov
8911fd46e1 Do not log errors when no worktree is found for certain assistant panel editors (#18923)
Nothing in the assistant panel needs LSP so far, so the errors are not
useful.

Release Notes:

- N/A
2024-10-09 18:45:22 +03:00
Joseph T Lyons
926e54bd4a v0.158.x dev 2024-10-09 11:32:34 -04:00
Kirill Bulatov
b6ba4fcc51 Silence the logs 2024-10-09 18:16:22 +03:00
Thorsten Ball
b703514d0e project: Observe SshRemoteClient to get notified about state changes (#18918)
Release Notes:

- N/A
2024-10-09 17:13:43 +02:00
Thorsten Ball
c674d73734 remote server: Do not spawn server when proxy reconnects (#18864)
This ensures that we only ever reconnect to a running server and not
spawn a new server with no state.

This avoids the problem of the server process crashing, `proxy`
reconnecting, starting a new server, and the user getting errors like
"unknown buffer id: ...".

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <bennet@zed.dev>
2024-10-09 16:51:12 +02:00
Adam Wolff
dbf986d37a telemetry: Refactor telemetry request into separate method (#18890)
Refactor telemetry request into separate method to make it easier to
override in a fork.

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-09 10:47:59 -04:00
Kirill Bulatov
a62a2fa8f7 Always wait for completion resolve before applying the completion edits (#18907)
After https://github.com/rust-lang/rust-analyzer/pull/18167 and certain
people who type and complete rapidly, it turned out that we have not
waited for `completionItem/resolve` to finish before applying the
completion results.

Release Notes:

- Fixed completion items applied improperly on fast typing
2024-10-09 17:18:20 +03:00
Piotr Osiewicz
f50bca7630 ssh: Improve dismissal behaviour (#18900)
Do not always close current window in SshConnectionModal; only do so
when the window was spawned from ssh modal. Assign unique IDs to "Open
folder" buttons

Closes #ISSUE

Release Notes:

- N/A
2024-10-09 12:22:53 +02:00
Thorsten Ball
9c54bd1bd4 macOS: Drop input handler to avoid editor/project not being dropped (#18898)
This fixes the problem of a `Project` sometimes not being dropped when
closing the single, last window of Zed.

Turns out, it wasn't get dropped for the following reason:

1. `editor::Editor` held a reference to project
2. The macOS `input_handler` on the `Window` held a reference to that
`Editor`
3. The AppKit window (and its input handler) get dropped asynchronously
(in the code in this diff), after the window is closed.
4. After the window is closed and no `cx.update()` calls are made
anymore, `flush_effects` is not called anymore.
5. But `flush_effects` is where we dropped entities that don't have any
more references.

In short: we dropped `Editor`, which held a reference to `Project`, out
of band, `flush_effects` wasn't called anymore, and thus the `Project`
wasn't dropped.

cc @ConradIrwin @bennetbo since we talked about this.

Release Notes:

- N/A

Co-authored-by: Antonio <antonio@zed.dev>
2024-10-09 10:45:35 +02:00
Mikayla Maki
5d5c4b6677 Revert http client changes (#18892)
These proved to be too unstable. Will restore these changes once the issues have been fixed.

Release Notes:

- N/A
2024-10-09 01:07:18 -07:00
Max Brunsfeld
e351148152 Fix bugs in expanding diff hunk (#18885)
Release Notes:

- Fixed an issue where diff hunks at the boundaries of multi buffer
excerpts could not be expanded
2024-10-08 17:30:42 -07:00
Marshall Bowers
b0a9005163 client: Send telemetry events with Content-Type: application/json (#18886)
This PR updates the telemetry events sent to collab to use
`Content-Type: application/json` instead of `Content-Type: text/plain`.

The POST bodies are JSON, so `application/json` is the correct MIME
type.

I suspect the `text/plain` is a remnant from when the events were still
going through Vercel.

Release Notes:

- N/A
2024-10-08 20:25:07 -04:00
Marshall Bowers
801210cd50 collab: Make github_user_login required in LlmTokenClaims (#18882)
This PR makes the `github_user_login` field required in the
`LlmTokenClaims`.

We previously added this in
https://github.com/zed-industries/zed/pull/16316 and made it optional
for backwards-compatibility.

It's been more than long enough for all of the previous LLM tokens to
have expired, so we can now make the field required.

Release Notes:

- N/A
2024-10-08 20:03:33 -04:00
Marshall Bowers
f861479890 collab: Update billing code for LLM usage billing (#18879)
This PR reworks our existing billing code in preparation for charging
based on LLM usage.

We aren't yet exercising the new billing-related code outside of
development.

There are some noteworthy changes for our existing LLM usage tracking:

- A new `monthly_usages` table has been added for tracking usage
per-user, per-model, per-month
- The per-month usage measures have been removed, in favor of the
`monthly_usages` table
- All of the per-month metrics in the Clickhouse rows have been changed
from a rolling 30-day window to a calendar month

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Richard <richard@zed.dev>
Co-authored-by: Max <max@zed.dev>
2024-10-08 18:29:38 -04:00
Danilo Leal
a95fb8f1f9 ssh: Fix text wrapping in loading text (#18876)
This PR adds `flex_wrap` to the loading text container to prevent the
loading modal layout to break.

Release Notes:

- N/A
2024-10-08 18:37:04 -03:00
Joseph T. Lyons
744891f15f Provide a default value for is_via_ssh when it isn't sent via older clients (#18874)
Release Notes:

- N/A
2024-10-08 16:16:38 -04:00
Peter Tripp
f33019c885 Document extension bump process (#18872)
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-08 16:13:56 -04:00
Peter Tripp
7960468d8a dart: Bump to v0.1.1 (#18859)
- Includes https://github.com/zed-industries/zed/pull/18845
2024-10-08 14:25:29 -04:00
Marshall Bowers
5377674fc0 csharp: Add support for triple-slash doc comments (#18869)
This PR adds support for triple-slash (`///`) doc comments in C#.

As requested by https://github.com/zed-industries/zed/issues/18766.

Release Notes:

- N/A
2024-10-08 13:54:11 -04:00
Danilo Leal
af9a595770 ssh: Add tweaks to the UI (#18817)
Follow up to https://github.com/zed-industries/zed/pull/18727

---

Release Notes:

- N/A
2024-10-08 14:32:52 -03:00
Marshall Bowers
3f2de172ae collab: Set cached token values when initially creating lifetime usage records (#18865)
This PR fixes an issue where we weren't setting the cached token fields
when initially creating a lifetime usage record.

Release Notes:

- N/A
2024-10-08 13:16:17 -04:00
Joseph T. Lyons
77bf2ad0f1 Add is_via_ssh field to edit events (#18867)
Release Notes:

- N/A
2024-10-08 13:13:40 -04:00
Marshall Bowers
3da1902e24 worktree: Depend on rpc with test-support feature in tests (#18866)
This PR updates the `worktree` crate to depend on `rpc` with the
`test-support` feature flag when running tests.

This fixes an issue I was seeing locally when trying to run tests in the
`worktree` crate:

```
λ cargo test -p worktree -- test_repository_subfolder_git_status
   Compiling worktree v0.1.0 (/Users/maxdeviant/projects/zed/crates/worktree)
error[E0432]: unresolved import `rpc::AnyProtoClient`
  --> crates/worktree/src/worktree.rs:39:18
   |
39 | use rpc::{proto, AnyProtoClient};
   |                  ^^^^^^^^^^^^^^ no `AnyProtoClient` in the root

For more information about this error, try `rustc --explain E0432`.
error: could not compile `worktree` (lib test) due to 1 previous error
```

Release Notes:

- N/A
2024-10-08 13:07:34 -04:00
Max Brunsfeld
4139e2de23 In proposed change editors, apply diff hunks in batches (#18841)
Release Notes:

- N/A
2024-10-08 08:58:28 -07:00
Thorsten Ball
ff7aa024ee remote server on macOS: Sign with entitlements (#18863)
This does two things:

- Prevent feature unification
- Sign the remote-server binary with the same entitlements we use for
Zed because we saw this in crash report:

Crashed Thread: 4 Dispatch queue: com.apple.root.user-initiated-qos

Exception Type: EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid))
      Exception Codes:       UNKNOWN_0x32 at 0x0000000103636644
      Exception Codes:       0x0000000000000032, 0x0000000103636644

      Termination Reason:    Namespace CODESIGNING, Code 2 Invalid Page

VM Region Info: 0x103636644 is in 0x103634000-0x103638000; bytes after
start: 9796 bytes before end: 6587
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
VM_ALLOCATE 103630000-103634000 [ 16K] r--/rwx SM=ZER
---> VM_ALLOCATE 103634000-103638000 [ 16K] r-x/rwx SM=COW
VM_ALLOCATE 103638000-103640000 [ 32K] r--/rwx SM=ZER

  Which sounds a lot like codesigning/jit/entitlements stuff.


Release Notes:

- N/A

Co-authored-by: Piotr <piotr@zed.dev>
Co-authored-by: Bennet <bennet@zed.dev>
2024-10-08 17:47:24 +02:00
Joseph T. Lyons
d295c46433 Remove deprecated copilot event (#18862)
`CopilotEvent` was succeeded by `InlineCompletionEvent` 5 months ago.

Release Notes:

- N/A
2024-10-08 11:10:20 -04:00
Joseph T. Lyons
4c7a6f5e7f Add is_via_ssh field to editor events (#18837)
Release Notes:

- N/A
2024-10-08 10:30:04 -04:00
Peter Tripp
dd44168cad dart: Improve indentation (#18845)
Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-08 10:20:20 -04:00
Joseph T. Lyons
5bb18adbe8 Inform users they can ask us to reopen issues closed by the stale issue action (#18857)
Release Notes:

- N/A
2024-10-08 08:13:29 -04:00
Thorsten Ball
b2eb439f32 remote server: Add more debug logging (#18855)
Closes #ISSUE

Release Notes:

- N/A
2024-10-08 13:57:26 +02:00
Bennet Bo Fenner
f0566d54eb ssh: Log error when remote server panics (#18853)
Release Notes:

- N/A
2024-10-08 12:57:47 +02:00
Thorsten Ball
be531653a4 Direnv warn (#18850)
Follow-up fixes to #18567

Release Notes:

- N/A
2024-10-08 11:54:28 +02:00
Bennet Bo Fenner
fa85238c69 ssh: Limit amount of reconnect attempts (#18819)
Co-Authored-by: Thorsten <thorsten@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
2024-10-08 11:37:54 +02:00
Stanislav Alekseev
910a773b89 Display environment loading failures in the activity indicator (#18567)
As @maan2003 noted in #18473, we should warn the user if direnv call
fails

Release Notes:

- Show a notice in the activity indicator if an error occurs while
loading the shell environment
2024-10-08 11:36:18 +02:00
Peter Tripp
87cc208f9f docs: Fix ollama available_models example (#18842) 2024-10-07 21:04:36 -04:00
Max Brunsfeld
b0a16a7601 Fix bugs with applying hunks from branch buffers (#18721)
Release Notes:

- N/A

---------

Co-authored-by: Marshall <marshall@zed.dev>
2024-10-07 16:28:33 -07:00
Marshall Bowers
3c91184726 collab: Drop mistakenly-added columns from the usages table (#18835)
This PR drops the `cache_creation_input_tokens_this_month ` and
`cache_read_input_tokens_this_month ` columns from the `usages` table in
the LLM database.

We mistakenly added these in #18834, but these aren't necessary due to
the structure of the `usages` table. We weren't actually using these
columns anywhere.

Release Notes:

- N/A
2024-10-07 18:21:48 -04:00
Marshall Bowers
d55f025906 collab: Track cache writes/reads in LLM usage (#18834)
This PR extends the LLM usage tracking to support tracking usage for
cache writes and reads for Anthropic models.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Antonio <antonio@zed.dev>
2024-10-07 17:32:49 -04:00
Marshall Bowers
c5d252b837 collab: Add missing cmake dependency to Dockerfile (#18832)
This PR adds the missing `cmake` dependency to the Docker image that is
now needed in order to build collab.

Release Notes:

- N/A
2024-10-07 16:25:17 -04:00
Joseph T. Lyons
a15b10986a Add ssh initialization events (#18831)
Release Notes:

- N/A
2024-10-07 16:17:43 -04:00
Mikayla Maki
5387a6f7f9 Fix an issue where LLM requests would block forever (#18830)
Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-07 16:03:26 -04:00
Mikayla Maki
8cdb9d6b85 Fix a bug where HTTP errors where being reported incorrectly (#18828)
Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-07 12:03:02 -07:00
Marshall Bowers
7d380e9e18 Temporarily prevent deploying collab to production (#18825)
This PR adds a temporary measure to prevent deploying collab to
production, while we investigate some issues stemming from the HTTP
client change.

Release Notes:

- N/A
2024-10-07 14:31:23 -04:00
Piotr Osiewicz
60c12a8d06 ssh: Remove old dev servers code paths (#18823)
Closes #ISSUE

Release Notes:

- N/A
2024-10-07 19:18:44 +02:00
Marshall Bowers
11206a8444 ui: Fix avatar indicators getting cut off (#18821)
This PR fixes an issue introduced in #18810 that was causing the avatar
indicators to get cut off.

Release Notes:

- N/A
2024-10-07 12:53:11 -04:00
Marshall Bowers
c83690ff14 storybook: Wire up HTTP client (#18818)
This PR wires up the HTTP client in the Storybook.

Release Notes:

- N/A
2024-10-07 12:29:10 -04:00
Marshall Bowers
d1a758708d php: Bump to v0.2.1 (#18815)
This PR bumps the PHP extension to v0.2.1.

Changes:

- https://github.com/zed-industries/zed/pull/18368
- https://github.com/zed-industries/zed/pull/18774

Release Notes:

- N/A
2024-10-07 10:23:16 -04:00
Marshall Bowers
7c7151551a proto: Bump to v0.2.0 (#18814)
This PR bumps the Protobuf extension to v0.2.0.

Changes:

- https://github.com/zed-industries/zed/pull/18763

Release Notes:

- N/A
2024-10-07 10:11:12 -04:00
Bennet Bo Fenner
a3b63448df ssh: Do not cancel connection process if user is typing password (#18812)
Previously, the connection process would be cancelled after 10 seconds,
even if the connection was established successfully but the user was
still typing in a password.
We know recognize when the user is prompted for a password, and cancel
the timeout task.

Co-Authored-by: Thorsten <thorsten@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
2024-10-07 15:53:32 +02:00
Nate Butler
65c9b15796 Remove avatar shape (#18810)
This PR re-removes `AvatarShape` as it is unused. The previous time it
was removed incorrectly, resulting in square avatars!

Release Notes:

- N/A
2024-10-07 09:23:40 -04:00
Bennet Bo Fenner
25a97a6a2b ssh: Detect timeouts when server is unresponsive (#18808)
To detect connection timeouts we ping the remote server every X seconds
and attempt to reconnect if the server failed to respond.
Next up is showing some feedback in the UI to make this visible to the
user, and stop reconnecting after X amount of retries.

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
2024-10-07 15:08:16 +02:00
Piotr Osiewicz
5aa165c530 ssh: Overhaul remoting UI (#18727)
Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
2024-10-07 15:01:50 +02:00
Thorsten Ball
9c5bec5efb formatting: Use project environment to find external formatters (#18611)
Closes #18261

This makes sure that we find external formatters in the project
environment.

TODO:

- [x] Use a different type for the triplet of `(buffer_handle,
buffer_path, buffer_env)`. Something like `FormattableBuffer`.
- [x] Test this!!

Release Notes:

- Fixed external formatters not being found, even when they were
available in the `$PATH` of a project.

---------

Co-authored-by: Bennet <bennet@zed.dev>
2024-10-07 12:24:12 +02:00
Thorsten Ball
c03b8d6c48 ssh remoting: Enable reconnecting after connection losses (#18586)
Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
2024-10-07 11:40:59 +02:00
Danilo Leal
67fbdbbed6 Put back code that makes the avatar rounded (#18799)
Follow-up to https://github.com/zed-industries/zed/pull/18768

---

Release Notes:

- N/A
2024-10-07 05:42:48 -03:00
Piotr Osiewicz
03c84466c2 chore: Fix some violations of 'needless_pass_by_ref_mut' lint (#18795)
While this lint is allow-by-default, it seems pretty useful to get rid
of mutable borrows when they're not needed.

Closes #ISSUE

Release Notes:

- N/A
2024-10-07 01:29:58 +02:00
Agustin Gomes
59f0f4ac42 Fix script/linux on RHEL/Fedora (#18788)
- Add missing `/etc/os-release` from a grep call
- Remove typo `grep grep` from another.

Co-authored-by: Peter Tripp <peter@zed.dev>
2024-10-06 14:47:48 -04:00
Peter Tripp
bd746145b0 ci: Make docs-only PRs only trigger docs-related tests (#18744)
This should speed up any docs-only PRs so that they don't have to run the full 5 minute battery of tests.

Release Notes:

- N/A
2024-10-06 10:28:39 -04:00
Peter Tripp
1b06c70a76 Fix alt-t context (#18783)
- Fix incorrect context introduced in https://github.com/zed-industries/zed/pull/18749/

Release Notes:

- N/A
2024-10-06 10:26:26 -04:00
Peter
06bd2431d2 proto: Add language server support (#18763)
Closes #18762

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-06 10:12:06 -04:00
Roman Zipp
200b2bf70a php: Add syntax highlighting for Intelephense completions (#18774)
Release Notes:

- N/A

This PR introduces syntax highlighting for intelephense autocomple. The
styling was selected to roughly match PHPStorm's default scheme.

Please note that I'm not very familiar with writing Rust, but I'm happy
to adapt to any requested changes!

## Examples

### Object attributes, methods and constants

![Screenshot 2024-10-06 at 13 38
03](https://github.com/user-attachments/assets/a91634ff-0f2e-41f0-b548-ecb09c40947c)
![Screenshot 2024-10-06 at 13 38
11](https://github.com/user-attachments/assets/b6f179f4-898b-4d82-9d36-a3e82328325c)

### Typed enum members

![Screenshot 2024-10-06 at 13 38
53](https://github.com/user-attachments/assets/7133b981-4f68-4210-b233-403cdf3ec9bb)
![Screenshot 2024-10-06 at 13 38
41](https://github.com/user-attachments/assets/2e806f3d-3538-45f2-b075-b8be5902b786)

### Variables

Includes altered highlighting for [reserved variable
names](https://www.php.net/manual/en/reserved.variables.php).

![Screenshot 2024-10-06 at 13 39
30](https://github.com/user-attachments/assets/be426eb8-5879-432d-b302-391c2c68a7cb)

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-06 10:11:21 -04:00
Nate Butler
8376dd2011 ui crate docs & spring cleaning (#18768)
Similar to https://github.com/zed-industries/zed/pull/18690 &
https://github.com/zed-industries/zed/pull/18695, this PR enables
required docs for `ui` and does some cleanup.

Changes:
- Enables the `deny(missing_docs)` crate-wide.
- Adds `allow(missing_docs)` on many modules until folks pick them up to
document them
- Documents some modules (all in `ui/src/styles`)
- Crate root-level organization: Traits move to `traits`, other misc
organization
- Cleaned out a bunch of unused code.

Note: I'd like to remove `utils/format_distance` but the assistant panel
uses it. To move it over to use the `time_format` crate we may need to
update it to use `time` instead of `chrono`. Needs more investigation.

Release Notes:

- N/A
2024-10-05 23:28:34 -04:00
Chris Boette
c9bee9f81f docs: Note the need for Rust when developing extensions (#18753) 2024-10-05 12:26:28 -04:00
Kirill Bulatov
1f31022cbe Compare migrations formatted uniformly (#18760)
Otherwise old migrations may be formatted differently than new
migrations, causing comparison errors.

Follow-up of https://github.com/zed-industries/zed/pull/18676

Release Notes:

- N/A
2024-10-05 12:58:45 +03:00
Peter Tripp
7608000df8 Fix option-t and option-shift-t in terminal (#18749) 2024-10-04 16:56:01 -04:00
Remco Smits
8f27ffda4d gpui: Fix uniform list horizon offset for non-horizontal scrollable lists (#18748)
Closes #18739

/cc @osiewicz 
/cc @maxdeviant 

I'm not sure why the `+ padding.left` was added, but this was the cause
of the issue. I also tested removing the extra left padding but didn't
seem to see a difference inside the project panel. So we can maybe even
remove it?

**Before:**
![Screenshot 2024-10-04 at 21 43
34](https://github.com/user-attachments/assets/b5d67cd9-f92b-4301-880c-d351fe156c98)

**After:**
<img width="294" alt="Screenshot 2024-10-04 at 21 49 05"
src="https://github.com/user-attachments/assets/8cc84170-a86b-46b8-91c9-39def64f0bd0">

Release Notes:

- Fix code action list not horizontal aligned correctly
2024-10-04 23:07:58 +03:00
Marshall Bowers
cee019b1ea editor: Qualify RangeExt::overlaps call to prevent phantom diagnostics (#18743)
This PR qualifies a call to `RangeExt::overlaps` to avoid some confusion
in rust-analyzer not being able to distinguish between
`RangeExt::overlaps` and `AnchorRangeExt::overlaps` and producing
phantom diagnostics.

We may also want to consider renaming the method on `AnchorRangeExt` to
disambiguate them.

Release Notes:

- N/A
2024-10-04 15:06:05 -04:00
Boris Cherny
01ad22683d telemetry: Add language_name and model_provider (#18640)
This PR adds a bit more metadata for assistant logging.

Release Notes:

- Assistant: Added `language_name` and `model_provider` fields to
telemetry events.

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
Co-authored-by: Max <max@zed.dev>
2024-10-04 14:37:27 -04:00
Peter Tripp
dfe1e43832 docs: Linux XDG desktop secrets portals 2024-10-04 14:13:07 -04:00
Marshall Bowers
e3a6f89e2d Make report_assistant_event take an AssistantEvent struct (#18741)
This PR makes the `report_assistant_event` method take an
`AssistantEvent` struct instead of all of the struct fields as
individual parameters.

Release Notes:

- N/A
2024-10-04 13:19:18 -04:00
Peter Tripp
07e808d16f Document File Scan Exclusions (#18738)
Release Notes:

- N/A
2024-10-04 12:07:43 -04:00
Muhammad Talal Anwar
2f7430af70 c: Add runnable for main function (#18720)
Release Notes:

- Added Runnable for C main function

This tags can then be used in tasks, for example:

```json
[
  {
    "label": "Run ${ZED_STEM}",
    "command": "gcc",
    "args": [
      "$ZED_FILE",
      "-o",
      "${ZED_DIRNAME}/${ZED_STEM}.out",
      "&&",
      "${ZED_DIRNAME}/${ZED_STEM}.out"
    ],
    "tags": ["c-main"]
  }
]

```
2024-10-04 17:28:12 +02:00
renovate[bot]
d012e35b04 Update Rust crate parking to v2.2.1 (#18664)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [parking](https://redirect.github.com/smol-rs/parking) | dependencies
| patch | `2.2.0` -> `2.2.1` |

---

### Release Notes

<details>
<summary>smol-rs/parking (parking)</summary>

###
[`v2.2.1`](https://redirect.github.com/smol-rs/parking/blob/HEAD/CHANGELOG.md#Version-221)

[Compare
Source](https://redirect.github.com/smol-rs/parking/compare/v2.2.0...v2.2.1)

- Specify the reason for using `parking` in the docs.
([#&#8203;25](https://redirect.github.com/smol-rs/parking/issues/25))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-04 11:09:20 -04:00
Daste
d695de4504 tab_switcher: Use git-aware colors for file icons (#18733)
Release Notes:

- Fixed tab switcher icons not respecting the `tabs.git_status` setting.

Fixes an issue mentioned in
https://github.com/zed-industries/zed/pull/17115#issuecomment-2378966170
- file icons in the tab switcher weren't colored according to git
status, even if `tabs.git_status` was set to true.

I used a similar approach I saw in other places of the project to get
the project entry and its git status, but maybe we could move the
coloring logic entirely to `tab_icon()`? Wouldn't this break anything?

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-04 10:37:41 -04:00
renovate[bot]
9702310737 Update Rust crate sqlformat to v0.2.6 (#18676)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [sqlformat](https://redirect.github.com/shssoichiro/sqlformat-rs) |
dependencies | patch | `0.2.4` -> `0.2.6` |

---

### Release Notes

<details>
<summary>shssoichiro/sqlformat-rs (sqlformat)</summary>

###
[`v0.2.6`](https://redirect.github.com/shssoichiro/sqlformat-rs/blob/HEAD/CHANGELOG.md#Version-026)

[Compare
Source](https://redirect.github.com/shssoichiro/sqlformat-rs/compare/v0.2.5...v0.2.6)

- fix: ON UPDATE with two many blank formatted incorrectly
([#&#8203;46](https://redirect.github.com/shssoichiro/sqlformat-rs/issues/46))
-   fix: `EXCEPT` not handled well
- fix: REFERENCES xyz ON UPDATE .. causes formatter to treat the
remaining as an UPDATE statement
-   fix: Escaped strings formatted incorrectly
-   fix: RETURNING is not placed on a new line
- fix: fix the issue of misaligned comments after formatting
([#&#8203;40](https://redirect.github.com/shssoichiro/sqlformat-rs/issues/40))

###
[`v0.2.5`](https://redirect.github.com/shssoichiro/sqlformat-rs/compare/v0.2.4...v0.2.5)

[Compare
Source](https://redirect.github.com/shssoichiro/sqlformat-rs/compare/v0.2.4...v0.2.5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-04 10:36:30 -04:00
Piotr Osiewicz
bafd7ed000 gpui: Store measure functions as context of taffy nodes (#18732)
Taffy maintains a mapping of NodeId <-> Context anyways (and does the
lookup), so it's redundant for us to store it separately. Tl;dr: we get
rid of one map and one map lookup per layout request.

Release Notes:

- N/A
2024-10-04 13:58:57 +02:00
Piotr Osiewicz
37ded190cf gpui: Use taffy to retrieve the parent for a given layout node (#18730)
Again. https://github.com/zed-industries/zed/pull/4070

Let's see how it goes this time around. The only thing that might've
been related to that revert on our Slack was about crashing in collab
panel.

Release Notes:

- N/A
2024-10-04 12:37:55 +02:00
Piotr Osiewicz
a99750fd35 chore: Bump taffy to 0.5.2 (#18729)
Release Notes:

- N/A
2024-10-04 12:37:44 +02:00
Ömer Sinan Ağacan
e2647025ac Add vim::MoveTo{Next,Prev} flags for regex and case sensitive search (#18429)
This makes the hard-coded regex and case-sensitive search flags in
`vim::MoveToNext` and `vim::MoveToPrev` commands configurable in key
bindings.

Example:

```json
{
  "context": "VimControl && !menu",
  "bindings": {
    "*": ["vim::MoveToNext", { "regex": false, "caseSensitive": false }],
    "#": ["vim::MoveToPrev", { "regex": false, "caseSensitive": false }]
  }
}
```

Closes #15837.

Release Notes:

- Added `regex` and `caseSensitive` arguments to `vim::MoveToNext` and
`vim ::MoveToPrev` commands, for toggling regex and case sensitive
search.
2024-10-04 09:10:26 +02:00
Marshall Bowers
6635758009 vcs_menu: Streamline branch creation from branch selector (#18712)
This PR streamlines the branch creation from the branch selector when
searching for a branch that does not exist.

The branch selector will show the available branches, as it does today:

<img width="576" alt="Screenshot 2024-10-03 at 4 01 25 PM"
src="https://github.com/user-attachments/assets/e1904f5b-4aad-4f88-901d-ab9422ec18bb">

When entering the name of a branch that does not exist, the picker will
be populated with an entry to create a new branch:

<img width="570" alt="Screenshot 2024-10-03 at 4 01 37 PM"
src="https://github.com/user-attachments/assets/07f8d12c-9422-4fd8-a6dc-ae450e297a13">

Selecting that entry will create the branch and switch to it.

Release Notes:

- Streamlined creating a new branch from the branch selector.
2024-10-03 16:18:28 -04:00
Junkui Zhang
8d6fa9526e windows: Fix sometimes log error messages don't show the crate name (#18706)
On windows, path could be something like `C:\path\to\the\crate`. Hence,
`split('/')` would refuse to work in this case.

### Before

![Screenshot 2024-10-04
023652](https://github.com/user-attachments/assets/9c14fb24-5ee0-4b56-8fbd-313abb28f134)

### After

![Screenshot 2024-10-04
024115](https://github.com/user-attachments/assets/217e175c-b0e1-4589-9c3d-98670882b185)


Release Notes:

- N/A
2024-10-03 13:00:33 -07:00
Marshall Bowers
fd22c9bef9 editor: Use predefined rounding value for color swatches (#18708)
This PR updates the color swatches added in #18665 to use a predefined
`rounding` value instead of a literal value.

The underlying values are the same, but we don't want to diverge from
our design system.

Release Notes:

- N/A
2024-10-03 15:20:41 -04:00
Joseph T. Lyons
43d05a432b Close stale issues out after 7 days (#18707)
Closes #ISSUE

Release Notes:

- N/A
2024-10-03 14:38:49 -04:00
Jordan Pittman
cac98b7bbf Show color swatches for LSP completions (#18665)
Closes #11991

Release Notes:

- Added support for color swatches for language server completions.

<img width="502" alt="Screenshot 2024-10-02 at 19 02 22"
src="https://github.com/user-attachments/assets/57e85492-3760-461a-9b17-a846dc40576b">

<img width="534" alt="Screenshot 2024-10-02 at 19 02 48"
src="https://github.com/user-attachments/assets/713ac41c-16f0-4ad3-9103-d2c9b3fa8b2e">

This implementation is mostly a port of the VSCode version of the
ColorExtractor. It seems reasonable the we should support _at least_
what VSCode does for detecting color swatches from LSP completions.

This implementation could definitely be better perf-wise by writing a
dedicated color parser. I also think it would be neat if, in the future,
Zed handled _more_ color formats — especially wide-gamut colors.

There are a few differences to the regexes in the VSCode implementation
but mainly so simplify the implementation :
- The hex vs rgb/hsl regexes were split into two parts
- The rgb/hsl regexes allow 3 or 4 color components whether hsla/rgba or
not and the parsing implementation accepts/rejects colors as needed

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-03 14:38:17 -04:00
Marshall Bowers
cddd7875a4 Extract Protocol Buffers support into an extension (#18704)
This PR extracts the Protocol Buffers support into an extension.

Release Notes:

- Removed built-in support for Protocol Buffers, in favor of making it
available as an extension. The Protocol Buffers extension will be
suggested for download when you open a `.proto` file.
2024-10-03 13:37:43 -04:00
Nate Butler
8c95b8d89a theme crate spring cleaning (#18695)
This PR does some spring cleaning on the `theme` crate:

- Removed two unused stories and the story dep
- Removed the `one` theme family (from the `theme` crate, not the app),
this is now `zed_default_themes`.
- This will hopefully remove some confusion caused by this theme we
started in rust but didn't end up using
- Removed `theme::prelude` (it just re-exported scale colors, which we
don't use outside `theme`)
- Removed completely unused `zed_pro` themes (we started on these during
the gpui2 port and didn't finish them.)

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-03 13:17:31 -04:00
Marshall Bowers
a9f816d5fb telemetry_events: Update crate-level docs (#18703)
This PR updates the `telemetry_events` crate to use module-level
documentation for its crate-level docs.

Release Notes:

- N/A
2024-10-03 12:38:51 -04:00
renovate[bot]
f7b3680e4d Update Rust crate pretty_assertions to v1.4.1 (#18668)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[pretty_assertions](https://redirect.github.com/rust-pretty-assertions/rust-pretty-assertions)
| workspace.dependencies | patch | `1.4.0` -> `1.4.1` |

---

### Release Notes

<details>
<summary>rust-pretty-assertions/rust-pretty-assertions
(pretty_assertions)</summary>

###
[`v1.4.1`](https://redirect.github.com/rust-pretty-assertions/rust-pretty-assertions/blob/HEAD/CHANGELOG.md#v141)

[Compare
Source](https://redirect.github.com/rust-pretty-assertions/rust-pretty-assertions/compare/v1.4.0...v1.4.1)

#### Fixed

- Show feature-flagged code in documentation. Thanks to
[@&#8203;sandydoo](https://redirect.github.com/sandydoo) for the fix!
([#&#8203;130](https://redirect.github.com/rust-pretty-assertions/rust-pretty-assertions/pull/130))

#### Internal

- Bump `yansi` version to `1.x`. Thanks to
[@&#8203;SergioBenitez](https://redirect.github.com/SergioBenitez) for
the update, and maintaining this library!
([#&#8203;121](https://redirect.github.com/rust-pretty-assertions/rust-pretty-assertions/pull/121))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 11:32:04 -04:00
renovate[bot]
ded3d3fc14 Update Python to v3.12.7 (#18652)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [python](https://redirect.github.com/containerbase/python-prebuild) |
dependencies | patch | `3.12.6` -> `3.12.7` |

---

### Release Notes

<details>
<summary>containerbase/python-prebuild (python)</summary>

###
[`v3.12.7`](https://redirect.github.com/containerbase/python-prebuild/releases/tag/3.12.7)

[Compare
Source](https://redirect.github.com/containerbase/python-prebuild/compare/3.12.6...3.12.7)

##### Bug Fixes

-   **deps:** update dependency python to v3.12.7

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 11:29:29 -04:00
Danilo Leal
ddcd45bb45 docs: Add tweaks to the outline panel page (#18697)
Thought we could be extra clear here with the meaning of "singleton
buffers".

Release Notes:

- N/A
2024-10-03 12:27:42 -03:00
renovate[bot]
29796aa412 Update Rust crate serde_json to v1.0.128 (#18669)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [serde_json](https://redirect.github.com/serde-rs/json) | dependencies
| patch | `1.0.127` -> `1.0.128` |
| [serde_json](https://redirect.github.com/serde-rs/json) |
workspace.dependencies | patch | `1.0.127` -> `1.0.128` |

---

### Release Notes

<details>
<summary>serde-rs/json (serde_json)</summary>

###
[`v1.0.128`](https://redirect.github.com/serde-rs/json/releases/tag/1.0.128)

[Compare
Source](https://redirect.github.com/serde-rs/json/compare/1.0.127...1.0.128)

- Support serializing maps containing 128-bit integer keys to
serde_json::Value
([#&#8203;1188](https://redirect.github.com/serde-rs/json/issues/1188),
thanks [@&#8203;Mrreadiness](https://redirect.github.com/Mrreadiness))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 11:14:22 -04:00
Nate Butler
773ad6bfd1 Document the theme crate (#18690)
This PR enables required documentation for the `theme` crate starts on
documenting it.

The end goal is to have all meaningful documentation in the crate filled
out – However I'm not sure that just adding `#![deny(missing_docs)]` to
the whole crate is the right approach.

I don't know that having 200+ "The color of the _ color" field docs is
useful however–In the short term I've excluded some of the modules that
contain structs with a ton of fields (`colors, `status`, etc.) until we
decide what the right solution here is.

Next steps are to clean up the crate, removing unused modules or those
with low usage in favor of other approaches.

Changes in this PR:
- Enable the `deny(missing_docs)` lint for the `theme` crate 
- Start documenting a subset of the crate.
- Enable `#![allow(missing_docs)]` for some modules.


Release Notes:

- N/A
2024-10-03 10:27:19 -04:00
Danilo Leal
dc85378b96 Clean up style properties on hunk controls (#18639)
This PR removes some duplicate style properties on the hunk controls,
namely padding, border, and background color.

Release Notes:

- N/A
2024-10-03 11:23:56 -03:00
Kirill Bulatov
1e8297a469 Remove a debug dev config line (#18689)
Follow-up of https://github.com/zed-industries/zed/pull/18645

Release Notes:

- N/A
2024-10-03 15:38:42 +03:00
renovate[bot]
9cd42427d8 Update Rust crate thiserror to v1.0.64 (#18677)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [thiserror](https://redirect.github.com/dtolnay/thiserror) |
workspace.dependencies | patch | `1.0.63` -> `1.0.64` |

---

### Release Notes

<details>
<summary>dtolnay/thiserror (thiserror)</summary>

###
[`v1.0.64`](https://redirect.github.com/dtolnay/thiserror/releases/tag/1.0.64)

[Compare
Source](https://redirect.github.com/dtolnay/thiserror/compare/1.0.63...1.0.64)

- Exclude derived impls from coverage instrumentation
([#&#8203;322](https://redirect.github.com/dtolnay/thiserror/issues/322),
thanks [@&#8203;oxalica](https://redirect.github.com/oxalica))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 23:28:00 -04:00
Joseph T. Lyons
df21fe174d Add command palette action name to outline panel docs (#18678)
Release Notes:

- N/A
2024-10-02 22:16:56 -04:00
Joseph T. Lyons
c48d4dbc6b Add basic outline panel docs (#18674)
Bandaid to: https://github.com/zed-industries/zed/issues/18672

Release Notes:

- Added basic outline panel docs
2024-10-02 22:06:07 -04:00
Piotr Osiewicz
19b186671b ssh: Add session state indicator to title bar (#18645)
![image](https://github.com/user-attachments/assets/0ed6f59c-e0e7-49e6-8db7-f09ec5cdf653)
The indicator turns yellow when ssh client is trying to reconnect. Note
that the state tracking is probably not ideal (we'll see how it pans out
once we start dog-fooding), but at the very least "green=good" should be
a decent mental model for now.

Release Notes:

- N/A
2024-10-03 00:35:56 +02:00
renovate[bot]
e2d613a803 Update Rust crate clap to v4.5.19 (#18660)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [clap](https://redirect.github.com/clap-rs/clap) |
workspace.dependencies | patch | `4.5.18` -> `4.5.19` |

---

### Release Notes

<details>
<summary>clap-rs/clap (clap)</summary>

###
[`v4.5.19`](https://redirect.github.com/clap-rs/clap/blob/HEAD/CHANGELOG.md#4519---2024-10-01)

[Compare
Source](https://redirect.github.com/clap-rs/clap/compare/v4.5.18...v4.5.19)

##### Internal

-   Update dependencies

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 17:39:32 -04:00
Marshall Bowers
6f4385e737 Sort dependencies in Cargo.toml files (#18657)
This PR sorts the dependencies in various `Cargo.toml` files after
#18414.

Release Notes:

- N/A
2024-10-02 16:26:48 -04:00
Marshall Bowers
9565a90528 collab: Revert changes to Clickhouse event rows (#18654)
This PR reverts the changes to the Clickhouse event rows that were
included in https://github.com/zed-industries/zed/pull/18414.

The changes don't seem to be correct, as they make the row structs
differ from the underlying table schema.

Release Notes:

- N/A
2024-10-02 16:10:25 -04:00
Conrad Irwin
3a5deb5c6f Replace isahc with async ureq (#18414)
REplace isahc with ureq everywhere gpui is used.

This should allow us to make http requests without libssl; and avoid a
long-tail of panics caused by ishac.

Release Notes:

- (potentially breaking change) updated our http client

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
2024-10-02 12:30:48 -07:00
renovate[bot]
f809787275 Update cloudflare/wrangler-action digest to 168bc28 (#18651)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
|
[cloudflare/wrangler-action](https://redirect.github.com/cloudflare/wrangler-action)
| action | digest | `f84a562` -> `168bc28` |

---

### Configuration

📅 **Schedule**: Branch creation - "after 3pm on Wednesday" in timezone
America/New_York, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

Release Notes:

- N/A

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC45Ny4wIiwidXBkYXRlZEluVmVyIjoiMzguOTcuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-02 15:23:22 -04:00
Kirill Bulatov
778dedec6c Prepare to sync other kinds of settings (#18616)
This PR does not change how things work for settings, but lays the
ground work for the future functionality.
After this change, Zed is prepared to sync more than just
`settings.json` files from local worktree and user config.

* ssh tasks

Part of this work is to streamline the task sync mechanism.
Instead of having an extra set of requests to fetch the task contents
from the server (as remote-via-collab does now and does not cover all
sync cases), we want to reuse the existing mechanism for synchronizing
user and local settings.

* editorconfig

Part of the task is to sync .editorconfig file changes to everyone which
involves sending and storing those configs.


Both ssh (and remove-over-collab) .zed/tasks.json and .editorconfig
files behave similar to .zed/settings.json local files: they belong to a
certain path in a certain worktree; may update over time, changing Zed's
functionality; can be merged hierarchically.
Settings sync follows the same "config file changed -> send to watchers
-> parse and merge locally and on watchers" path that's needed for both
new kinds of files, ergo the messaging layer is extended to send more
types of settings for future watch & parse and merge impls to follow.

Release Notes:

- N/A
2024-10-02 22:00:40 +03:00
Marshall Bowers
7c4615519b editor: Ensure proposed changes editor is syntax-highlighted when opened (#18648)
This PR fixes an issue where the proposed changes editor would not have
any syntax highlighting until a modification was made.

When creating the branch buffer we reparse the buffer to rebuild the
syntax map.

Release Notes:

- N/A
2024-10-02 14:23:59 -04:00
Marshall Bowers
0e8276560f language: Update buffer doc comments (#18646)
This PR updates the doc comments in `buffer.rs` to use the standard
style for linking to other items.

Release Notes:

- N/A
2024-10-02 14:10:19 -04:00
Mikayla Maki
209ebb0c65 Revert "Fix blurry cursor on Wayland at a scale other than 100%" (#18642)
Closes #17771

Reverts zed-industries/zed#17496

This PR turns out to need more work than I thought when I merged it. 

Release Notes:

- Linux: Fix a bug where the cursor would be the wrong size on Wayland
2024-10-02 10:44:16 -07:00
Danilo Leal
a5f50e5c1e Tweak warning diagnostic toggle (#18637)
This PR adds color to the warning diagnostic toggle, so that, if it's
turned on, the warning icon is yellow. And, in the opposite case, it's
muted.

| Turned on | Turned off |
|--------|--------|
| <img width="1136" alt="Screenshot 2024-10-02 at 6 08 30 PM"
src="https://github.com/user-attachments/assets/be64738b-4c14-41d4-b1d4-ad788cf9e72b">
| <img width="1136" alt="Screenshot 2024-10-02 at 6 08 36 PM"
src="https://github.com/user-attachments/assets/d144ff50-4bf6-4c23-925a-05bcbbcd8b9d">
|

---

Release Notes:

- N/A
2024-10-02 13:57:20 -03:00
Danilo Leal
5aaaed52fc Adjust spacing and sizing of buffer search bar icon buttons (#18638)
This PR mostly makes all of the search bar icon buttons all squared and
adjusts the spacing between them, as well as the additional input that
appears when you toggle the "Replace all" action.

<img width="900" alt="Screenshot 2024-10-02 at 6 08 30 PM"
src="https://github.com/user-attachments/assets/86d50a3b-94bd-4c6a-822e-5f7f7b2e2707">

---

Release Notes:

- N/A
2024-10-02 13:57:03 -03:00
Junseong Park
845991c0e5 docs: Add missing UI font settings to "Configuring Zed" (#18267)
- Add missing `ui_font` options in `configuring-zed.md`

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-02 12:35:35 -04:00
Marshall Bowers
167af4bc1d Use const over static for string literals (#18635)
I noticed a few places where we were storing `&'static str`s in
`static`s instead of `const`s.

This PR updates them to use `const`.

Release Notes:

- N/A
2024-10-02 12:33:13 -04:00
Victor Roetman
2cd12f84de docs: Add FIPS mode error to Linux troubleshooting (#18407)
- Closes: #18335
Update linux.md with a workaround for the
```
crypto/fips/fips.c:154: OpenSSL internal error: FATAL FIPS SELFTEST FAILURE
```
error when using bundled libssl and libcrypto.

Co-authored-by: Peter Tripp <peter@zed.dev>
2024-10-02 12:18:41 -04:00
Joseph T Lyons
028d7a624f v0.157.x dev 2024-10-02 11:03:57 -04:00
Marshall Bowers
cfd61f9337 Clean up formatting in Cargo.toml (#18632)
This PR cleans up some formatting in some `Cargo.toml` files.

Release Notes:

- N/A
2024-10-02 10:38:23 -04:00
Marshall Bowers
21336eb124 docs: Add note about forking the extensions repo to a personal GitHub account (#18631)
This PR adds a note to the docs encouraging folks to fork the
`zed-industries/extensions` repo to a personal GitHub account rather
than a GitHub organization, as this makes life easier for everyone.

Release Notes:

- N/A
2024-10-02 10:10:53 -04:00
Danilo Leal
8a18c94f33 Make slash command descriptions consistent (#18595)
This PR adds a description constant in most of the slash command files
so that both the editor _and_ footer pickers use the same string. In
terms of copywriting, I did some tweaking to reduce the longer ones a
bit. Also standardized them all to use sentence case, as opposed to each
instance using a different convention. The editor picker needs more
work, though, given the arguments and descriptions are being cut at the
moment. This should happen in a follow-up!

<img width="900" alt="Screenshot 2024-10-01 at 7 25 19 PM"
src="https://github.com/user-attachments/assets/e8759eff-0de9-4a4d-a026-366d85507b3c">

---

Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-02 10:35:50 -03:00
Roy Williams
82d3fcdf4b Tweak assistant prompt to only fix diagnostic issues when requested to do so (#18596)
Release Notes:

- Assistant: Make the model less likely to incorporate diagnostic
information when not requested to fix any issues.
 
![CleanShot 2024-10-01 at 13 44
08](https://github.com/user-attachments/assets/f0e9a132-6cac-4dc6-889f-467e59ec8bbc)
2024-10-02 09:29:11 -04:00
Piotr Osiewicz
e01bc6765d editor: Fix "Reveal in File Manager" not working with multibuffers (#18626)
Additionally, mark context menu entry as disabled when the action would
fail (untitled buffer, collab sessions).

Supersedes #18584 

Release Notes:

- Fixed "Reveal in Finder/File Manager", "Copy Path", "Copy Relative
Path" and "Copy file location" actions not working with multibuffers.
2024-10-02 13:45:07 +02:00
Patrick
fd94c2b3fd Keep tab position when closing tabs (#18168)
- Closes #18036

Release Notes:

- N/A
2024-10-02 13:44:42 +02:00
loczek
0ee1d7ab26 Add snippet commands (#18453)
Closes #17860
Closes #15403

Release Notes:

- Added `snippets: configure snippets` command to create and modify
snippets
- Added `snippets: open folder` command for opening the
`~/.config/zed/snippets` directory


https://github.com/user-attachments/assets/fd9e664c-44b1-49bf-87a8-42b9e516f12f
2024-10-02 13:27:16 +02:00
Bennet Bo Fenner
b3cdd2ccff ssh remoting: Fix ssh process not being cleaned up when connection is closed (#18623)
We introduced a memory leak in #18572, which meant that `Drop` was never
called on `SshRemoteConnection`, meaning that the ssh process kept
running

Co-Authored-by: Thorsten <thorsten@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Thorsten <thorsten@zed.dev>
2024-10-02 13:21:19 +02:00
Roman Zipp
e80cbab93f Fix docs format_on_save value is not a boolean (#18619)
Fixed [Configuring
Languages](https://zed.dev/docs/configuring-languages) docs using
boolean value for `format_on_save` option although it accepts string
values of `"on"` or `"off"`

Details:

The documentation on [configuring
languages](https://zed.dev/docs/configuring-languages) states the use of
boolean values for the `format_on_save` option although the
[configuration
reference](https://zed.dev/docs/configuring-zed#format-on-save) only
allows the usage of string values `"on"` or `"off"`. In fact using
boolean values will not work and won't translate to `on` or `off`

Release Notes:

- N/A
2024-10-02 14:03:23 +03:00
Max Brunsfeld
563a1dcbab Fix panic when opening proposed changes editor with reversed ranges (#18599)
Closes https://github.com/zed-industries/zed/issues/18589

Release Notes:

- N/A

Co-authored-by: Antonio <antonio@zed.dev>
2024-10-01 12:58:21 -06:00
Max Brunsfeld
7dcb0de28c Keep all hunks expanded in proposed change editor (#18598)
Also, fix visual bug when pressing escape with a non-empty selection in
a deleted text block.

Release Notes:

- N/A

Co-authored-by: Antonio <antonio@zed.dev>
2024-10-01 12:58:12 -06:00
Junkui Zhang
9b148f3dcc Limit the value can be set for font weight (#18594)
Closes #18531



This PR limits the range of values that can be set for `FontWeight`.
Since any value less than 1.0 or greater than 999.9 causes Zed to crash
on Windows, I’ve restricted `FontWeight` to this range.

I could apply this constraint only on Windows, but considering the
documentation at https://zed.dev/docs/configuring-zed#buffer-font-weight
indicates that `FontWeight` should be between 100 and 900, I thought it
might be a good idea to apply this restriction in the settings.


Release Notes:

- Changed `ui_font_weight` and `buffer_font_weight` settings to require
values to be between `100` and `950` (inclusive).

---------

Co-authored-by: Marshall Bowers <elliott.codes@gmail.com>
2024-10-01 13:32:31 -04:00
Max Brunsfeld
d14e36b323 Add an apply button to hunks in proposed changes editor (#18592)
Release Notes:

- N/A

---------

Co-authored-by: Antonio <antonio@zed.dev>
Co-authored-by: Nathan <nathan@zed.dev>
2024-10-01 11:07:52 -06:00
Marshall Bowers
eb962b7bfc editor: Include proposed changes editor in navigation history (#18593)
This PR makes it so the proposed changes editor works with the workspace
navigation history.

This allows for easily navigating back to the proposed changes editor
after opening one of the excerpts into the base buffer.

Release Notes:

- N/A
2024-10-01 13:05:50 -04:00
Marshall Bowers
280b8a89ea editor: Allow opening excerpts from proposed changes editor (#18591)
This PR adds the ability to open excerpts in the base buffer from the
proposed changes editor.

Release Notes:

- N/A
2024-10-01 12:40:18 -04:00
Kirill Bulatov
051627c449 Project panel horizontal scrollbar (#18513)
<img width="389" alt="image"
src="https://github.com/user-attachments/assets/c6718c6e-0fe1-40ed-b3db-7d576c4d98c8">


https://github.com/user-attachments/assets/734f1f52-70d9-4308-b1fc-36c7cfd4dd76

Closes https://github.com/zed-industries/zed/issues/7001
Closes https://github.com/zed-industries/zed/issues/4427
Part of https://github.com/zed-industries/zed/issues/15324
Part of https://github.com/zed-industries/zed/issues/14551

* Adjusts a `UniformList` to have a horizontal sizing behavior: the old
mode forced all items to have the size of the list exactly.
A new mode (with corresponding `ListItems` having `overflow_x` enabled)
lays out the uniform list elements with width of its widest element,
setting the same width to the list itself too.

* Using the new behavior, adds a new scrollbar into the project panel
and enhances its file name editor to scroll it during editing of long
file names

* Also restyles the scrollbar a bit, making it narrower and removing its
background

* Changes the project_panel.scrollbar.show settings to accept `null` and
be `null` by default, to inherit `editor`'s scrollbar settings. All
editor scrollbar settings are supported now.

Release Notes:

- Added a horizontal scrollbar to project panel
([#7001](https://github.com/zed-industries/zed/issues/7001))
([#4427](https://github.com/zed-industries/zed/issues/4427))

---------

Co-authored-by: Piotr Osiewicz <piotr@zed.dev>
2024-10-01 18:32:16 +03:00
pantheraleo-7
68d6177d37 docs: Correct typo in configuring-zed.md (#18580)
Release Notes:

- N/A
2024-10-01 18:09:34 +03:00
Peter Tripp
1be24f7739 Rename proto language to Proto (#18559)
All the other languages are capitalized. Proto should be too.
2024-10-01 09:31:03 -04:00
Junkui Zhang
6336248c1a windows: Revert "Fix hide, activate method on Windows to hide/show application" (#18571)
This PR reverts the changes introduced via #18164. As shown in the video
below, once you `hide` the app, there is essentially no way to bring it
back. I must emphasize that the window logic on Windows is entirely
different from macOS. On macOS, when you `hide` an app, its icon always
remains visible in the dock, and you can always bring the hidden app
back by clicking that icon. However, on Windows, there is no such
mechanism—the app is literally hidden.

I think the `hide` feature should be macOS-only.



https://github.com/user-attachments/assets/65c8a007-eedb-4444-9499-787b50f2d1e9



Release Notes:

- N/A
2024-10-01 13:58:40 +03:00
Thorsten Ball
7ce8797d78 ssh remoting: Add infrastructure to handle reconnects (#18572)
This restructures the code in `remote` so that it's easier to replace
the current SSH connection with a new one in case of
disconnects/reconnects.

Right now, it successfully reconnects, BUT we're still missing the big
piece on the server-side: keeping the server process alive and
reconnecting to the same process that keeps the project-state.

Release Notes:

- N/A

---------

Co-authored-by: Bennet <bennet@zed.dev>
2024-10-01 12:16:44 +02:00
Michael Sloan
527c9097f8 linux: Various X11 scroll improvements (#18484)
Closes  #14089, #14416, #15970, #17230, #18485

Release Notes:

- Fixed some cases where Linux X11 mouse scrolling doesn't work at all
(#14089, ##15970, #17230)
- Fixed handling of switching between Linux X11 devices used for
scrolling (#14416, #18485)

Change details:

Also includes the commit from PR #18317 so I don't have to deal with
merge conflicts.

* Now uses valuator info from slave pointers rather than master. This
hopefully fixes remaining cases where scrolling is fully
broken. https://github.com/zed-industries/zed/issues/14089,
https://github.com/zed-industries/zed/issues/15970,
https://github.com/zed-industries/zed/issues/17230

* Per-device recording of "last scroll position" used to calculate
deltas. This meant that swithing scroll devices would cause a sudden
jump of scroll position, often to the beginning or end of the
file (https://github.com/zed-industries/zed/issues/14416).

* Re-queries device metadata when devices change, so that newly
plugged in devices will work, and re-use of device-ids don't use old
metadata with a new device.

* xinput 2 documentation describes support for multiple master
devices. I believe this implementation will support that, since now it
just uses `DeviceInfo` from slave devices. The concept of master
devices is only used in registering for events.

* Uses popcount+bit masking to resolve axis indexes, instead of
iterating bit indices.

---------

Co-authored-by: Thorsten Ball <mrnugget@gmail.com>
2024-10-01 09:14:40 +02:00
Jason Lee
72be8c5d14 gpui: Fix hide, activate method on Windows to hide/show application (#18164)
Release Notes:

- N/A

Continue #18161 to fix `cx.hide`, `cx.activate` method on Windows to
hide/show application.

## After


https://github.com/user-attachments/assets/fe0070f9-7844-4c2a-b859-3e22ee4b8d22

---------

Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2024-09-30 23:20:24 -07:00
Alvaro Parker
8d795ff882 Fix file watching for symlinks (#17609)
Closes #17605

Watches for target paths if file watched is a symlink in Linux. 
This will check if the generated `notify::Event` has any paths matching
the `root_path` and if the file is a symlink it will also check if the
path matches the `target_root_path` (the path that the symlink is
pointing to)

Release Notes:

- Added file watching for symlinks
2024-09-30 23:04:35 -07:00
Jason Lee
39be9e5949 gpui: Fix show: false support on Windows to create an invisible window (#18161)
Release Notes:

- N/A
- 
The `show` of WindowOptions is valid on macOS but not on Windows, this
changes to fix it to support create an invisible window.

```bash
cargo run -p gpui --example window
```

## Before



https://github.com/user-attachments/assets/4157bdaa-39a7-44df-bbdc-30b00e9c61e9


## After



https://github.com/user-attachments/assets/d48fa524-0caa-4f87-932d-01d7a468c488


https://github.com/user-attachments/assets/dd052f15-c8db-4a2a-a6af-a7c0ffecca84
2024-09-30 18:25:02 -07:00
Peter Tripp
1d2172aba8 docs: Correct glibc requirements (#18554) 2024-09-30 21:07:10 -04:00
Patrick MARIE
a752bbcee8 Fix linux double click (#18504)
Closes #17573

Release Notes:

- Check that double clicks on Linux are triggered by same button.
2024-09-30 16:51:05 -07:00
Jason Lee
938a0679c0 gpui: Fix img element to auto size when only have width or height (#17994)
Release Notes:

- N/A

---

We may only want to set the height of an image to limit the size and
make the width adaptive.

In HTML, we will only set width or height, and the other side will adapt
and maintain the original image ratio.

I changed this because I had a logo image that only to be limited in
height, and then I found that setting the height of the `img` alone
would not display correctly.

I also tried to set `ObjectFit` in this Demo, but it seems that none of
them can achieve the same effect as "After".

## Before
<img width="809" alt="before 2024-09-18 164029"
src="https://github.com/user-attachments/assets/7ba559ed-e53b-43e6-a072-93c8ba5b14ee">

## After
<img width="749" alt="after 2024-09-18 172003"
src="https://github.com/user-attachments/assets/51ee2eba-76b3-400a-abbf-de0e9c4021e2">
2024-09-30 16:39:19 -07:00
Junkui Zhang
77506afd83 windows: Implement copy/paste images (#17852)
**Clipboard Behavior on Windows Under This PR:**

| User Action | Zed’s Behavior |
| ------------------- |
-------------------------------------------------- |
| Paste PNG | Worked |
| Paste JPEG | Worked |
| Paste WebP | Worked, but not in the way you expect (see Issue section
below) |
| Paste GIF | Partially worked (see Issue section below) |
| Paste SVG | Partially worked (see Issue section below) |
| Paste BMP | Worked, but not in the way you expect (see Issue section
below) |
| Paste TIFF | Worked, but not in the way you expect (see Issue section
below) |
| Paste Files         | Worked, same behavior as macOS              |
| Copy image in Zed | Not tested, as I couldn’t find a way to copy
images |

---

**Differences Between the Windows and macOS Clipboard**

The clipboard functionality on Windows differs significantly from macOS.
On macOS, there can be multiple items in the clipboard, whereas, on
Windows, the clipboard holds only a single item. You can retrieve
different formats from the clipboard, but they are all just different
representations of the same item.

For example, when you copy a JPG image from Microsoft Word, the
clipboard will contain data in several formats:

- Microsoft Office proprietary data
- JPG format data
- PNG format data
- SVG format data

Please note that these formats all represent the same image, just in
different formats. This is due to compatibility concerns on Windows, as
various applications support different formats. Ideally, multiple
formats should be placed on the clipboard to support more software.
However, in general, supporting PNG will cover 99% of software, like
Chrome, which only supports PNG and BMP formats.

Additionally, since the clipboard on Windows only contains a single
item, special handling is required when copying multiple objects, such
as text and images. For instance, if you copy both text and an image
simultaneously in Microsoft Word, Microsoft places the following data on
the clipboard:

- Microsoft Office proprietary data containing a lot of content such as
text fonts, sizes, italics, positioning, image size, content, etc.
- RTF data representing the above content in RTF format
- HTML data representing the content in HTML format
- Plain text data

Therefore, for the current `ClipboardItem` implementation, if there are
multiple `ClipboardEntry` objects to be placed on the clipboard, RTF or
HTML formats are required. This PR does not support this scenario, and
only supports copying or pasting a single item from the clipboard.

---

**Known Issues**

- **WebP, BMP, TIFF**: These formats are not explicitly supported in
this PR. However, as mentioned earlier, in most cases, there are
corresponding PNG format data on the clipboard. This PR retrieves data
via PNG format, so users copying images in these formats from other
sources will still see the images displayed correctly.
  
- **GIF**: In this PR, GIFs are displayed, but for GIF images with
multiple frames, the image will not animate and will freeze on a single
frame. Since I observed the same behavior on macOS, I believe this is
not an issue with this PR.

- **SVG**: In this PR, only the top-left corner of the SVG image is
displayed. Again, I observed the same behavior on macOS, so I believe
this issue is not specific to this PR.

--- 

I hope this provides a clearer understanding. Any feedback or
suggestions on how to improve this are welcome.

Release Notes:

- N/A
2024-09-30 16:29:23 -07:00
Junkui Zhang
ecb7144b95 windows: Fix can not set folder for FileSaveDialog (#17708)
Closes #17622
Closes #17682

The story here is that `SHCreateItemFromParsingName` dose not accept UNC
path.

Video:



https://github.com/user-attachments/assets/f4f7f671-5ab5-4965-9158-e7a79ac02654



Release Notes:

- N/A
2024-09-30 16:26:20 -07:00
maan2003
837756198f linux/wayland: Add support for pasting images (#17671)
Release Notes:

- You can now paste images into the Assistant Panel to include them as
context on Linux wayland
2024-09-30 16:25:32 -07:00
Andrey Arutiunian
eb9fd62a90 Fix rendering of markdown tables (#18315)
- Closes: https://github.com/zed-industries/zed/issues/11024

## Release Notes:

- Improved Markdown Preview rendering of tables

## Before:


![image](https://github.com/user-attachments/assets/25f05604-38a9-4bde-901c-6d53a5d9d94d)

<img width="2035" alt="Screenshot 2024-09-25 at 05 47 19"
src="https://github.com/user-attachments/assets/a30c56f5-4793-44c2-8527-294189f9e724">

## Now:


![image](https://github.com/user-attachments/assets/ce06f045-d0db-4b8c-a1fc-2811d35f2683)


<img width="2040" alt="Screenshot 2024-09-25 at 05 47 48"
src="https://github.com/user-attachments/assets/76e5d217-9110-4c5d-9fad-dc63ae0b75f4">

## Note:

I'm not a Rust programmer and this is my first PR in Zed (because i just
want to fix this, so i can view my notes in Markdown in Zed, not slow
Visual Studio Code) - so there may be errors. I'm open for critic a
2024-09-30 15:50:30 -07:00
Peter Tripp
3010dfe038 Support More Linux (#18480)
- Add `script/build-docker`
- Add `script/install-cmake`
- Add `script/install-mold`
- Improve `script/linux` 
  - Add missing dependencies: `jq`, `git`, `tar`, `gzip` as required.
  - Add check for mold
  - Fix Redhat 8.x derivatives (RHEL, Centos, Almalinux, Rocky, Oracle, Amazon)
  - Fix perl libs to be Fedora only
  - Install the best `libstdc++` available on apt distros
  - ArchLinux: run `pacman -Syu` to update repos before installing. 
  - Should work on Raspbian (untested) 

This make it possible to test builds on other distros using docker:
```
./script/build-docker amazonlinux:2023
```
2024-09-30 17:46:21 -04:00
Peter Tripp
432de00e89 ci: Use BuildJet Ubuntu 20.04 runners for better glibc compatibility (#18442)
Use BuildJet Ubuntu 20.04 runners.
- Linux arm64 unchanged (glibc >= 2.35)
- Linux x64 glibc requirement becomes to >= 2.31 (from glibc >= 2.35).

Note: Ubuntu 20.04 repo cmake (3.16.3) is normally too old to build Zed, but `ubuntu-2004` [includes cmake
3.30.3](https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2004-Readme.md#tools).
2024-09-30 17:02:19 -04:00
Peter Tripp
09424edc35 ci: Add script/determine-release-channel (#18476)
- Refactor duplicated inline script from ci.yml to
`script/determine-release-channel`
- Remove references to non-existent '-nightly' release tags

Release Notes:

- N/A
2024-09-30 16:17:21 -04:00
Peter Tripp
74cba2407f ci: Move collab to Dockerfile-collab (#18515)
This makes it possible to have multiple Dockerfiles, each with their own
`.dockerignore`. Previously any docker builds would always include
anything inside `.dockerignore`. I believe this feature may require
`export DOCKER_BUILDKIT=1` but we use that in CI already.
2024-09-30 16:14:26 -04:00
Danilo Leal
053e31994f Fine-tune hunk controls block (#18543)
This PR changes the undo icon and adds a background color so that indent
lines don't bleed through the control block.

<img width="900" alt="Screenshot 2024-09-30 at 5 38 44 PM"
src="https://github.com/user-attachments/assets/4955f0f6-50ce-432f-85b9-1da0172d5e51">

Release Notes:

- N/A
2024-09-30 13:33:20 -03:00
Thorsten Ball
69e698c3be terminal: Fix blinking settings & blinking with custom shape (#18538)
This is a follow-up to #18530 thanks to this comment here:
https://github.com/zed-industries/zed/pull/18530#issuecomment-2382870564

In short: it fixes the `blinking` setting and the `cursor_shape` setting
as it relates to blinking.

Turns out our `blinking` setting was always the wrong value when using
`terminal_controlled` and the terminal _would_ control the blinking.

Example script to test with:

```bash
echo -e "0 normal \x1b[\x30 q"; sleep 2
echo -e "1 blink block \x1b[\x31 q"; sleep 2
echo -e "2 solid block \x1b[\x32 q"; sleep 2
echo -e "3 blink under \x1b[\x33 q"; sleep 2
echo -e "4 solid under \x1b[\x34 q"; sleep 2
echo -e "5 blink vert \x1b[\x35 q"; sleep 2
echo -e "6 solid vert \x1b[\x36 q"; sleep 2
echo -e "0 normal \x1b[\x30 q"; sleep 2

echo -e "color \x1b]12;#00ff00\x1b\\"; sleep 2
echo -e "reset \x1b]112\x1b\\ \x1b[\x30 q"
```

Before the changes in here, this script would set the cursor shape and
the blinking, but the blinking boolean would always be wrong.

This change here makes sure that it works consistently:

- `terminal.cursor_shape` only controls the *default* shape of the
terminal, not the blinking.
- `terminal.blinking = on` means that it's *always* blinking, regardless
of what terminal programs want
- `terminal.blinking = off` means that it's *never* blinking, regardless
of what terminal programs want
- `terminal.blinking = terminal_controlled (default)` means that it's
blinking depending on what terminal programs want. when a terminal
program resets the cursor to default, it sets it back to
`terminal.cursor_shape` if that is set.

Release Notes:

- Fixed the behavior of `{"terminal": {"blinking":
"[on|off|terminal_controlled]"}` to work correctly and to work correctly
when custom `cursor_shape` is set.
- `terminal.cursor_shape` only controls the *default* shape of the
terminal, not the blinking.
- `terminal.blinking = on` means that it's *always* blinking, regardless
of what terminal programs want
- `terminal.blinking = off` means that it's *never* blinking, regardless
of what terminal programs want
- `terminal.blinking = terminal_controlled (default)` means that it's
blinking depending on what terminal programs want. when a terminal
program resets the cursor to default, it sets it back to
`terminal.cursor_shape` if that is set.

Demo:


https://github.com/user-attachments/assets/b3fbeafd-ad58-41c8-9c07-1f03bc31771f

Co-authored-by: Bennet <bennet@zed.dev>
2024-09-30 15:36:35 +02:00
Stanislav Alekseev
215bce1974 Make direct direnv loading default (#18536)
I've been running with direct direnv loading for a while now and haven't
experienced any significant issues other than #18473. Making it default
would make direnv integration more reliable and consistent. I've also
updated the docs a bit to ensure that they represent current status of
direnv integration

Release Notes:

- Made direnv integration use direct (`direnv export json`) mode by
default instead of relying on a shell hook, improving consistency and
reliability of direnv detection
2024-09-30 15:35:36 +02:00
Kirill Bulatov
e64a86ce9f Fix a typo in the multi buffers documentation (#18535)
Closes https://github.com/zed-industries/zed/issues/18533

Release Notes:

- N/A
2024-09-30 15:28:46 +03:00
wannacu
8ae74bc6df gpui: Fix pre-edit position after applying scale factor (#18214)
before:

![image](https://github.com/user-attachments/assets/20590089-3333-4ca8-a371-b07acfbe43f9)

after:

![image](https://github.com/user-attachments/assets/2d25623e-0602-4d24-b563-64e1d2ec3492)

Release Notes:

- N/A
2024-09-30 12:57:59 +02:00
Thorsten Ball
65f6a7e5bc linux/x11: Give title bar inactive bg on mouse down (#18529)
This fixes something that I felt was off for a while. Previously, when
you'd click on the titlebar to move the window, the titlebar would only
change its background once the moving starts, but not on mouse-down.

That felt really off, since the moving is down with mouse-down and move,
so I think giving the user feedback about the mouse-down event makes
more sense.

I know there's a subjectivity to this change, so I'm ready to hear other
opinions, but for now I want to go with this.

Release Notes:

- N/A
2024-09-30 12:39:11 +02:00
Thorsten Ball
533416c5a9 terminal: Make CursorShape configurable (#18530)
This builds on top of @Yevgen's #15840 and combines it with the settings
names introduced in #17572.

Closes #4731.

Release Notes:

- Added a setting for the terminal's default cursor shape. The setting
is `{"terminal": {"cursor_shape": "block"}}``. Possible values: `block`,
`bar`, `hollow`, `underline`.

Demo:


https://github.com/user-attachments/assets/96ed28c2-c222-436b-80cb-7cd63eeb47dd
2024-09-30 12:38:57 +02:00
0hDEADBEAF
57ad5778fa Add a way to explicitly specify RC toolkit path (#18402)
Closes #18393 

Release Notes:

- Added a `ZED_RC_TOOLKIT_PATH` env variable so `winresource` crate can fetch the RC executable path correctly on some configurations
2024-09-30 11:34:44 +03:00
Patrick MARIE
707ccb04d2 Restore paste on middle-click on linux (#18503)
This is a partial revert of e6c1c51b37, which removed the middle-click
pasting on linux (both x11 & wayland). It also restores the
`middle_click_paste` option behavior which became unexistent.

Release Notes:

- Restore Linux middle-click pasting.
2024-09-30 10:27:47 +02:00
VacheDesNeiges
1f72069b42 Improve C++ Tree-sitter queries (#18016)
I made a few tree-sitter queries for improving the highlighting of C++. 

There is one query that I'm not totally certain about and would
appreciate some feedback on it, the one that concerns attributes.

Many editor only highlight the identifier as a keyword (This is the
behavior implemented in this commit), while others, for example the
tree-sitter plugin for neovim, tags the entire attribute for
highlighting (double brackets included). I don't know which one is
preferable. Here are screenshots of the two versions:


![image](https://github.com/user-attachments/assets/4e1b92c8-adc7-4900-a5b1-dc43c98f4c67)


![image](https://github.com/user-attachments/assets/290a13e3-5cb3-45cb-b6d9-3dc3e6a8af2d)


Release Notes:


- Fixed C++ attributes identifiers being wrongly highlighed through the
tag "variable"
- C++ attribute identifiers (nodiscard,deprecated, noreturn, etc.. ) are
now highlighted through the tag "keyword"
- Changed C++ primitives types (void, bool, int, size_t, etc.. ) to no
longer be highlighted with the tag "keyword", they can now be
highlighted by the tag "type.primitive".
- Added a tag "concept" for highlighting C++ concept identifiers. (This
tag name has been chosen to be the same than the one returned by
clangd's semantic tokens)
2024-09-30 10:27:30 +02:00
Kirill Bulatov
ed5eb725f9 Improve language server log view split ergonomics (#18527)
Allows to split log view, and opens it split on the right, same as the
syntax tree view.

Release Notes:

- Improved language server log panel split ergonomics
2024-09-30 11:25:11 +03:00
jansol
3fafdeb1a8 gpui: Fix blur region on Plasma/Wayland (#18465)
Once again aping after what winit does - since we always want to have
the whole window blurred there is apparently no need to specify a blur
region at all. Rounded corners would be the exception, but that is not
possible with the current protocol (it is planned for the vendor-neutral
version though!)

This eliminates the problem where only a fixed region of the window
would get blurred if the window was resized to be larger than at launch.
Also a drive-by comment grammar fix 😉

Release Notes:

- Fixed blur region handling on Plasma/Wayland
2024-09-30 10:09:13 +03:00
Sylvain Brunerie
898d48a574 php: Add syntax highlighting inside heredoc strings (#18368)
PHP heredoc strings make it easy to define string literals over multiple
lines:

```php
    $someString = <<<EOT
        multiline
        text
        EOT;
```

That `EOT` identifier can be anything else, and it is actually being
used in Sublime Text and VS Code to inject syntax highlighting for
another language in said string, depending on the identifier. For
instance, if the identifier is SQL, SQL syntax highlighting will be
applied to the contents of the string. Likewise if the identifier is CSS
or JS.

```php
    $someString = <<<SQL
        SELECT *
        FROM my_table
        SQL;
```

This PR changes the PHP extension so that it supports that feature too.

Release Notes:

- php: Added syntax highlighting inside heredoc strings
2024-09-30 10:02:12 +03:00
Stanislav Alekseev
5b40debb5f Don't stop loading the env if direnv call fails (#18473)
Before this we we would stop loading the environment if the call to
direnv failed, which is not necessary in any way
cc @mrnugget

Release Notes:

- Fixed the environment not loading if `direnv` mode is set to `direct`
and `.envrc` is not allowed
2024-09-30 09:54:22 +03:00
Maksim Bondarenkov
e39695bf1c docs: Update msys2 section in development/windows (#18385)
merge after
https://packages.msys2.org/packages/mingw-w64-clang-x86_64-zed is
available. alternatively you can check the
[queue](https://packages.msys2.org/queue) for build status

Zed now compiles and runs under msys2/CLANG64 environment, so change the
docs to give the users a choice of their environment

Release Notes:

- N/A
2024-09-30 09:38:49 +03:00
Tom Wieczorek
77df7e56f7 settings: Make external formatter arguments optional (#18340)
If specifying a formatter in the settings like this:

    "languages": {
      "foo": {
        "formatter": {
          "external": {
            "command": "/path/to/foo-formatter"
          }
        }
      }
    }

Zed will show an error like this:

    Invalid user settings file
    data did not match any variant of untagged enum SingleOrVec

This is because the arguments are not optional. The error is hard to
understand, so let's make the arguments actually optional, which makes
the above settings snippet valid.

Release Notes:

- Make external formatter arguments optional
2024-09-30 09:34:41 +03:00
Piotr Osiewicz
250f2e76eb tasks: Display runnables at the start of folds (#18526)
Release Notes:

- Fixed task indicators not showing up at the starts of folds.
2024-09-30 08:05:51 +02:00
Thorben Kröger
5f35fa5d92 Associate uv.lock files with TOML (#18426)
The `uv` python package manager uses the TOML for it's `uv.lock` file,
see https://docs.astral.sh/uv/guides/projects/#uvlock.

Ref #7808

Release Notes:

- associate `uv.lock` files with the TOML language
2024-09-29 13:54:09 -04:00
Antonio Scandurra
84ce81caf1 Pass Summary::Context to Item::summarize (#18510)
We are going to use this in the multi-buffer to produce a summary for an
`Excerpt` that contains a `Range<Anchor>`.

Release Notes:

- N/A

Co-authored-by: Nathan <nathan@zed.dev>
2024-09-29 10:30:48 -06:00
Joseph T. Lyons
8aeab4800c Continue to redirect to GitHub commits for nightly and dev release notes (#18487)
We are now using the `view release notes locally` action when clicking
on the update toast - the endpoint for this action does not currently
return anything for valid for these channels, as we don't have support
yet for diffing between these builds, so for now, [continue to do what
the `view release notes` action did and just send the user to the commit
view on
GitHub](caffb2733f/crates/auto_update/src/auto_update.rs (L255-L260)).
It is a bit counterintuitive to send the user to the browser when using
the "local" action, but this is just a patch in the interim.

If we make adjustments to our channels to keep the nightly tag stable
and add some sort of unique suffix, like a timestamp, we can then adjust
things to return these in the request body and show them in the editor.

Release Notes:

- N/A
2024-09-28 15:20:32 -04:00
Joseph T. Lyons
1021f0e288 Show release notes locally when showing update notification (#18486)
Closes https://github.com/zed-industries/zed/issues/17527

I think we are ok to switch to using the local action now. There are a
few things we don't support, like media, but we don't include media
directly too often, and I think this might help push the community to
maybe add support for it. That being said, I updated the markdown coming
back from the endpoint to include links to the web version of the
release notes, so they can always hop over to that version, if they
would like.


https://github.com/user-attachments/assets/b4d207a7-1640-48f1-91d0-94537f74116c

All forming of the Markdown happens in the endpoint, so if someone with
a better eye wants to update this, you can do that here:


0e5923e3e7/src/pages/api/release_notes/v2/%5Bchannel_type%5D/%5Bversion%5D.ts (L50-L62)

Release Notes:

- Changed the `view the release notes` button in the update toast to
trigger the local release notes action.
2024-09-28 14:21:13 -04:00
Danilo Leal
675673ed54 Fine-tune hunk control spacing (#18463)
<img width="900" alt="Screenshot 2024-09-28 at 1 09 35 AM"
src="https://github.com/user-attachments/assets/0b9d744f-3b92-488a-bc74-987f5a9d8c6c">

---

Release Notes:

- N/A
2024-09-28 01:45:40 +02:00
Danilo Leal
3737d4eb4f Add tooltip for code actions icon button (#18461)
I have just recently discovered this keybinding myself out of talking to
folks, ha. The tooltip here might ease the discovery for other folks in
the future.

<img width="700" alt="Screenshot 2024-09-27 at 11 04 28 PM"
src="https://github.com/user-attachments/assets/844d3b55-15af-47f7-a8db-5c8832ceba29">

---

Release Notes:

- N/A
2024-09-27 18:25:02 -03:00
Max Brunsfeld
0daa070448 More git hunk highlighting fixes (#18459)
Follow-up to https://github.com/zed-industries/zed/pull/18454

Release Notes:

- N/A
2024-09-27 13:48:37 -07:00
Max Brunsfeld
689da9d0b1 Move git hunk controls to the left side (#18460)
![Screenshot 2024-09-27 at 1 05
14 PM](https://github.com/user-attachments/assets/260a7d05-daa8-4a22-92bc-3b956035227f)

Release Notes:

- N/A
2024-09-27 13:13:55 -07:00
Danilo Leal
1c5be9de4e Capitalize tooltip labels on buffer search (#18458)
For consistency, as this seems to be the pattern we're using overall for
labels and buttons.

---

Release Notes:

- N/A
2024-09-27 17:02:32 -03:00
Kirill Bulatov
d5f67406b0 Install cargo-edito without extra features (#18457)
https://github.com/killercup/cargo-edit/pull/907 removed the feature
from the crate

Release Notes:

- N/A
2024-09-27 22:42:04 +03:00
Max Brunsfeld
c3075dfe9a Fix bugs in diff hunk highlighting (#18454)
Fixes https://github.com/zed-industries/zed/issues/18405

In https://github.com/zed-industries/zed/pull/18313, we introduced a
problem where git addition highlights might spuriously return when
undoing certain changes. It turned out, there were already some cases
where git hunk highlighting was incorrect when editing at the boundaries
of expanded diff hunks.

In this PR, I've introduced a test helper method for more rigorously
(and readably) testing the editor's git state. You can assert about the
entire state of an editor's diff decorations using a formatted diff:

```rust
    cx.assert_diff_hunks(
        r#"
        - use some::mod1;
          use some::mod2;
          const A: u32 = 42;
        - const B: u32 = 42;
          const C: u32 = 42;
          fn main() {
        -     println!("hello");
        +     //println!("hello");
              println!("world");
        +     //
        +     //
          }
          fn another() {
              println!("another");
        +     println!("another");
          }
        - fn another2() {
              println!("another2");
          }
        "#
        .unindent(),
    );
```

This will assert about the editor's actual row highlights, not just the
editor's internal hunk-tracking state.

I rewrote all of our editor diff tests to use these more high-level
assertions, and it caught the new bug, as well as some pre-existing bugs
in the highlighting of added content.

The problem was how we *remove* highlighted rows. Previously, it relied
on supplying exactly the same range as one that we had previously
highlighted. I've added a `remove_highlighted_rows(ranges)` APIs which
is much simpler - it clears out any row ranges that intersect the given
ranges (which is all that we need for the Git diff use case).

Release Notes:

- N/A
2024-09-27 11:14:28 -07:00
423 changed files with 13756 additions and 8500 deletions

View File

@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0

View File

@@ -18,7 +18,7 @@ jobs:
- buildjet-16vcpu-ubuntu-2204
steps:
- name: Checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
ref: ${{ github.event.inputs.branch }}
ssh-key: ${{ secrets.ZED_BOT_DEPLOY_KEY }}
@@ -41,7 +41,7 @@ jobs:
exit 1
;;
esac
which cargo-set-version > /dev/null || cargo install cargo-edit --features vendored-openssl
which cargo-set-version > /dev/null || cargo install cargo-edit
output=$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')
git commit -am "Bump to $output for @$GITHUB_ACTOR" --author "Zed Bot <hi@zed.dev>"
git tag v${output}${tag_suffix}

View File

@@ -7,9 +7,13 @@ on:
- "v[0-9]+.[0-9]+.x"
tags:
- "v*"
paths-ignore:
- "docs/**"
pull_request:
branches:
- "**"
paths-ignore:
- "docs/**"
concurrency:
# Allow only one workflow per any non-`main` branch.
@@ -30,7 +34,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
fetch-depth: 0
@@ -81,7 +85,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -107,7 +111,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -136,7 +140,7 @@ jobs:
runs-on: hosted-windows-1
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -177,7 +181,7 @@ jobs:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
# We need to fetch more than one commit so that `script/draft-release-notes`
# is able to diff between the current and previous tag.
@@ -192,29 +196,12 @@ jobs:
- name: Determine version and release channel
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
set -eu
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
script/determine-release-channel
version=$(script/get-crate-version zed)
channel=$(cat crates/zed/RELEASE_CHANNEL)
echo "Publishing version: ${version} on release channel ${channel}"
echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
expected_tag_name=""
case ${channel} in
stable)
expected_tag_name="v${version}";;
preview)
expected_tag_name="v${version}-pre";;
nightly)
expected_tag_name="v${version}-nightly";;
*)
echo "can't publish a release on channel ${channel}"
exit 1;;
esac
if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
exit 1
fi
- name: Draft release notes
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
mkdir -p target/
# Ignore any errors that occur while drafting release notes to not fail the build.
script/draft-release-notes "$version" "$channel" > target/release-notes.md || true
@@ -232,20 +219,20 @@ jobs:
mv target/x86_64-apple-darwin/release/Zed.dmg target/x86_64-apple-darwin/release/Zed-x86_64.dmg
- name: Upload app bundle (universal) to workflow run if main branch or specific label
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}.dmg
path: target/release/Zed.dmg
- name: Upload app bundle (aarch64) to workflow run if main branch or specific label
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-aarch64.dmg
path: target/aarch64-apple-darwin/release/Zed-aarch64.dmg
- name: Upload app bundle (x86_64) to workflow run if main branch or specific label
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: Zed_${{ github.event.pull_request.head.sha || github.sha }}-x86_64.dmg
@@ -271,7 +258,7 @@ jobs:
timeout-minutes: 60
name: Create a Linux bundle
runs-on:
- buildjet-16vcpu-ubuntu-2204
- buildjet-16vcpu-ubuntu-2004
if: ${{ startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
needs: [linux_tests]
env:
@@ -279,45 +266,24 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
- name: Install Linux dependencies
run: ./script/linux
run: ./script/linux && ./script/install-mold 2.34.0
- name: Determine version and release channel
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
set -eu
version=$(script/get-crate-version zed)
channel=$(cat crates/zed/RELEASE_CHANNEL)
echo "Publishing version: ${version} on release channel ${channel}"
echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
expected_tag_name=""
case ${channel} in
stable)
expected_tag_name="v${version}";;
preview)
expected_tag_name="v${version}-pre";;
nightly)
expected_tag_name="v${version}-nightly";;
*)
echo "can't publish a release on channel ${channel}"
exit 1;;
esac
if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
exit 1
fi
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
script/determine-release-channel
- name: Create Linux .tar.gz bundle
run: script/bundle-linux
- name: Upload Linux bundle to workflow run if main branch or specific label
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-x86_64-unknown-linux-gnu.tar.gz
@@ -347,7 +313,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -357,35 +323,14 @@ jobs:
- name: Determine version and release channel
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
set -eu
version=$(script/get-crate-version zed)
channel=$(cat crates/zed/RELEASE_CHANNEL)
echo "Publishing version: ${version} on release channel ${channel}"
echo "RELEASE_CHANNEL=${channel}" >> $GITHUB_ENV
expected_tag_name=""
case ${channel} in
stable)
expected_tag_name="v${version}";;
preview)
expected_tag_name="v${version}-pre";;
nightly)
expected_tag_name="v${version}-nightly";;
*)
echo "can't publish a release on channel ${channel}"
exit 1;;
esac
if [[ $GITHUB_REF_NAME != $expected_tag_name ]]; then
echo "invalid release tag ${GITHUB_REF_NAME}. expected ${expected_tag_name}"
exit 1
fi
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
script/determine-release-channel
- name: Create and upload Linux .tar.gz bundle
run: script/bundle-linux
- name: Upload Linux bundle to workflow run if main branch or specific label
uses: actions/upload-artifact@50769540e7f4bd5e21e526ee35c689e35e0d6874 # v4
uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4
if: ${{ github.ref == 'refs/heads/main' }} || contains(github.event.pull_request.labels.*.name, 'run-bundling') }}
with:
name: zed-${{ github.event.pull_request.head.sha || github.sha }}-aarch64-unknown-linux-gnu.tar.gz

View File

@@ -14,16 +14,16 @@ jobs:
stale-issue-message: >
Hi there! 👋
We're working to clean up our issue tracker by closing older issues that might not be relevant anymore. Are you able to reproduce this issue in the latest version of Zed? If so, please let us know by commenting on this issue and we will keep it open; otherwise, we'll close it in 10 days. Feel free to open a new issue if you're seeing this message after the issue has been closed.
We're working to clean up our issue tracker by closing older issues that might not be relevant anymore. Are you able to reproduce this issue in the latest version of Zed? If so, please let us know by commenting on this issue and we will keep it open; otherwise, we'll close it in 7 days. Feel free to open a new issue if you're seeing this message after the issue has been closed.
Thanks for your help!
close-issue-message: "This issue was closed due to inactivity; feel free to open a new issue if you're still experiencing this problem!"
close-issue-message: "This issue was closed due to inactivity. If you're still experiencing this problem, feel free to ping a Zed team member to reopen this issue or open a new one."
# We will increase `days-before-stale` to 365 on or after Jan 24th,
# 2024. This date marks one year since migrating issues from
# 'community' to 'zed' repository. The migration added activity to all
# issues, preventing 365 days from working until then.
days-before-stale: 180
days-before-close: 10
days-before-close: 7
any-of-issue-labels: "defect,panic / crash"
operations-per-run: 1000
ascending: true

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:

View File

@@ -12,7 +12,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -36,28 +36,28 @@ jobs:
mdbook build ./docs --dest-dir=../target/deploy/docs/
- name: Deploy Docs
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy target/deploy --project-name=docs
- name: Deploy Install
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: r2 object put -f script/install.sh zed-open-source-website-assets/install.sh
- name: Deploy Docs Workers
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: deploy .cloudflare/docs-proxy/src/worker.js
- name: Deploy Install Workers
uses: cloudflare/wrangler-action@f84a562284fc78278ff9052435d9526f9c718361 # v3
uses: cloudflare/wrangler-action@9681c2997648301493e78cacbfb790a9f19c833f # v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}

View File

@@ -17,7 +17,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
fetch-depth: 0
@@ -36,7 +36,7 @@ jobs:
needs: style
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
fetch-depth: 0
@@ -71,12 +71,16 @@ jobs:
run: doctl registry login
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
- name: Build docker image
run: docker build . --build-arg GITHUB_SHA=$GITHUB_SHA --tag registry.digitalocean.com/zed/collab:$GITHUB_SHA
run: |
docker build -f Dockerfile-collab \
--build-arg GITHUB_SHA=$GITHUB_SHA \
--tag registry.digitalocean.com/zed/collab:$GITHUB_SHA \
.
- name: Publish docker image
run: docker push registry.digitalocean.com/zed/collab:${GITHUB_SHA}
@@ -93,7 +97,7 @@ jobs:
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false

View File

@@ -14,17 +14,20 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
version: 9
- run: |
- name: Prettier Check on /docs
working-directory: ./docs
run: |
pnpm dlx prettier . --check || {
echo "To fix, run from the root of the zed repo:"
echo " cd docs && pnpm dlx prettier . --write && cd .."
false
}
working-directory: ./docs
- name: Check spelling
run: script/check-spelling docs/

View File

@@ -16,7 +16,7 @@ jobs:
- ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false

View File

@@ -27,7 +27,7 @@ jobs:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false

View File

@@ -23,7 +23,7 @@ jobs:
- test
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
fetch-depth: 0
@@ -44,7 +44,7 @@ jobs:
needs: style
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -75,7 +75,7 @@ jobs:
node-version: "18"
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -100,7 +100,7 @@ jobs:
name: Create a Linux *.tar.gz bundle for x86
if: github.repository_owner == 'zed-industries'
runs-on:
- buildjet-16vcpu-ubuntu-2204
- buildjet-16vcpu-ubuntu-2004
needs: tests
env:
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
@@ -109,7 +109,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -117,7 +117,7 @@ jobs:
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install Linux dependencies
run: ./script/linux
run: ./script/linux && ./script/install-mold 2.34.0
- name: Limit target directory size
run: script/clear-target-dir-if-larger-than 100
@@ -149,7 +149,7 @@ jobs:
ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON: ${{ secrets.ZED_CLOUD_PROVIDER_ADDITIONAL_MODELS_JSON }}
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
clean: false
@@ -182,7 +182,7 @@ jobs:
- bundle-linux-arm
steps:
- name: Checkout repo
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0

View File

@@ -8,11 +8,16 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries'
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up uv
uses: astral-sh/setup-uv@v3
with:
python-version: "3.11"
architecture: "x64"
cache: "pip"
- run: pip install -r script/update_top_ranking_issues/requirements.txt
- run: python script/update_top_ranking_issues/main.py --github-token ${{ secrets.GITHUB_TOKEN }} --issue-reference-number 5393
version: "latest"
enable-cache: true
cache-dependency-glob: "script/update_top_ranking_issues/pyproject.toml"
- name: Install Python 3.12
run: uv python install 3.12
- name: Install dependencies
run: uv sync --project script/update_top_ranking_issues -p 3.12
- name: Run script
run: uv run --project script/update_top_ranking_issues script/update_top_ranking_issues/main.py --github-token ${{ secrets.GITHUB_TOKEN }} --issue-reference-number 5393

View File

@@ -8,11 +8,16 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries'
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5
- uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
- name: Set up uv
uses: astral-sh/setup-uv@v3
with:
python-version: "3.11"
architecture: "x64"
cache: "pip"
- run: pip install -r script/update_top_ranking_issues/requirements.txt
- run: python script/update_top_ranking_issues/main.py --github-token ${{ secrets.GITHUB_TOKEN }} --issue-reference-number 6952 --query-day-interval 7
version: "latest"
enable-cache: true
cache-dependency-glob: "script/update_top_ranking_issues/pyproject.toml"
- name: Install Python 3.12
run: uv python install 3.12
- name: Install dependencies
run: uv sync --project script/update_top_ranking_issues -p 3.12
- name: Run script
run: uv run --project script/update_top_ranking_issues script/update_top_ranking_issues/main.py --github-token ${{ secrets.GITHUB_TOKEN }} --issue-reference-number 6952 --query-day-interval 7

View File

@@ -38,6 +38,10 @@
}
}
},
"file_types": {
"Dockerfile": ["Dockerfile*[!dockerignore]"],
"Git Ignore": ["dockerignore"]
},
"hard_tabs": false,
"formatter": "auto",
"remove_trailing_whitespace_on_save": true,

255
Cargo.lock generated
View File

@@ -108,6 +108,19 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "alert_dialog"
version = "0.1.0"
dependencies = [
"gpui",
"menu",
"settings",
"story",
"theme",
"ui",
"workspace",
]
[[package]]
name = "aliasable"
version = "0.1.3"
@@ -341,9 +354,9 @@ dependencies = [
[[package]]
name = "ashpd"
version = "0.9.1"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfe7e0dd0ac5a401dc116ed9f9119cf9decc625600474cb41f0fc0a0050abc9a"
checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9"
dependencies = [
"async-fs 2.1.2",
"async-net 2.0.0",
@@ -535,9 +548,9 @@ dependencies = [
[[package]]
name = "async-compression"
version = "0.4.12"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa"
checksum = "7e614738943d3f68c628ae3dbce7c3daffb196665f82f8c8ea6b65de73c79429"
dependencies = [
"deflate64",
"flate2",
@@ -1578,7 +1591,7 @@ dependencies = [
"bitflags 2.6.0",
"cexpr",
"clang-sys",
"itertools 0.12.1",
"itertools 0.10.5",
"lazy_static",
"lazycell",
"proc-macro2",
@@ -2282,9 +2295,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.18"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
dependencies = [
"clap_builder",
"clap_derive",
@@ -2292,9 +2305,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.18"
version = "4.5.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
dependencies = [
"anstream",
"anstyle",
@@ -2553,6 +2566,7 @@ dependencies = [
"collections",
"ctor",
"dashmap 6.0.1",
"derive_more",
"dev_server_projects",
"editor",
"env_logger",
@@ -3050,18 +3064,18 @@ dependencies = [
[[package]]
name = "cranelift-bforest"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b80c3a50b9c4c7e5b5f73c0ed746687774fc9e36ef652b110da8daebf0c6e0e6"
checksum = "32d69b774780246008783a75edfb943eccc2487b6a43808503a07cd563f2ffde"
dependencies = [
"cranelift-entity",
]
[[package]]
name = "cranelift-bitset"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38778758c2ca918b05acb2199134e0c561fb577c50574259b26190b6c2d95ded"
checksum = "a7d8d71c6b32c1a7cff254c5e5d7359872c1e5e610fbe963472afcddbd9cf303"
dependencies = [
"serde",
"serde_derive",
@@ -3069,9 +3083,9 @@ dependencies = [
[[package]]
name = "cranelift-codegen"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58258667ad10e468bfc13a8d620f50dfcd4bb35d668123e97defa2549b9ad397"
checksum = "3ad3a906f2a3f3590ad9798d59a46959a8593258eb985af722f634723c063a2c"
dependencies = [
"bumpalo",
"cranelift-bforest",
@@ -3092,33 +3106,33 @@ dependencies = [
[[package]]
name = "cranelift-codegen-meta"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "043f0b702e529dcb07ff92bd7d40e7d5317b5493595172c5eb0983343751ee06"
checksum = "cd5e4ee12262a135efbef3ced4ab2153adafe4adc55f36af94f9d73be0f7505d"
dependencies = [
"cranelift-codegen-shared",
]
[[package]]
name = "cranelift-codegen-shared"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7763578888ab53eca5ce7da141953f828e82c2bfadcffc106d10d1866094ffbb"
checksum = "5b9374a2a5f060f72e3080fe1c87c9ff4bef2cbe798faae60daf276fb1a13968"
[[package]]
name = "cranelift-control"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32db15f08c05df570f11e8ab33cb1ec449a64b37c8a3498377b77650bef33d8b"
checksum = "fba3ca2f344bb22d265a928e7c3f5f46e1a2eb41f1393bd53538d07b6ffb5293"
dependencies = [
"arbitrary",
]
[[package]]
name = "cranelift-entity"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5289cdb399381a27e7bbfa1b42185916007c3d49aeef70b1d01cb4caa8010130"
checksum = "a6aef77dfb018eed09d92d4244abe3c1c060cbbd900c24f75ddde7d75d0e781e"
dependencies = [
"cranelift-bitset",
"serde",
@@ -3127,9 +3141,9 @@ dependencies = [
[[package]]
name = "cranelift-frontend"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31ba8ab24eb9470477e98ddfa3c799a649ac5a0d9a2042868c4c952133c234e8"
checksum = "7b1d6954f03d63df1cb95d66153c97df0201862220861349bbd5f583754b1917"
dependencies = [
"cranelift-codegen",
"log",
@@ -3139,15 +3153,15 @@ dependencies = [
[[package]]
name = "cranelift-isle"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b72a3c5c166a70426dcb209bdd0bb71a787c1ea76023dc0974fbabca770e8f9"
checksum = "f8b9b7e088b784796ea8aa5947c1cc12034c1b076a077ec2a5a287da717fa746"
[[package]]
name = "cranelift-native"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46a42424c956bbc31fc5c2706073df896156c5420ae8fa2a5d48dbc7b295d71b"
checksum = "4cab7424083d070669ff3fdeea7c5b4b5013a055aa1ee0532703f17a5f62af64"
dependencies = [
"cranelift-codegen",
"libc",
@@ -3156,9 +3170,9 @@ dependencies = [
[[package]]
name = "cranelift-wasm"
version = "0.111.0"
version = "0.111.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49778df4289933d735b93c30a345513e030cf83101de0036e19b760f8aa09f68"
checksum = "81a9f6d0495984eef1d753ec8748de0b216b37ade16d219f1c0f27d8188d7f77"
dependencies = [
"cranelift-codegen",
"cranelift-entity",
@@ -3729,6 +3743,7 @@ dependencies = [
"multi_buffer",
"ordered-float 2.10.1",
"parking_lot",
"pretty_assertions",
"project",
"rand 0.8.5",
"release_channel",
@@ -3838,9 +3853,9 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "emojis"
version = "0.6.3"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e72f23d65b46527e461b161ab9a126c378aa2249d8a8d15718d23ab1fb4d8786"
checksum = "99e1f1df1f181f2539bac8bf027d31ca5ffbf9e559e3f2d09413b9107b5c02f4"
dependencies = [
"phf",
]
@@ -4144,6 +4159,7 @@ dependencies = [
"snippet_provider",
"task",
"theme",
"tokio",
"toml 0.8.19",
"ui",
"url",
@@ -5146,9 +5162,9 @@ dependencies = [
[[package]]
name = "grid"
version = "0.13.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d196ffc1627db18a531359249b2bf8416178d84b729f3cebeb278f285fb9b58c"
checksum = "be136d9dacc2a13cc70bb6c8f902b414fb2641f8db1314637c6b7933411a8f82"
[[package]]
name = "group"
@@ -5953,9 +5969,9 @@ dependencies = [
[[package]]
name = "ipc-channel"
version = "0.18.2"
version = "0.18.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e46231d1db8ea8f874012b1b87efb9e968f763c577220372a9c7caadce1448da"
checksum = "c7f4c80f2df4fc64fb7fc2cff69fc034af26e6e6617ea9f1313131af464b9ca0"
dependencies = [
"bincode",
"crossbeam-channel",
@@ -5967,7 +5983,7 @@ dependencies = [
"serde",
"tempfile",
"uuid",
"windows 0.48.0",
"windows 0.58.0",
]
[[package]]
@@ -6366,7 +6382,6 @@ dependencies = [
"node_runtime",
"paths",
"project",
"protols-tree-sitter-proto",
"regex",
"rope",
"rust-embed",
@@ -6472,7 +6487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.52.6",
"windows-targets 0.48.5",
]
[[package]]
@@ -7840,9 +7855,9 @@ dependencies = [
[[package]]
name = "parking"
version = "2.2.0"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
@@ -8350,9 +8365,9 @@ dependencies = [
[[package]]
name = "pretty_assertions"
version = "1.4.0"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
@@ -8403,9 +8418,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.87"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a"
dependencies = [
"unicode-ident",
]
@@ -8624,15 +8639,6 @@ version = "2.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "106dd99e98437432fed6519dedecfade6a06a73bb7b2a1e019fdd2bee5778d94"
[[package]]
name = "protols-tree-sitter-proto"
version = "0.2.0"
source = "git+https://github.com/zed-industries/tree-sitter-proto?rev=0848bd30a64be48772e15fbb9d5ba8c0cc5772ad#0848bd30a64be48772e15fbb9d5ba8c0cc5772ad"
dependencies = [
"cc",
"tree-sitter-language",
]
[[package]]
name = "psm"
version = "0.1.21"
@@ -8944,7 +8950,6 @@ dependencies = [
"gpui",
"language",
"log",
"markdown",
"menu",
"ordered-float 2.10.1",
"picker",
@@ -9098,6 +9103,7 @@ dependencies = [
"serde_json",
"smol",
"tempfile",
"thiserror",
"util",
]
@@ -9106,7 +9112,9 @@ name = "remote_server"
version = "0.1.0"
dependencies = [
"anyhow",
"backtrace",
"cargo_toml",
"clap",
"client",
"clock",
"env_logger",
@@ -10060,9 +10068,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.127"
version = "1.0.128"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
dependencies = [
"indexmap 2.4.0",
"itoa",
@@ -10499,6 +10507,20 @@ dependencies = [
"util",
]
[[package]]
name = "snippets_ui"
version = "0.1.0"
dependencies = [
"fuzzy",
"gpui",
"language",
"paths",
"picker",
"ui",
"util",
"workspace",
]
[[package]]
name = "socket2"
version = "0.4.10"
@@ -10589,6 +10611,7 @@ dependencies = [
"libsqlite3-sys",
"parking_lot",
"smol",
"sqlformat",
"thread_local",
"util",
"uuid",
@@ -10605,9 +10628,9 @@ dependencies = [
[[package]]
name = "sqlformat"
version = "0.2.4"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f"
checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
dependencies = [
"nom",
"unicode_categories",
@@ -10854,6 +10877,7 @@ dependencies = [
name = "storybook"
version = "0.1.0"
dependencies = [
"alert_dialog",
"anyhow",
"clap",
"collab_ui",
@@ -10863,6 +10887,7 @@ dependencies = [
"fuzzy",
"gpui",
"indoc",
"isahc_http_client",
"language",
"log",
"menu",
@@ -11261,6 +11286,7 @@ dependencies = [
"project",
"serde",
"serde_json",
"settings",
"theme",
"ui",
"util",
@@ -11269,9 +11295,9 @@ dependencies = [
[[package]]
name = "taffy"
version = "0.4.4"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ec17858c2d465b2f734b798b920818a974faf0babb15d7fef81818a4b2d16f1"
checksum = "9cb893bff0f80ae17d3a57e030622a967b8dbc90e38284d9b4b1442e23873c94"
dependencies = [
"arrayvec",
"grid",
@@ -11345,6 +11371,7 @@ dependencies = [
name = "telemetry_events"
version = "0.1.0"
dependencies = [
"language",
"semantic_version",
"serde",
]
@@ -11394,6 +11421,7 @@ dependencies = [
"gpui",
"libc",
"rand 0.8.5",
"regex",
"release_channel",
"schemars",
"serde",
@@ -11410,12 +11438,12 @@ dependencies = [
[[package]]
name = "terminal_size"
version = "0.3.0"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7"
checksum = "4f599bd7ca042cfdf8f4512b277c02ba102247820f9d9d4a9f521f496751a6ef"
dependencies = [
"rustix 0.38.35",
"windows-sys 0.48.0",
"windows-sys 0.59.0",
]
[[package]]
@@ -11494,7 +11522,6 @@ dependencies = [
"serde_json_lenient",
"serde_repr",
"settings",
"story",
"util",
"uuid",
]
@@ -11541,18 +11568,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.63"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.63"
version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [
"proc-macro2",
"quote",
@@ -11715,6 +11742,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
name = "title_bar"
version = "0.1.0"
dependencies = [
"alert_dialog",
"auto_update",
"call",
"client",
@@ -11731,6 +11759,7 @@ dependencies = [
"pretty_assertions",
"project",
"recent_projects",
"remote",
"rpc",
"serde",
"settings",
@@ -13003,9 +13032,9 @@ dependencies = [
[[package]]
name = "wasmtime"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a5883d64dfc8423c56e3d8df27cffc44db25336aa468e8e0724fddf30a333d7"
checksum = "7e4a5b05e9f1797e557e79f0cf04348eaa7a232596939ef4762838ddf7a6127a"
dependencies = [
"anyhow",
"async-trait",
@@ -13049,9 +13078,9 @@ dependencies = [
[[package]]
name = "wasmtime-asm-macros"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c4dc7e2a379c0dd6be5b55857d14c4b277f43a9c429a9e14403eb61776ae3be"
checksum = "64414227e19556d4372f9688458c5673606de83473eb66cd0514d36ea8808cab"
dependencies = [
"cfg-if",
]
@@ -13082,9 +13111,9 @@ dependencies = [
[[package]]
name = "wasmtime-component-macro"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b07773d1c3dab5f014ec61316ee317aa424033e17e70a63abdf7c3a47e58fcf"
checksum = "d3ead31b73689602225742920adbcd881f5656702c1a3b4830862c0c66731727"
dependencies = [
"anyhow",
"proc-macro2",
@@ -13097,15 +13126,15 @@ dependencies = [
[[package]]
name = "wasmtime-component-util"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e38d735320f4e83478369ce649ad8fe87c6b893220902e798547a225fc0c5874"
checksum = "ab2c778661800e1dcd8ba3e15ff042299709e0a4c512525d9cbb604a04c0421b"
[[package]]
name = "wasmtime-cranelift"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e570d831d0785d93d7d8c722b1eb9a34e0d0c1534317666f65892818358a2da9"
checksum = "9f7ee1f436bcf7d213ef7c2e9d44caffcd57e540ccf997d013384c2ae9b82db7"
dependencies = [
"anyhow",
"cfg-if",
@@ -13127,9 +13156,9 @@ dependencies = [
[[package]]
name = "wasmtime-environ"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5fe80dfbd81687431a7d4f25929fae1ae96894786d5c96b14ae41164ee97377"
checksum = "fa8c33adfb3b9f8d6ef716bc55aea5e6b2275cd5a6721ec8c837d1cb0c471516"
dependencies = [
"anyhow",
"cpp_demangle",
@@ -13154,9 +13183,9 @@ dependencies = [
[[package]]
name = "wasmtime-fiber"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f39043d13c7b58db69dc9a0feb191a961e75a9ec2402aebf42de183c022bb8a"
checksum = "9f3227ed807c2dda9dd770c241023fcd6e48e6722c1c26ff79fc3604d412e884"
dependencies = [
"anyhow",
"cc",
@@ -13169,9 +13198,9 @@ dependencies = [
[[package]]
name = "wasmtime-jit-icache-coherence"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d15de8429db996f0d17a4163a35eccc3f874cbfb50f29c379951ea1bbb39452e"
checksum = "fa89fc440f0edca882ba6d1890608898e6f0193afdc504c0a64478ec53622bd6"
dependencies = [
"anyhow",
"cfg-if",
@@ -13181,15 +13210,15 @@ dependencies = [
[[package]]
name = "wasmtime-slab"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f68d38fa6b30c5e1fc7d608263062997306f79e577ebd197ddcd6b0f55d87d1"
checksum = "682b7a5b6772c4e4de8c696fc619ec97930b5e89098db9bee22c1136e002438b"
[[package]]
name = "wasmtime-types"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6634e7079d9c5cfc81af8610ed59b488cc5b7f9777a2f4c1667a2565c2e45249"
checksum = "4a95ea5572f8c3ffe777af21aa00a92097ded291a342fecad9f2c6a972ecea99"
dependencies = [
"anyhow",
"cranelift-entity",
@@ -13201,9 +13230,9 @@ dependencies = [
[[package]]
name = "wasmtime-versioned-export-macros"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3850e3511d6c7f11a72d571890b0ed5f6204681f7f050b9de2690e7f13123fed"
checksum = "ac3621bfccd4e4336ae141d62b96e96316c0f23c47d64e9700594ebe3c4d9a10"
dependencies = [
"proc-macro2",
"quote",
@@ -13243,9 +13272,9 @@ dependencies = [
[[package]]
name = "wasmtime-winch"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a25199625effa4c13dd790d64bd56884b014c69829431bfe43991c740bd5bc1"
checksum = "d1d3e99f6bba37864487c9356398667699935b9cfa3655ed2b153b9428b3dd21"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -13260,9 +13289,9 @@ dependencies = [
[[package]]
name = "wasmtime-wit-bindgen"
version = "24.0.0"
version = "24.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cb331ac7ed1d5ba49cddcdb6b11973752a857148858bb308777d2fc5584121f"
checksum = "ee0f4524da226d2cb503d794c8928de6bc24878758cebd4e383c946e9fdb8b3a"
dependencies = [
"anyhow",
"heck 0.4.1",
@@ -13529,7 +13558,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.59.0",
"windows-sys 0.48.0",
]
[[package]]
@@ -13540,9 +13569,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winch-codegen"
version = "0.22.0"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "073efe897d9ead7fc609874f94580afc831114af5149b6a90ee0a3a39b497fe0"
checksum = "c139fb9298d9651b6869afd544e567ca2448cd5f5ddcb24e4bb86a1ee187c8b3"
dependencies = [
"anyhow",
"cranelift-codegen",
@@ -13555,15 +13584,6 @@ dependencies = [
"wasmtime-environ",
]
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows"
version = "0.54.0"
@@ -14103,6 +14123,7 @@ dependencies = [
"parking_lot",
"postage",
"project",
"release_channel",
"remote",
"schemars",
"serde",
@@ -14298,9 +14319,9 @@ dependencies = [
[[package]]
name = "yansi"
version = "0.5.1"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yazi"
@@ -14383,7 +14404,7 @@ dependencies = [
[[package]]
name = "zed"
version = "0.156.0"
version = "0.158.0"
dependencies = [
"activity_indicator",
"anyhow",
@@ -14467,6 +14488,7 @@ dependencies = [
"simplelog",
"smol",
"snippet_provider",
"snippets_ui",
"supermaven",
"sysinfo",
"tab_switcher",
@@ -14524,7 +14546,7 @@ dependencies = [
[[package]]
name = "zed_dart"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"zed_extension_api 0.1.0",
]
@@ -14629,7 +14651,7 @@ dependencies = [
[[package]]
name = "zed_php"
version = "0.2.0"
version = "0.2.1"
dependencies = [
"zed_extension_api 0.1.0",
]
@@ -14641,6 +14663,13 @@ dependencies = [
"zed_extension_api 0.1.0",
]
[[package]]
name = "zed_proto"
version = "0.2.0"
dependencies = [
"zed_extension_api 0.1.0",
]
[[package]]
name = "zed_purescript"
version = "0.0.1"

View File

@@ -99,6 +99,7 @@ members = [
"crates/settings_ui",
"crates/snippet",
"crates/snippet_provider",
"crates/snippets_ui",
"crates/sqlez",
"crates/sqlez_macros",
"crates/story",
@@ -119,6 +120,7 @@ members = [
"crates/time_format",
"crates/title_bar",
"crates/ui",
"crates/alert_dialog",
"crates/ui_input",
"crates/ui_macros",
"crates/util",
@@ -152,6 +154,7 @@ members = [
"extensions/php",
"extensions/perplexity",
"extensions/prisma",
"extensions/proto",
"extensions/purescript",
"extensions/ruff",
"extensions/ruby",
@@ -174,6 +177,7 @@ members = [
default-members = ["crates/zed"]
[workspace.dependencies]
#
# Workspace member crates
#
@@ -219,7 +223,6 @@ go_to_line = { path = "crates/go_to_line" }
google_ai = { path = "crates/google_ai" }
gpui = { path = "crates/gpui" }
gpui_macros = { path = "crates/gpui_macros" }
handlebars = "4.3"
headless = { path = "crates/headless" }
html_to_markdown = { path = "crates/html_to_markdown" }
http_client = { path = "crates/http_client" }
@@ -275,6 +278,7 @@ settings = { path = "crates/settings" }
settings_ui = { path = "crates/settings_ui" }
snippet = { path = "crates/snippet" }
snippet_provider = { path = "crates/snippet_provider" }
snippets_ui = { path = "crates/snippets_ui" }
sqlez = { path = "crates/sqlez" }
sqlez_macros = { path = "crates/sqlez_macros" }
story = { path = "crates/story" }
@@ -295,6 +299,7 @@ theme_selector = { path = "crates/theme_selector" }
time_format = { path = "crates/time_format" }
title_bar = { path = "crates/title_bar" }
ui = { path = "crates/ui" }
alert_dialog = { path = "crates/alert_dialog" }
ui_input = { path = "crates/ui_input" }
ui_macros = { path = "crates/ui_macros" }
util = { path = "crates/util" }
@@ -316,6 +321,7 @@ any_vec = "0.14"
anyhow = "1.0.86"
arrayvec = { version = "0.7.4", features = ["serde"] }
ashpd = "0.9.1"
async-compat = "0.2.1"
async-compression = { version = "0.4", features = ["gzip", "futures-io"] }
async-dispatcher = "0.1"
async-fs = "1.6"
@@ -354,10 +360,11 @@ futures-batch = "0.6.1"
futures-lite = "1.13"
git2 = { version = "0.19", default-features = false }
globset = "0.4"
handlebars = "4.3"
heed = { version = "0.20.1", features = ["read-txn-no-tls"] }
hex = "0.4.3"
hyper = "0.14"
html5ever = "0.27.0"
hyper = "0.14"
ignore = "0.4.22"
image = "0.25.1"
indexmap = { version = "1.6.2", features = ["serde"] }
@@ -380,9 +387,9 @@ ordered-float = "2.1.1"
palette = { version = "0.7.5", default-features = false, features = ["std"] }
parking_lot = "0.12.1"
pathdiff = "0.2"
profiling = "1"
postage = { version = "0.5", features = ["futures-traits"] }
pretty_assertions = "1.3.0"
profiling = "1"
prost = "0.9"
prost-build = "0.9"
prost-types = "0.9"
@@ -416,6 +423,7 @@ similar = "1.3"
simplelog = "0.12.2"
smallvec = { version = "1.6", features = ["union"] }
smol = "1.2"
sqlformat = "0.2"
strsim = "0.11"
strum = { version = "0.25.0", features = ["derive"] }
subtle = "2.5.0"
@@ -450,15 +458,14 @@ tree-sitter-html = "0.20"
tree-sitter-jsdoc = "0.23"
tree-sitter-json = "0.23"
tree-sitter-md = { git = "https://github.com/zed-industries/tree-sitter-markdown", rev = "4cfa6aad6b75052a5077c80fd934757d9267d81b" }
protols-tree-sitter-proto = { git = "https://github.com/zed-industries/tree-sitter-proto", rev = "0848bd30a64be48772e15fbb9d5ba8c0cc5772ad" }
tree-sitter-python = "0.23"
tree-sitter-regex = "0.23"
tree-sitter-ruby = "0.23"
tree-sitter-rust = "0.23"
tree-sitter-typescript = "0.23"
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" }
unindent = "0.1.7"
tree-sitter-yaml = { git = "https://github.com/zed-industries/tree-sitter-yaml", rev = "baff0b51c64ef6a1fb1f8390f3ad6015b83ec13a" }
unicase = "2.6"
unindent = "0.1.7"
unicode-segmentation = "1.10"
url = "2.2"
uuid = { version = "1.1.2", features = ["v4", "v5", "serde"] }

View File

@@ -31,10 +31,12 @@ ENV GITHUB_SHA=$GITHUB_SHA
# - Staging: `4f408ec65a3867278322a189b4eb20f1ab51f508`
# - Production: `fc4c533d0a8c489e5636a4249d2b52a80039fbd7`
#
# Also add `cmake`, since we need it to build `wasmtime`.
#
# Installing these as a temporary workaround, but I think ideally we'd want to figure
# out what caused them to be included in the first place.
RUN apt-get update; \
apt-get install -y --no-install-recommends libxkbcommon-dev libxkbcommon-x11-dev
apt-get install -y --no-install-recommends libxkbcommon-dev libxkbcommon-x11-dev cmake
RUN --mount=type=cache,target=./script/node_modules \
--mount=type=cache,target=/usr/local/cargo/registry \

26
Dockerfile-distros Normal file
View File

@@ -0,0 +1,26 @@
# syntax=docker/dockerfile:1
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
WORKDIR /app
ARG TZ=Etc/UTC \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
DEBIAN_FRONTEND=noninteractive
ENV CARGO_TERM_COLOR=always
COPY script/linux script/
RUN ./script/linux
COPY script/install-mold script/install-cmake script/
RUN ./script/install-mold "2.34.0"
RUN ./script/install-cmake "3.30.4"
COPY . .
# When debugging, make these into individual RUN statements.
# Cleanup to avoid saving big layers we aren't going to use.
RUN . "$HOME/.cargo/env" \
&& cargo fetch \
&& cargo build \
&& cargo run -- --help \
&& cargo clean --quiet

View File

@@ -0,0 +1,2 @@
**/target
**/node_modules

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trash"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>

After

Width:  |  Height:  |  Size: 330 B

View File

@@ -664,7 +664,8 @@
"shift-up": "terminal::ScrollLineUp",
"shift-down": "terminal::ScrollLineDown",
"shift-home": "terminal::ScrollToTop",
"shift-end": "terminal::ScrollToBottom"
"shift-end": "terminal::ScrollToBottom",
"ctrl-shift-space": "terminal::ToggleViMode"
}
},
{

View File

@@ -440,7 +440,12 @@
"cmd-k shift-right": ["workspace::SwapPaneInDirection", "Right"],
"cmd-k shift-up": ["workspace::SwapPaneInDirection", "Up"],
"cmd-k shift-down": ["workspace::SwapPaneInDirection", "Down"],
"cmd-shift-x": "zed::Extensions",
"cmd-shift-x": "zed::Extensions"
}
},
{
"context": "Workspace && !Terminal",
"bindings": {
"alt-t": "task::Rerun",
"alt-shift-t": "task::Spawn"
}
@@ -673,7 +678,8 @@
"cmd-home": "terminal::ScrollToTop",
"cmd-end": "terminal::ScrollToBottom",
"shift-home": "terminal::ScrollToTop",
"shift-end": "terminal::ScrollToBottom"
"shift-end": "terminal::ScrollToBottom",
"ctrl-shift-space": "terminal::ToggleViMode"
}
}
]

View File

@@ -50,6 +50,9 @@ And here's the section to rewrite based on that prompt again for reference:
{{#if diagnostic_errors}}
{{#each diagnostic_errors}}
Below are the diagnostic errors visible to the user. If the user requests problems to be fixed, use this information, but do not try to fix these errors if the user hasn't asked you to.
<diagnostic_error>
<line_number>{{line_number}}</line_number>
<error_message>{{error_message}}</error_message>

View File

@@ -356,9 +356,19 @@
/// Scrollbar-related settings
"scrollbar": {
/// When to show the scrollbar in the project panel.
/// This setting can take four values:
///
/// Default: always
"show": "always"
/// 1. null (default): Inherit editor settings
/// 2. Show the scrollbar if there's important information or
/// follow the system's configured behavior (default):
/// "auto"
/// 3. Match the system's configured behavior:
/// "system"
/// 4. Always show the scrollbar:
/// "always"
/// 5. Never show the scrollbar:
/// "never"
"show": null
}
},
"outline_panel": {
@@ -599,13 +609,11 @@
}
},
// Configuration for how direnv configuration should be loaded. May take 2 values:
// 1. Load direnv configuration through the shell hook, works for POSIX shells and fish.
// "load_direnv": "shell_hook"
// 2. Load direnv configuration using `direnv export json` directly.
// This can help with some shells that otherwise would not detect
// the direnv environment, such as nushell or elvish.
// 1. Load direnv configuration using `direnv export json` directly.
// "load_direnv": "direct"
"load_direnv": "shell_hook",
// 2. Load direnv configuration through the shell hook, works for POSIX shells and fish.
// "load_direnv": "shell_hook"
"load_direnv": "direct",
"inline_completions": {
// A list of globs representing files that inline completions should be disabled for.
"disabled_globs": [".env"]
@@ -671,6 +679,18 @@
// 3. Always blink the cursor, ignoring the terminal mode
// "blinking": "on",
"blinking": "terminal_controlled",
// Default cursor shape for the terminal.
// 1. A block that surrounds the following character
// "block"
// 2. A vertical bar
// "bar"
// 3. An underline that runs along the following character
// "underscore"
// 4. A box drawn around the following character
// "hollow"
//
// Default: not set, defaults to "block"
"cursor_shape": null,
// Set whether Alternate Scroll mode (code: ?1007) is active by default.
// Alternate Scroll mode converts mouse scroll events into up / down key
// presses when in the alternate screen (e.g. when running applications
@@ -769,7 +789,8 @@
"**/Zed/**/*.json",
"tsconfig.json",
"pyrightconfig.json"
]
],
"TOML": ["uv.lock"]
},
/// By default use a recent system version of node, or install our own.
/// You can override this to use a version of node that is not in $PATH with:
@@ -819,6 +840,9 @@
"allowed": true
}
},
"Dart": {
"tab_size": 2
},
"Elixir": {
"language_servers": ["elixir-ls", "!next-ls", "!lexical", "..."]
},

View File

@@ -1 +1,2 @@
allow-private-module-inception = true
avoid-breaking-exported-api = false

View File

@@ -10,7 +10,7 @@ use gpui::{
use language::{
LanguageRegistry, LanguageServerBinaryStatus, LanguageServerId, LanguageServerName,
};
use project::{LanguageServerProgress, Project};
use project::{EnvironmentErrorMessage, LanguageServerProgress, Project, WorktreeId};
use smallvec::SmallVec;
use std::{cmp::Reverse, fmt::Write, sync::Arc, time::Duration};
use ui::{prelude::*, ButtonLike, ContextMenu, PopoverMenu, PopoverMenuHandle};
@@ -175,7 +175,31 @@ impl ActivityIndicator {
.flatten()
}
fn pending_environment_errors<'a>(
&'a self,
cx: &'a AppContext,
) -> impl Iterator<Item = (&'a WorktreeId, &'a EnvironmentErrorMessage)> {
self.project.read(cx).shell_environment_errors(cx)
}
fn content_to_render(&mut self, cx: &mut ViewContext<Self>) -> Option<Content> {
// Show if any direnv calls failed
if let Some((&worktree_id, error)) = self.pending_environment_errors(cx).next() {
return Some(Content {
icon: Some(
Icon::new(IconName::Warning)
.size(IconSize::Small)
.into_any_element(),
),
message: error.0.clone(),
on_click: Some(Arc::new(move |this, cx| {
this.project.update(cx, |project, cx| {
project.remove_environment_error(cx, worktree_id);
});
cx.dispatch_action(Box::new(workspace::OpenLog));
})),
});
}
// Show any language server has pending activity.
let mut pending_work = self.pending_language_server_work(cx);
if let Some(PendingWork {

View File

@@ -0,0 +1,25 @@
[package]
name = "alert_dialog"
version = "0.1.0"
edition = "2021"
publish = false
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/alert_dialog.rs"
[dependencies]
gpui.workspace = true
menu.workspace = true
settings.workspace = true
story = { workspace = true, optional = true }
theme.workspace = true
ui.workspace = true
workspace.workspace = true
[features]
default = []
stories = ["dep:story"]

View File

@@ -0,0 +1,420 @@
#![deny(missing_docs)]
//! Provides the Alert Dialog UI component A modal dialog that interrupts the user's workflow to convey critical information.
use std::sync::Arc;
use gpui::{
Action, AppContext, ClickEvent, DismissEvent, EventEmitter, FocusHandle, FocusableView, View,
WeakView,
};
use ui::{
div, px, v_flex, vh, ActiveTheme, Button, ButtonCommon, ButtonSize, Clickable, ElementId,
ElevationIndex, FluentBuilder, Headline, HeadlineSize, InteractiveElement, IntoElement,
ParentElement, Render, RenderOnce, SharedString, Spacing, Styled, StyledTypography,
ViewContext, VisualContext, WindowContext,
};
use workspace::{ModalView, Workspace};
#[derive(Clone, IntoElement)]
struct AlertDialogButton {
id: ElementId,
label: SharedString,
on_click: Option<Arc<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
}
impl AlertDialogButton {
fn new(id: impl Into<ElementId>, label: impl Into<SharedString>) -> Self {
Self {
id: id.into(),
label: label.into(),
on_click: None,
}
}
fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
self.on_click = Some(Arc::new(handler));
self
}
}
impl RenderOnce for AlertDialogButton {
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
Button::new(self.id, self.label)
.size(ButtonSize::Large)
.layer(ElevationIndex::ModalSurface)
.when_some(self.on_click, |this, on_click| {
this.on_click(move |event, cx| {
on_click(event, cx);
})
})
}
}
const MAX_DIALOG_WIDTH: f32 = 440.0;
const MIN_DIALOG_WIDTH: f32 = 260.0;
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
enum AlertDialogLayout {
/// For dialogs short titles and action names.
///
/// Example:
///
/// Title: "Discard changes?"
///
/// Actions: "Cancel" | "Discard"
#[default]
Vertical,
/// For dialogs with long titles or action names,
/// or large amounts of content.
///
/// As titles, action names or content get longer, the dialog
/// automatically switches to this layout
Horizontal,
}
/// An alert dialog that interrupts the user's workflow to convey critical information.
///
/// Use this component when immediate user attention or action is required.
///
/// It blocks all other interactions until the user responds, making it suitable
/// for important confirmations or critical error messages.
#[derive(Clone)]
pub struct AlertDialog {
/// The title of the alert dialog
pub title: SharedString,
/// The main message or content of the alert
pub message: Option<SharedString>,
/// The primary action the user can take
primary_action: AlertDialogButton,
/// The secondary action the user can take
secondary_action: AlertDialogButton,
focus_handle: FocusHandle,
}
impl EventEmitter<DismissEvent> for AlertDialog {}
impl FocusableView for AlertDialog {
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
self.focus_handle.clone()
}
}
impl ModalView for AlertDialog {
fn fade_out_background(&self) -> bool {
true
}
}
impl AlertDialog {
/// Create a new alert dialog
pub fn new(
cx: &mut WindowContext,
f: impl FnOnce(Self, &mut ViewContext<Self>) -> Self,
) -> View<Self> {
cx.new_view(|cx| {
let focus_handle = cx.focus_handle();
f(
Self {
title: "Untitled Alert".into(),
message: None,
primary_action: AlertDialogButton::new("primary-action", "OK"),
secondary_action: AlertDialogButton::new("secondary-action", "Cancel"),
focus_handle,
},
cx,
)
})
}
/// Set the title of the alert dialog
pub fn title(mut self, title: impl Into<SharedString>) -> Self {
self.title = title.into();
self
}
/// Set the main message or content of the alert dialog
pub fn message(mut self, message: impl Into<SharedString>) -> Self {
self.message = Some(message.into());
self
}
/// Set the primary action the user can take
pub fn primary_action(
mut self,
label: impl Into<SharedString>,
handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
) -> Self {
self.primary_action = AlertDialogButton::new("primary-action", label).on_click(handler);
self
}
/// Set the secondary action the user can take
pub fn secondary_action(
mut self,
label: impl Into<SharedString>,
handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
) -> Self {
self.secondary_action = AlertDialogButton::new("secondary-action", label).on_click(handler);
self
}
/// Set the secondary action to a dismiss action with a custom label
///
/// Example: "Close", "Dismiss", "No"
pub fn secondary_dismiss_action(mut self, label: impl Into<SharedString>) -> Self {
self.secondary_action = AlertDialogButton::new("secondary-action", label)
.on_click(|_, cx| cx.dispatch_action(menu::Cancel.boxed_clone()));
self
}
fn dialog_layout(&self) -> AlertDialogLayout {
let title_len = self.title.len();
let primary_action_len = self.primary_action.label.len();
let secondary_action_len = self.secondary_action.label.len();
let message_len = self.message.as_ref().map_or(0, |m| m.len());
if title_len > 35
|| primary_action_len > 14
|| secondary_action_len > 14
|| message_len > 80
{
AlertDialogLayout::Horizontal
} else {
AlertDialogLayout::Vertical
}
}
/// Spawns the alert dialog in a new modal
pub fn show(&self, workspace: WeakView<Workspace>, cx: &mut ViewContext<Self>) {
let this = self.clone();
let focus_handle = self.focus_handle.clone();
cx.spawn(|_, mut cx| async move {
workspace.update(&mut cx, |workspace, cx| {
workspace.toggle_modal(cx, |_cx| this);
cx.focus(&focus_handle);
})
})
.detach();
}
fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext<Self>) {
cx.emit(DismissEvent)
}
}
impl Render for AlertDialog {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let layout = self.dialog_layout();
let spacing = if layout == AlertDialogLayout::Horizontal {
Spacing::Large4X.rems(cx)
} else {
Spacing::XLarge.rems(cx)
};
v_flex()
.key_context("Alert")
.track_focus(&self.focus_handle)
.on_action(cx.listener(Self::cancel))
.occlude()
.min_w(px(MIN_DIALOG_WIDTH))
.max_w(if layout == AlertDialogLayout::Horizontal {
px(MAX_DIALOG_WIDTH)
} else {
px(MIN_DIALOG_WIDTH)
})
.max_h(vh(0.75, cx))
.flex_none()
.overflow_hidden()
.p(spacing)
.gap(spacing)
.rounded_lg()
.font_ui(cx)
.bg(ElevationIndex::ModalSurface.bg(cx))
.shadow(ElevationIndex::ModalSurface.shadow())
// Title and message
.child(
v_flex()
.w_full()
// This is a flex hack. Layout breaks without it ¯\_(ツ)_/¯
.min_h(px(1.))
.max_w_full()
.flex_grow()
.when(layout == AlertDialogLayout::Vertical, |this| {
// If we had `.text_center()` we would use it here instead of centering the content
// since this approach will only work as long as the content is a single line
this.justify_center().mx_auto()
})
.child(
div()
// Same as above, if `.text_center()` is supported in the future, use here.
.when(layout == AlertDialogLayout::Vertical, |this| this.mx_auto())
.child(Headline::new(self.title.clone()).size(HeadlineSize::Small)),
)
.when_some(self.message.clone(), |this, message| {
// TODO: When content will be long (example: a document, log or stack trace)
// we should render some sort of styled container, as well as allow the content to scroll
this.child(
div()
// Same as above, if `.text_center()` is supported in the future, use here.
.when(layout == AlertDialogLayout::Vertical, |this| this.mx_auto())
.text_color(cx.theme().colors().text_muted)
.text_ui(cx)
.child(message.clone()),
)
}),
)
// Actions & checkbox
.child(
div()
.flex()
.w_full()
.items_center()
// Force buttons to stack for Horizontal layout
.when(layout == AlertDialogLayout::Vertical, |this| {
this.flex_col()
})
.when(layout == AlertDialogLayout::Horizontal, |this| {
this.justify_between()
.h(ButtonSize::Large.rems())
.gap(Spacing::Medium.rems(cx))
})
.child(div().flex_shrink_0())
.child(
div()
.flex()
.gap(Spacing::Medium.rems(cx))
.when(layout == AlertDialogLayout::Vertical, |this| {
this.flex_col_reverse().w_full()
})
.when(layout == AlertDialogLayout::Horizontal, |this| {
this.items_center()
})
.child(self.secondary_action.clone())
.child(self.primary_action.clone()),
),
)
}
}
/// Example stories for [AlertDialog]
///
/// Run with `script/storybook alert_dialog`
#[cfg(feature = "stories")]
pub mod alert_dialog_stories {
#![allow(missing_docs)]
use gpui::{Render, View};
use story::{Story, StorySection};
use ui::{prelude::*, ElevationIndex};
use super::AlertDialog;
pub struct AlertDialogStory {
vertical_alert_dialog: View<AlertDialog>,
horizontal_alert_dialog: View<AlertDialog>,
long_content_alert_dialog: View<AlertDialog>,
}
impl AlertDialogStory {
pub fn new(cx: &mut WindowContext) -> Self {
let vertical_alert_dialog = AlertDialog::new(cx, |dialog, _cx| {
dialog
.title("Discard changes?")
.message("Something bad could happen...")
.primary_action("Discard", |_, _| {
println!("Discarded!");
})
.secondary_action("Cancel", |_, _| {
println!("Cancelled!");
})
});
let horizontal_alert_dialog = AlertDialog::new(cx, |dialog, _cx| {
dialog
.title("Do you want to leave the current call?")
.message("The current window will be closed, and connections to any shared projects will be terminated.")
.primary_action("Leave Call", |_, _| {})
.secondary_action("Cancel", |_, _| {})
});
let long_content = r#"{
"error": "RuntimeError",
"message": "An unexpected error occurred during execution",
"stackTrace": [
{
"fileName": "main.rs",
"lineNumber": 42,
"functionName": "process_data"
},
{
"fileName": "utils.rs",
"lineNumber": 23,
"functionName": "validate_input"
},
{
"fileName": "core.rs",
"lineNumber": 105,
"functionName": "execute_operation"
}
]
}"#;
let long_content_alert_dialog = AlertDialog::new(cx, |dialog, _cx| {
dialog
.title("A RuntimeError occurred")
.message(long_content)
.primary_action("Send Report", |_, _| {})
.secondary_action("Close", |_, _| {})
});
Self {
vertical_alert_dialog,
horizontal_alert_dialog,
long_content_alert_dialog,
}
}
}
impl Render for AlertDialogStory {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
Story::container().child(
StorySection::new()
.child(
div()
.flex()
.items_center()
.justify_center()
.w(px(780.))
.h(px(380.))
.overflow_hidden()
.bg(ElevationIndex::Background.bg(cx))
.child(self.vertical_alert_dialog.clone()),
)
.child(
div()
.flex()
.items_center()
.justify_center()
.w(px(580.))
.h(px(420.))
.overflow_hidden()
.bg(ElevationIndex::Background.bg(cx))
.child(self.horizontal_alert_dialog.clone()),
)
.child(
div()
.flex()
.items_center()
.justify_center()
.w(px(580.))
.h(px(780.))
.overflow_hidden()
.bg(ElevationIndex::Background.bg(cx))
.child(self.long_content_alert_dialog.clone()),
),
)
}
}
}

View File

@@ -521,6 +521,10 @@ pub struct Usage {
pub input_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub output_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_creation_input_tokens: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_read_input_tokens: Option<u32>,
}
#[derive(Debug, Serialize, Deserialize)]

View File

@@ -18,7 +18,7 @@ use crate::{
PendingSlashCommand, PendingSlashCommandStatus, QuoteSelection, RemoteContextMetadata,
SavedContextMetadata, Split, ToggleFocus, ToggleModelSelector, WorkflowStepResolution,
};
use anyhow::{anyhow, Result};
use anyhow::Result;
use assistant_slash_command::{SlashCommand, SlashCommandOutputSection};
use assistant_tool::ToolRegistry;
use client::{proto, Client, Status};
@@ -77,7 +77,7 @@ use ui::TintColor;
use ui::{
prelude::*,
utils::{format_distance_from_now, DateTimeType},
Avatar, AvatarShape, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem,
Avatar, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem,
ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tooltip,
};
use util::{maybe, ResultExt};
@@ -262,9 +262,7 @@ impl PickerDelegate for SavedContextPickerDelegate {
.gap_2()
.children(if let Some(host_user) = host_user {
vec![
Avatar::new(host_user.avatar_uri.clone())
.shape(AvatarShape::Circle)
.into_any_element(),
Avatar::new(host_user.avatar_uri.clone()).into_any_element(),
Label::new(format!("Shared by @{}", host_user.github_login))
.color(Color::Muted)
.size(LabelSize::Small)
@@ -699,7 +697,9 @@ impl AssistantPanel {
log::error!("no context found with ID: {}", context_id.to_proto());
return;
};
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx).log_err();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx)
.log_err()
.flatten();
let assistant_panel = cx.view().downgrade();
let editor = cx.new_view(|cx| {
@@ -973,7 +973,8 @@ impl AssistantPanel {
this.update(&mut cx, |this, cx| {
let workspace = this.workspace.clone();
let project = this.project.clone();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err();
let lsp_adapter_delegate =
make_lsp_adapter_delegate(&project, cx).log_err().flatten();
let fs = this.fs.clone();
let project = this.project.clone();
@@ -1003,7 +1004,9 @@ impl AssistantPanel {
None
} else {
let context = self.context_store.update(cx, |store, cx| store.create(cx));
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx).log_err();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx)
.log_err()
.flatten();
let assistant_panel = cx.view().downgrade();
let editor = cx.new_view(|cx| {
@@ -1209,7 +1212,7 @@ impl AssistantPanel {
let project = self.project.clone();
let workspace = self.workspace.clone();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&project, cx).log_err().flatten();
cx.spawn(|this, mut cx| async move {
let context = context.await?;
@@ -1256,7 +1259,9 @@ impl AssistantPanel {
.update(cx, |store, cx| store.open_remote_context(id, cx));
let fs = self.fs.clone();
let workspace = self.workspace.clone();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx).log_err();
let lsp_adapter_delegate = make_lsp_adapter_delegate(&self.project, cx)
.log_err()
.flatten();
cx.spawn(|this, mut cx| async move {
let context = context.await?;
@@ -1555,7 +1560,7 @@ impl ContextEditor {
editor.set_show_runnables(false, cx);
editor.set_show_wrap_guides(false, cx);
editor.set_show_indent_guides(false, cx);
editor.set_completion_provider(Box::new(completion_provider));
editor.set_completion_provider(Some(Box::new(completion_provider)));
editor.set_collaboration_hub(Box::new(project.clone()));
editor
});
@@ -5507,22 +5512,21 @@ fn render_docs_slash_command_trailer(
fn make_lsp_adapter_delegate(
project: &Model<Project>,
cx: &mut AppContext,
) -> Result<Arc<dyn LspAdapterDelegate>> {
) -> Result<Option<Arc<dyn LspAdapterDelegate>>> {
project.update(cx, |project, cx| {
// TODO: Find the right worktree.
let worktree = project
.worktrees(cx)
.next()
.ok_or_else(|| anyhow!("no worktrees when constructing LocalLspAdapterDelegate"))?;
let Some(worktree) = project.worktrees(cx).next() else {
return Ok(None::<Arc<dyn LspAdapterDelegate>>);
};
let http_client = project.client().http_client().clone();
project.lsp_store().update(cx, |lsp_store, cx| {
Ok(LocalLspAdapterDelegate::new(
Ok(Some(LocalLspAdapterDelegate::new(
lsp_store,
&worktree,
http_client,
project.fs().clone(),
cx,
) as Arc<dyn LspAdapterDelegate>)
) as Arc<dyn LspAdapterDelegate>))
})
})
}

View File

@@ -46,7 +46,7 @@ use std::{
sync::Arc,
time::{Duration, Instant},
};
use telemetry_events::{AssistantKind, AssistantPhase};
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use text::BufferSnapshot;
use util::{post_inc, ResultExt, TryFutureExt};
use uuid::Uuid;
@@ -549,7 +549,7 @@ impl Context {
cx: &mut ModelContext<Self>,
) -> Self {
let buffer = cx.new_model(|_cx| {
let mut buffer = Buffer::remote(
let buffer = Buffer::remote(
language::BufferId::new(1).unwrap(),
replica_id,
capability,
@@ -2133,14 +2133,21 @@ impl Context {
});
if let Some(telemetry) = this.telemetry.as_ref() {
telemetry.report_assistant_event(
Some(this.id.0.clone()),
AssistantKind::Panel,
AssistantPhase::Response,
model.telemetry_id(),
let language_name = this
.buffer
.read(cx)
.language()
.map(|language| language.name());
telemetry.report_assistant_event(AssistantEvent {
conversation_id: Some(this.id.0.clone()),
kind: AssistantKind::Panel,
phase: AssistantPhase::Response,
model: model.telemetry_id(),
model_provider: model.provider_id().to_string(),
response_latency,
error_message,
);
language_name,
});
}
if let Ok(stop_reason) = result {

View File

@@ -50,6 +50,7 @@ use std::{
task::{self, Poll},
time::{Duration, Instant},
};
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use terminal_view::terminal_panel::TerminalPanel;
use text::{OffsetRangeExt, ToPoint as _};
use theme::ThemeSettings;
@@ -209,18 +210,6 @@ impl InlineAssistant {
initial_prompt: Option<String>,
cx: &mut WindowContext,
) {
if let Some(telemetry) = self.telemetry.as_ref() {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
telemetry.report_assistant_event(
None,
telemetry_events::AssistantKind::Inline,
telemetry_events::AssistantPhase::Invoked,
model.telemetry_id(),
None,
None,
);
}
}
let snapshot = editor.read(cx).buffer().read(cx).snapshot(cx);
let mut selections = Vec::<Selection<Point>>::new();
@@ -267,6 +256,21 @@ impl InlineAssistant {
text_anchor: buffer.anchor_after(buffer_range.end),
};
codegen_ranges.push(start..end);
if let Some(telemetry) = self.telemetry.as_ref() {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
telemetry.report_assistant_event(AssistantEvent {
conversation_id: None,
kind: AssistantKind::Inline,
phase: AssistantPhase::Invoked,
model: model.telemetry_id(),
model_provider: model.provider_id().to_string(),
response_latency: None,
error_message: None,
language_name: buffer.language().map(|language| language.name()),
});
}
}
}
let assist_group_id = self.next_assist_group_id.post_inc();
@@ -761,23 +765,34 @@ impl InlineAssistant {
}
pub fn finish_assist(&mut self, assist_id: InlineAssistId, undo: bool, cx: &mut WindowContext) {
if let Some(telemetry) = self.telemetry.as_ref() {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
telemetry.report_assistant_event(
None,
telemetry_events::AssistantKind::Inline,
if undo {
telemetry_events::AssistantPhase::Rejected
} else {
telemetry_events::AssistantPhase::Accepted
},
model.telemetry_id(),
None,
None,
);
}
}
if let Some(assist) = self.assists.get(&assist_id) {
if let Some(telemetry) = self.telemetry.as_ref() {
if let Some(model) = LanguageModelRegistry::read_global(cx).active_model() {
let language_name = assist.editor.upgrade().and_then(|editor| {
let multibuffer = editor.read(cx).buffer().read(cx);
let ranges = multibuffer.range_to_buffer_ranges(assist.range.clone(), cx);
ranges
.first()
.and_then(|(buffer, _, _)| buffer.read(cx).language())
.map(|language| language.name())
});
telemetry.report_assistant_event(AssistantEvent {
conversation_id: None,
kind: AssistantKind::Inline,
phase: if undo {
AssistantPhase::Rejected
} else {
AssistantPhase::Accepted
},
model: model.telemetry_id(),
model_provider: model.provider_id().to_string(),
response_latency: None,
error_message: None,
language_name,
});
}
}
let assist_group_id = assist.group_id;
if self.assist_groups[&assist_group_id].linked {
for assist_id in self.unlink_assist_group(assist_group_id, cx) {
@@ -1142,7 +1157,7 @@ impl InlineAssistant {
for row_range in inserted_row_ranges {
editor.highlight_rows::<InlineAssist>(
row_range,
Some(cx.theme().status().info_background),
cx.theme().status().info_background,
false,
cx,
);
@@ -1208,8 +1223,8 @@ impl InlineAssistant {
editor.set_read_only(true);
editor.set_show_inline_completions(Some(false), cx);
editor.highlight_rows::<DeletedLines>(
Anchor::min()..=Anchor::max(),
Some(cx.theme().status().deleted_background),
Anchor::min()..Anchor::max(),
cx.theme().status().deleted_background,
false,
cx,
);
@@ -2557,7 +2572,7 @@ enum CodegenStatus {
#[derive(Default)]
struct Diff {
deleted_row_ranges: Vec<(Anchor, RangeInclusive<u32>)>,
inserted_row_ranges: Vec<RangeInclusive<Anchor>>,
inserted_row_ranges: Vec<Range<Anchor>>,
}
impl Diff {
@@ -2706,6 +2721,7 @@ impl CodegenAlternative {
self.edit_position = Some(self.range.start.bias_right(&self.snapshot));
let telemetry_id = model.telemetry_id();
let provider_id = model.provider_id();
let chunks: LocalBoxFuture<Result<BoxStream<Result<String>>>> =
if user_prompt.trim().to_lowercase() == "delete" {
async { Ok(stream::empty().boxed()) }.boxed_local()
@@ -2716,7 +2732,7 @@ impl CodegenAlternative {
.spawn(|_, cx| async move { model.stream_completion_text(request, &cx).await });
async move { Ok(chunks.await?.boxed()) }.boxed_local()
};
self.handle_stream(telemetry_id, chunks, cx);
self.handle_stream(telemetry_id, provider_id.to_string(), chunks, cx);
Ok(())
}
@@ -2780,6 +2796,7 @@ impl CodegenAlternative {
pub fn handle_stream(
&mut self,
model_telemetry_id: String,
model_provider_id: String,
stream: impl 'static + Future<Output = Result<BoxStream<'static, Result<String>>>>,
cx: &mut ModelContext<Self>,
) {
@@ -2810,6 +2827,15 @@ impl CodegenAlternative {
}
let telemetry = self.telemetry.clone();
let language_name = {
let multibuffer = self.buffer.read(cx);
let ranges = multibuffer.range_to_buffer_ranges(self.range.clone(), cx);
ranges
.first()
.and_then(|(buffer, _, _)| buffer.read(cx).language())
.map(|language| language.name())
};
self.diff = Diff::default();
self.status = CodegenStatus::Pending;
let mut edit_start = self.range.start.to_offset(&snapshot);
@@ -2920,14 +2946,16 @@ impl CodegenAlternative {
let error_message =
result.as_ref().err().map(|error| error.to_string());
if let Some(telemetry) = telemetry {
telemetry.report_assistant_event(
None,
telemetry_events::AssistantKind::Inline,
telemetry_events::AssistantPhase::Response,
model_telemetry_id,
telemetry.report_assistant_event(AssistantEvent {
conversation_id: None,
kind: AssistantKind::Inline,
phase: AssistantPhase::Response,
model: model_telemetry_id,
model_provider: model_provider_id.to_string(),
response_latency,
error_message,
);
language_name,
});
}
result?;
@@ -3103,7 +3131,7 @@ impl CodegenAlternative {
new_end_row,
new_snapshot.line_len(MultiBufferRow(new_end_row)),
));
self.diff.inserted_row_ranges.push(start..=end);
self.diff.inserted_row_ranges.push(start..end);
new_row += lines;
}
}
@@ -3181,7 +3209,7 @@ impl CodegenAlternative {
new_end_row,
new_snapshot.line_len(MultiBufferRow(new_end_row)),
));
inserted_row_ranges.push(start..=end);
inserted_row_ranges.push(start..end);
new_row += line_count;
}
}
@@ -3539,6 +3567,7 @@ mod tests {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
codegen.update(cx, |codegen, cx| {
codegen.handle_stream(
String::new(),
String::new(),
future::ready(Ok(chunks_rx.map(Ok).boxed())),
cx,
@@ -3610,6 +3639,7 @@ mod tests {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
codegen.update(cx, |codegen, cx| {
codegen.handle_stream(
String::new(),
String::new(),
future::ready(Ok(chunks_rx.map(Ok).boxed())),
cx,
@@ -3684,6 +3714,7 @@ mod tests {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
codegen.update(cx, |codegen, cx| {
codegen.handle_stream(
String::new(),
String::new(),
future::ready(Ok(chunks_rx.map(Ok).boxed())),
cx,
@@ -3757,6 +3788,7 @@ mod tests {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
codegen.update(cx, |codegen, cx| {
codegen.handle_stream(
String::new(),
String::new(),
future::ready(Ok(chunks_rx.map(Ok).boxed())),
cx,
@@ -3820,6 +3852,7 @@ mod tests {
let (chunks_tx, chunks_rx) = mpsc::unbounded();
codegen.update(cx, |codegen, cx| {
codegen.handle_stream(
String::new(),
String::new(),
future::ready(Ok(chunks_rx.map(Ok).boxed())),
cx,

View File

@@ -521,9 +521,9 @@ impl PromptLibrary {
editor.set_show_indent_guides(false, cx);
editor.set_use_modal_editing(false);
editor.set_current_line_highlight(Some(CurrentLineHighlight::None));
editor.set_completion_provider(Box::new(
editor.set_completion_provider(Some(Box::new(
SlashCommandCompletionProvider::new(None, None),
));
)));
if focus {
editor.focus(cx);
}
@@ -910,7 +910,7 @@ impl PromptLibrary {
.features
.clone(),
font_size: HeadlineSize::Large
.size()
.rems()
.into(),
font_weight: settings.ui_font.weight,
line_height: relative(

View File

@@ -31,11 +31,11 @@ impl SlashCommand for AutoCommand {
}
fn description(&self) -> String {
"Automatically infer what context to add, based on your prompt".into()
"Automatically infer what context to add".into()
}
fn menu_text(&self) -> String {
"Automatically Infer Context".into()
self.description()
}
fn label(&self, cx: &AppContext) -> CodeLabel {

View File

@@ -19,11 +19,11 @@ impl SlashCommand for DeltaSlashCommand {
}
fn description(&self) -> String {
"re-insert changed files".into()
"Re-insert changed files".into()
}
fn menu_text(&self) -> String {
"Re-insert Changed Files".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -95,7 +95,7 @@ impl SlashCommand for DiagnosticsSlashCommand {
}
fn menu_text(&self) -> String {
"Insert Diagnostics".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -104,11 +104,11 @@ impl SlashCommand for FetchSlashCommand {
}
fn description(&self) -> String {
"insert URL contents".into()
"Insert fetched URL contents".into()
}
fn menu_text(&self) -> String {
"Insert fetched URL contents".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -110,11 +110,11 @@ impl SlashCommand for FileSlashCommand {
}
fn description(&self) -> String {
"insert file".into()
"Insert file".into()
}
fn menu_text(&self) -> String {
"Insert File".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -19,11 +19,11 @@ impl SlashCommand for NowSlashCommand {
}
fn description(&self) -> String {
"insert the current date and time".into()
"Insert current date and time".into()
}
fn menu_text(&self) -> String {
"Insert Current Date and Time".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -47,11 +47,11 @@ impl SlashCommand for ProjectSlashCommand {
}
fn description(&self) -> String {
"Generate semantic searches based on the current context".into()
"Generate a semantic search based on context".into()
}
fn menu_text(&self) -> String {
"Project Context".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -16,11 +16,11 @@ impl SlashCommand for PromptSlashCommand {
}
fn description(&self) -> String {
"insert prompt from library".into()
"Insert prompt from library".into()
}
fn menu_text(&self) -> String {
"Insert Prompt from Library".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -34,11 +34,11 @@ impl SlashCommand for SearchSlashCommand {
}
fn description(&self) -> String {
"semantic search".into()
"Search your project semantically".into()
}
fn menu_text(&self) -> String {
"Semantic Search".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -17,11 +17,11 @@ impl SlashCommand for OutlineSlashCommand {
}
fn description(&self) -> String {
"insert symbols for active tab".into()
"Insert symbols for active tab".into()
}
fn menu_text(&self) -> String {
"Insert Symbols for Active Tab".into()
self.description()
}
fn complete_argument(

View File

@@ -24,11 +24,11 @@ impl SlashCommand for TabSlashCommand {
}
fn description(&self) -> String {
"insert open tabs (active tab by default)".to_owned()
"Insert open tabs (active tab by default)".to_owned()
}
fn menu_text(&self) -> String {
"Insert Open Tabs".to_owned()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -29,11 +29,11 @@ impl SlashCommand for TerminalSlashCommand {
}
fn description(&self) -> String {
"insert terminal output".into()
"Insert terminal output".into()
}
fn menu_text(&self) -> String {
"Insert Terminal Output".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -29,11 +29,11 @@ impl SlashCommand for WorkflowSlashCommand {
}
fn description(&self) -> String {
"insert a prompt that opts into the edit workflow".into()
"Insert prompt to opt into the edit workflow".into()
}
fn menu_text(&self) -> String {
"Insert Workflow Prompt".into()
self.description()
}
fn requires_argument(&self) -> bool {

View File

@@ -184,7 +184,7 @@ impl PickerDelegate for SlashCommandDelegate {
h_flex()
.group(format!("command-entry-label-{ix}"))
.w_full()
.min_w(px(220.))
.min_w(px(250.))
.child(
v_flex()
.child(
@@ -203,7 +203,9 @@ impl PickerDelegate for SlashCommandDelegate {
div()
.font_buffer(cx)
.child(
Label::new(args).size(LabelSize::Small),
Label::new(args)
.size(LabelSize::Small)
.color(Color::Muted),
)
.visible_on_hover(format!(
"command-entry-label-{ix}"

View File

@@ -25,6 +25,7 @@ use std::{
sync::Arc,
time::{Duration, Instant},
};
use telemetry_events::{AssistantEvent, AssistantKind, AssistantPhase};
use terminal::Terminal;
use terminal_view::TerminalView;
use theme::ThemeSettings;
@@ -1039,6 +1040,7 @@ impl Codegen {
self.transaction = Some(TerminalTransaction::start(self.terminal.clone()));
self.generation = cx.spawn(|this, mut cx| async move {
let model_telemetry_id = model.telemetry_id();
let model_provider_id = model.provider_id();
let response = model.stream_completion_text(prompt, &cx).await;
let generate = async {
let (mut hunks_tx, mut hunks_rx) = mpsc::channel(1);
@@ -1063,14 +1065,16 @@ impl Codegen {
let error_message = result.as_ref().err().map(|error| error.to_string());
if let Some(telemetry) = telemetry {
telemetry.report_assistant_event(
None,
telemetry_events::AssistantKind::Inline,
telemetry_events::AssistantPhase::Response,
model_telemetry_id,
telemetry.report_assistant_event(AssistantEvent {
conversation_id: None,
kind: AssistantKind::Inline,
phase: AssistantPhase::Response,
model: model_telemetry_id,
model_provider: model_provider_id.to_string(),
response_latency,
error_message,
);
language_name: None,
});
}
result?;

View File

@@ -264,6 +264,18 @@ pub fn view_release_notes(_: &ViewReleaseNotes, cx: &mut AppContext) -> Option<(
fn view_release_notes_locally(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
let release_channel = ReleaseChannel::global(cx);
let url = match release_channel {
ReleaseChannel::Nightly => Some("https://github.com/zed-industries/zed/commits/nightly/"),
ReleaseChannel::Dev => Some("https://github.com/zed-industries/zed/commits/main/"),
_ => None,
};
if let Some(url) = url {
cx.open_url(url);
return;
}
let version = AppVersion::global(cx).to_string();
let client = client::Client::global(cx).http_client();
@@ -345,15 +357,17 @@ pub fn notify_of_any_new_update(cx: &mut ViewContext<Workspace>) -> Option<()> {
let should_show_notification = should_show_notification.await?;
if should_show_notification {
workspace.update(&mut cx, |workspace, cx| {
let workspace_handle = workspace.weak_handle();
workspace.show_notification(
NotificationId::unique::<UpdateNotification>(),
cx,
|cx| cx.new_view(|_| UpdateNotification::new(version)),
|cx| cx.new_view(|_| UpdateNotification::new(version, workspace_handle)),
);
updater
.read(cx)
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
updater.update(cx, |updater, cx| {
updater
.set_should_show_update_notification(false, cx)
.detach_and_log_err(cx);
});
})?;
}
anyhow::Ok(())

View File

@@ -1,13 +1,18 @@
use gpui::{
div, DismissEvent, EventEmitter, InteractiveElement, IntoElement, ParentElement, Render,
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext,
SemanticVersion, StatefulInteractiveElement, Styled, ViewContext, WeakView,
};
use menu::Cancel;
use release_channel::ReleaseChannel;
use workspace::ui::{h_flex, v_flex, Icon, IconName, Label, StyledExt};
use util::ResultExt;
use workspace::{
ui::{h_flex, v_flex, Icon, IconName, Label, StyledExt},
Workspace,
};
pub struct UpdateNotification {
version: SemanticVersion,
workspace: WeakView<Workspace>,
}
impl EventEmitter<DismissEvent> for UpdateNotification {}
@@ -41,7 +46,11 @@ impl Render for UpdateNotification {
.child(Label::new("View the release notes"))
.cursor_pointer()
.on_click(cx.listener(|this, _, cx| {
crate::view_release_notes(&Default::default(), cx);
this.workspace
.update(cx, |workspace, cx| {
crate::view_release_notes_locally(workspace, cx);
})
.log_err();
this.dismiss(&menu::Cancel, cx)
})),
)
@@ -49,8 +58,8 @@ impl Render for UpdateNotification {
}
impl UpdateNotification {
pub fn new(version: SemanticVersion) -> Self {
Self { version }
pub fn new(version: SemanticVersion, workspace: WeakView<Workspace>) -> Self {
Self { version, workspace }
}
pub fn dismiss(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {

View File

@@ -1178,7 +1178,7 @@ impl Room {
this.update(&mut cx, |this, cx| {
this.joined_projects.retain(|project| {
if let Some(project) = project.upgrade() {
!project.read(cx).is_disconnected()
!project.read(cx).is_disconnected(cx)
} else {
false
}

View File

@@ -808,7 +808,7 @@ pub fn mentions_to_proto(mentions: &[(Range<usize>, UserId)]) -> Vec<proto::Chat
impl sum_tree::Item for ChannelMessage {
type Summary = ChannelMessageSummary;
fn summary(&self) -> Self::Summary {
fn summary(&self, _cx: &()) -> Self::Summary {
ChannelMessageSummary {
max_id: self.id,
count: 1,

View File

@@ -394,7 +394,7 @@ pub struct PendingEntitySubscription<T: 'static> {
}
impl<T: 'static> PendingEntitySubscription<T> {
pub fn set_model(mut self, model: &Model<T>, cx: &mut AsyncAppContext) -> Subscription {
pub fn set_model(mut self, model: &Model<T>, cx: &AsyncAppContext) -> Subscription {
self.consumed = true;
let mut handlers = self.client.handler_set.lock();
let id = (TypeId::of::<T>(), self.remote_id);
@@ -1752,7 +1752,7 @@ impl CredentialsProvider for KeychainCredentialsProvider {
}
/// prefix for the zed:// url scheme
pub static ZED_URL_SCHEME: &str = "zed";
pub const ZED_URL_SCHEME: &str = "zed";
/// Parses the given link into a Zed link.
///

View File

@@ -1,12 +1,13 @@
mod event_coalescer;
use crate::{ChannelId, TelemetrySettings};
use anyhow::Result;
use chrono::{DateTime, Utc};
use clock::SystemClock;
use collections::{HashMap, HashSet};
use futures::Future;
use gpui::{AppContext, BackgroundExecutor, Task};
use http_client::{self, HttpClient, HttpClientWithUrl, Method};
use http_client::{self, AsyncBody, HttpClient, HttpClientWithUrl, Method, Request};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use release_channel::ReleaseChannel;
@@ -16,9 +17,9 @@ use std::io::Write;
use std::{env, mem, path::PathBuf, sync::Arc, time::Duration};
use sysinfo::{CpuRefreshKind, Pid, ProcessRefreshKind, RefreshKind, System};
use telemetry_events::{
ActionEvent, AppEvent, AssistantEvent, AssistantKind, AssistantPhase, CallEvent, CpuEvent,
EditEvent, EditorEvent, Event, EventRequestBody, EventWrapper, ExtensionEvent,
InlineCompletionEvent, MemoryEvent, ReplEvent, SettingEvent,
ActionEvent, AppEvent, AssistantEvent, CallEvent, CpuEvent, EditEvent, EditorEvent, Event,
EventRequestBody, EventWrapper, ExtensionEvent, InlineCompletionEvent, MemoryEvent, ReplEvent,
SettingEvent,
};
use tempfile::NamedTempFile;
#[cfg(not(debug_assertions))]
@@ -288,7 +289,7 @@ impl Telemetry {
system_id: Option<String>,
installation_id: Option<String>,
session_id: String,
cx: &mut AppContext,
cx: &AppContext,
) {
let mut state = self.state.lock();
state.system_id = system_id.map(|id| id.into());
@@ -364,6 +365,7 @@ impl Telemetry {
operation: &'static str,
copilot_enabled: bool,
copilot_enabled_for_language: bool,
is_via_ssh: bool,
) {
let event = Event::Editor(EditorEvent {
file_extension,
@@ -371,6 +373,7 @@ impl Telemetry {
operation: operation.into(),
copilot_enabled,
copilot_enabled_for_language,
is_via_ssh,
});
self.report_event(event)
@@ -391,25 +394,8 @@ impl Telemetry {
self.report_event(event)
}
pub fn report_assistant_event(
self: &Arc<Self>,
conversation_id: Option<String>,
kind: AssistantKind,
phase: AssistantPhase,
model: String,
response_latency: Option<Duration>,
error_message: Option<String>,
) {
let event = Event::Assistant(AssistantEvent {
conversation_id,
kind,
phase,
model: model.to_string(),
response_latency,
error_message,
});
self.report_event(event)
pub fn report_assistant_event(self: &Arc<Self>, event: AssistantEvent) {
self.report_event(Event::Assistant(event));
}
pub fn report_call_event(
@@ -473,7 +459,7 @@ impl Telemetry {
}))
}
pub fn log_edit_event(self: &Arc<Self>, environment: &'static str) {
pub fn log_edit_event(self: &Arc<Self>, environment: &'static str, is_via_ssh: bool) {
let mut state = self.state.lock();
let period_data = state.event_coalescer.log_event(environment);
drop(state);
@@ -482,6 +468,7 @@ impl Telemetry {
let event = Event::Edit(EditEvent {
duration: end.timestamp_millis() - start.timestamp_millis(),
environment: environment.to_string(),
is_via_ssh,
});
self.report_event(event);
@@ -502,7 +489,7 @@ impl Telemetry {
worktree_id: WorktreeId,
updated_entries_set: &UpdatedEntriesSet,
) {
let project_names: Vec<String> = {
let project_type_names: Vec<String> = {
let mut state = self.state.lock();
state
.worktree_id_map
@@ -538,8 +525,8 @@ impl Telemetry {
};
// Done on purpose to avoid calling `self.state.lock()` multiple times
for project_name in project_names {
self.report_app_event(format!("open {} project", project_name));
for project_type_name in project_type_names {
self.report_app_event(format!("open {} project", project_type_name));
}
}
@@ -611,6 +598,29 @@ impl Telemetry {
self.state.lock().is_staff
}
fn build_request(
self: &Arc<Self>,
// We take in the JSON bytes buffer so we can reuse the existing allocation.
mut json_bytes: Vec<u8>,
event_request: EventRequestBody,
) -> Result<Request<AsyncBody>> {
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, &event_request)?;
let checksum = calculate_json_checksum(&json_bytes).unwrap_or("".to_string());
Ok(Request::builder()
.method(Method::POST)
.uri(
self.http_client
.build_zed_api_url("/telemetry/events", &[])?
.as_ref(),
)
.header("Content-Type", "application/json")
.header("x-zed-checksum", checksum)
.body(json_bytes.into())?)
}
pub fn flush_events(self: &Arc<Self>) {
let mut state = self.state.lock();
state.first_event_date_time = None;
@@ -637,10 +647,10 @@ impl Telemetry {
}
}
{
let request_body = {
let state = this.state.lock();
let request_body = EventRequestBody {
EventRequestBody {
system_id: state.system_id.as_deref().map(Into::into),
installation_id: state.installation_id.as_deref().map(Into::into),
session_id: state.session_id.clone(),
@@ -653,25 +663,11 @@ impl Telemetry {
release_channel: state.release_channel.map(Into::into),
events,
};
json_bytes.clear();
serde_json::to_writer(&mut json_bytes, &request_body)?;
}
}
};
let checksum = calculate_json_checksum(&json_bytes).unwrap_or("".to_string());
let request = http_client::Request::builder()
.method(Method::POST)
.uri(
this.http_client
.build_zed_api_url("/telemetry/events", &[])?
.as_ref(),
)
.header("Content-Type", "text/plain")
.header("x-zed-checksum", checksum)
.body(json_bytes.into());
let response = this.http_client.send(request?).await?;
let request = this.build_request(json_bytes, request_body)?;
let response = this.http_client.send(request).await?;
if response.status() != 200 {
log::error!("Failed to send events: HTTP {:?}", response.status());
}

View File

@@ -138,7 +138,7 @@ enum UpdateContacts {
}
impl UserStore {
pub fn new(client: Arc<Client>, cx: &mut ModelContext<Self>) -> Self {
pub fn new(client: Arc<Client>, cx: &ModelContext<Self>) -> Self {
let (mut current_user_tx, current_user_rx) = watch::channel();
let (update_contacts_tx, mut update_contacts_rx) = mpsc::unbounded();
let rpc_subscriptions = vec![
@@ -310,7 +310,7 @@ impl UserStore {
fn update_contacts(
&mut self,
message: UpdateContacts,
cx: &mut ModelContext<Self>,
cx: &ModelContext<Self>,
) -> Task<Result<()>> {
match message {
UpdateContacts::Wait(barrier) => {
@@ -525,9 +525,9 @@ impl UserStore {
}
pub fn dismiss_contact_request(
&mut self,
&self,
requester_id: u64,
cx: &mut ModelContext<Self>,
cx: &ModelContext<Self>,
) -> Task<Result<()>> {
let client = self.client.upgrade();
cx.spawn(move |_, _| async move {
@@ -573,7 +573,7 @@ impl UserStore {
})
}
pub fn clear_contacts(&mut self) -> impl Future<Output = ()> {
pub fn clear_contacts(&self) -> impl Future<Output = ()> {
let (tx, mut rx) = postage::barrier::channel();
self.update_contacts_tx
.unbounded_send(UpdateContacts::Clear(tx))
@@ -583,7 +583,7 @@ impl UserStore {
}
}
pub fn contact_updates_done(&mut self) -> impl Future<Output = ()> {
pub fn contact_updates_done(&self) -> impl Future<Output = ()> {
let (tx, mut rx) = postage::barrier::channel();
self.update_contacts_tx
.unbounded_send(UpdateContacts::Wait(tx))
@@ -594,9 +594,9 @@ impl UserStore {
}
pub fn get_users(
&mut self,
&self,
user_ids: Vec<u64>,
cx: &mut ModelContext<Self>,
cx: &ModelContext<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
let mut user_ids_to_fetch = user_ids.clone();
user_ids_to_fetch.retain(|id| !self.users.contains_key(id));
@@ -629,9 +629,9 @@ impl UserStore {
}
pub fn fuzzy_search_users(
&mut self,
&self,
query: String,
cx: &mut ModelContext<Self>,
cx: &ModelContext<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
self.load_users(proto::FuzzySearchUsers { query }, cx)
}
@@ -640,11 +640,7 @@ impl UserStore {
self.users.get(&user_id).cloned()
}
pub fn get_user_optimistic(
&mut self,
user_id: u64,
cx: &mut ModelContext<Self>,
) -> Option<Arc<User>> {
pub fn get_user_optimistic(&self, user_id: u64, cx: &ModelContext<Self>) -> Option<Arc<User>> {
if let Some(user) = self.users.get(&user_id).cloned() {
return Some(user);
}
@@ -653,11 +649,7 @@ impl UserStore {
None
}
pub fn get_user(
&mut self,
user_id: u64,
cx: &mut ModelContext<Self>,
) -> Task<Result<Arc<User>>> {
pub fn get_user(&self, user_id: u64, cx: &ModelContext<Self>) -> Task<Result<Arc<User>>> {
if let Some(user) = self.users.get(&user_id).cloned() {
return Task::ready(Ok(user));
}
@@ -697,7 +689,7 @@ impl UserStore {
.map(|accepted_tos_at| accepted_tos_at.is_some())
}
pub fn accept_terms_of_service(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
pub fn accept_terms_of_service(&self, cx: &ModelContext<Self>) -> Task<Result<()>> {
if self.current_user().is_none() {
return Task::ready(Err(anyhow!("no current user")));
};
@@ -726,9 +718,9 @@ impl UserStore {
}
fn load_users(
&mut self,
&self,
request: impl RequestMessage<Response = UsersResponse>,
cx: &mut ModelContext<Self>,
cx: &ModelContext<Self>,
) -> Task<Result<Vec<Arc<User>>>> {
let client = self.client.clone();
cx.spawn(|this, mut cx| async move {

View File

@@ -216,10 +216,11 @@ impl fmt::Debug for Global {
if timestamp.replica_id > 0 {
write!(f, ", ")?;
}
write!(f, "{}: {}", timestamp.replica_id, timestamp.value)?;
}
if self.local_branch_value > 0 {
write!(f, "<branch>: {}", self.local_branch_value)?;
if timestamp.replica_id == LOCAL_BRANCH_REPLICA_ID {
write!(f, "<branch>: {}", timestamp.value)?;
} else {
write!(f, "{}: {}", timestamp.replica_id, timestamp.value)?;
}
}
write!(f, "}}")
}

View File

@@ -28,10 +28,11 @@ axum = { version = "0.6", features = ["json", "headers", "ws"] }
axum-extra = { version = "0.4", features = ["erased-json"] }
base64.workspace = true
chrono.workspace = true
clock.workspace = true
clickhouse.workspace = true
clock.workspace = true
collections.workspace = true
dashmap.workspace = true
derive_more.workspace = true
envy = "0.4.2"
futures.workspace = true
google_ai.workspace = true
@@ -43,13 +44,13 @@ live_kit_server.workspace = true
log.workspace = true
nanoid.workspace = true
open_ai.workspace = true
supermaven_api.workspace = true
parking_lot.workspace = true
prometheus = "0.13"
prost.workspace = true
rand.workspace = true
reqwest = { version = "0.11", features = ["json"] }
rpc.workspace = true
rustc-demangle.workspace = true
scrypt = "0.11"
sea-orm = { version = "1.1.0-rc.1", features = ["sqlx-postgres", "postgres-array", "runtime-tokio-rustls", "with-uuid"] }
semantic_version.workspace = true
@@ -61,7 +62,7 @@ sha2.workspace = true
sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "json", "time", "uuid", "any"] }
strum.workspace = true
subtle.workspace = true
rustc-demangle.workspace = true
supermaven_api.workspace = true
telemetry_events.workspace = true
text.workspace = true
thiserror.workspace = true
@@ -85,6 +86,7 @@ client = { workspace = true, features = ["test-support"] }
collab_ui = { workspace = true, features = ["test-support"] }
collections = { workspace = true, features = ["test-support"] }
ctor.workspace = true
dev_server_projects.workspace = true
editor = { workspace = true, features = ["test-support"] }
env_logger.workspace = true
file_finder.workspace = true
@@ -92,6 +94,7 @@ fs = { workspace = true, features = ["test-support"] }
git = { workspace = true, features = ["test-support"] }
git_hosting_providers.workspace = true
gpui = { workspace = true, features = ["test-support"] }
headless.workspace = true
hyper.workspace = true
indoc.workspace = true
language = { workspace = true, features = ["test-support"] }
@@ -108,7 +111,6 @@ recent_projects = { workspace = true }
release_channel.workspace = true
remote = { workspace = true, features = ["test-support"] }
remote_server.workspace = true
dev_server_projects.workspace = true
rpc = { workspace = true, features = ["test-support"] }
sea-orm = { version = "1.1.0-rc.1", features = ["sqlx-sqlite"] }
serde_json.workspace = true
@@ -120,7 +122,6 @@ unindent.workspace = true
util.workspace = true
workspace = { workspace = true, features = ["test-support"] }
worktree = { workspace = true, features = ["test-support"] }
headless.workspace = true
[package.metadata.cargo-machete]
ignored = ["async-stripe"]

View File

@@ -112,6 +112,7 @@ CREATE TABLE "worktree_settings_files" (
"worktree_id" INTEGER NOT NULL,
"path" VARCHAR NOT NULL,
"content" TEXT,
"kind" VARCHAR,
PRIMARY KEY(project_id, worktree_id, path),
FOREIGN KEY(project_id, worktree_id) REFERENCES worktrees (project_id, id) ON DELETE CASCADE
);
@@ -421,6 +422,15 @@ CREATE TABLE dev_server_projects (
paths TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS billing_preferences (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
user_id INTEGER NOT NULL REFERENCES users(id),
max_monthly_llm_usage_spending_in_cents INTEGER NOT NULL
);
CREATE UNIQUE INDEX "uix_billing_preferences_on_user_id" ON billing_preferences (user_id);
CREATE TABLE IF NOT EXISTS billing_customers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

View File

@@ -0,0 +1 @@
ALTER TABLE "worktree_settings_files" ADD COLUMN "kind" VARCHAR;

View File

@@ -0,0 +1,8 @@
create table if not exists billing_preferences (
id serial primary key,
created_at timestamp without time zone not null default now(),
user_id integer not null references users(id) on delete cascade,
max_monthly_llm_usage_spending_in_cents integer not null
);
create unique index "uix_billing_preferences_on_user_id" on billing_preferences (user_id);

View File

@@ -0,0 +1,11 @@
alter table models
add column price_per_million_cache_creation_input_tokens integer not null default 0,
add column price_per_million_cache_read_input_tokens integer not null default 0;
alter table usages
add column cache_creation_input_tokens_this_month bigint not null default 0,
add column cache_read_input_tokens_this_month bigint not null default 0;
alter table lifetime_usages
add column cache_creation_input_tokens bigint not null default 0,
add column cache_read_input_tokens bigint not null default 0;

View File

@@ -0,0 +1,3 @@
alter table usages
drop column cache_creation_input_tokens_this_month,
drop column cache_read_input_tokens_this_month;

View File

@@ -0,0 +1,13 @@
create table monthly_usages (
id serial primary key,
user_id integer not null,
model_id integer not null references models (id) on delete cascade,
month integer not null,
year integer not null,
input_tokens bigint not null default 0,
cache_creation_input_tokens bigint not null default 0,
cache_read_input_tokens bigint not null default 0,
output_tokens bigint not null default 0
);
create unique index uix_monthly_usages_on_user_id_model_id_month_year on monthly_usages (user_id, model_id, month, year);

View File

@@ -22,16 +22,23 @@ use stripe::{
};
use util::ResultExt;
use crate::db::billing_subscription::StripeSubscriptionStatus;
use crate::db::billing_subscription::{self, StripeSubscriptionStatus};
use crate::db::{
billing_customer, BillingSubscriptionId, CreateBillingCustomerParams,
CreateBillingSubscriptionParams, CreateProcessedStripeEventParams, UpdateBillingCustomerParams,
UpdateBillingSubscriptionParams,
UpdateBillingPreferencesParams, UpdateBillingSubscriptionParams,
};
use crate::llm::db::LlmDatabase;
use crate::llm::{DEFAULT_MAX_MONTHLY_SPEND, FREE_TIER_MONTHLY_SPENDING_LIMIT};
use crate::rpc::ResultExt as _;
use crate::{AppState, Error, Result};
pub fn router() -> Router {
Router::new()
.route(
"/billing/preferences",
get(get_billing_preferences).put(update_billing_preferences),
)
.route(
"/billing/subscriptions",
get(list_billing_subscriptions).post(create_billing_subscription),
@@ -42,6 +49,82 @@ pub fn router() -> Router {
)
}
#[derive(Debug, Deserialize)]
struct GetBillingPreferencesParams {
github_user_id: i32,
}
#[derive(Debug, Serialize)]
struct BillingPreferencesResponse {
max_monthly_llm_usage_spending_in_cents: i32,
}
async fn get_billing_preferences(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<GetBillingPreferencesParams>,
) -> Result<Json<BillingPreferencesResponse>> {
let user = app
.db
.get_user_by_github_user_id(params.github_user_id)
.await?
.ok_or_else(|| anyhow!("user not found"))?;
let preferences = app.db.get_billing_preferences(user.id).await?;
Ok(Json(BillingPreferencesResponse {
max_monthly_llm_usage_spending_in_cents: preferences
.map_or(DEFAULT_MAX_MONTHLY_SPEND.0 as i32, |preferences| {
preferences.max_monthly_llm_usage_spending_in_cents
}),
}))
}
#[derive(Debug, Deserialize)]
struct UpdateBillingPreferencesBody {
github_user_id: i32,
max_monthly_llm_usage_spending_in_cents: i32,
}
async fn update_billing_preferences(
Extension(app): Extension<Arc<AppState>>,
extract::Json(body): extract::Json<UpdateBillingPreferencesBody>,
) -> Result<Json<BillingPreferencesResponse>> {
let user = app
.db
.get_user_by_github_user_id(body.github_user_id)
.await?
.ok_or_else(|| anyhow!("user not found"))?;
let billing_preferences =
if let Some(_billing_preferences) = app.db.get_billing_preferences(user.id).await? {
app.db
.update_billing_preferences(
user.id,
&UpdateBillingPreferencesParams {
max_monthly_llm_usage_spending_in_cents: ActiveValue::set(
body.max_monthly_llm_usage_spending_in_cents,
),
},
)
.await?
} else {
app.db
.create_billing_preferences(
user.id,
&crate::db::CreateBillingPreferencesParams {
max_monthly_llm_usage_spending_in_cents: body
.max_monthly_llm_usage_spending_in_cents,
},
)
.await?
};
Ok(Json(BillingPreferencesResponse {
max_monthly_llm_usage_spending_in_cents: billing_preferences
.max_monthly_llm_usage_spending_in_cents,
}))
}
#[derive(Debug, Deserialize)]
struct ListBillingSubscriptionsParams {
github_user_id: i32,
@@ -79,7 +162,7 @@ async fn list_billing_subscriptions(
.into_iter()
.map(|subscription| BillingSubscriptionJson {
id: subscription.id,
name: "Zed Pro".to_string(),
name: "Zed LLM Usage".to_string(),
status: subscription.stripe_subscription_status,
cancel_at: subscription.stripe_cancel_at.map(|cancel_at| {
cancel_at
@@ -114,10 +197,10 @@ async fn create_billing_subscription(
.await?
.ok_or_else(|| anyhow!("user not found"))?;
let Some((stripe_client, stripe_price_id)) = app
let Some((stripe_client, stripe_access_price_id)) = app
.stripe_client
.clone()
.zip(app.config.stripe_price_id.clone())
.zip(app.config.stripe_llm_access_price_id.clone())
else {
log::error!("failed to retrieve Stripe client or price ID");
Err(Error::http(
@@ -149,7 +232,7 @@ async fn create_billing_subscription(
params.customer = Some(customer_id);
params.client_reference_id = Some(user.github_login.as_str());
params.line_items = Some(vec![CreateCheckoutSessionLineItems {
price: Some(stripe_price_id.to_string()),
price: Some(stripe_access_price_id.to_string()),
quantity: Some(1),
..Default::default()
}]);
@@ -631,3 +714,106 @@ async fn find_or_create_billing_customer(
Ok(Some(billing_customer))
}
const SYNC_LLM_USAGE_WITH_STRIPE_INTERVAL: Duration = Duration::from_secs(24 * 60 * 60);
pub fn sync_llm_usage_with_stripe_periodically(app: Arc<AppState>, llm_db: LlmDatabase) {
let Some(stripe_client) = app.stripe_client.clone() else {
log::warn!("failed to retrieve Stripe client");
return;
};
let Some(stripe_llm_usage_price_id) = app.config.stripe_llm_usage_price_id.clone() else {
log::warn!("failed to retrieve Stripe LLM usage price ID");
return;
};
let executor = app.executor.clone();
executor.spawn_detached({
let executor = executor.clone();
async move {
loop {
sync_with_stripe(
&app,
&llm_db,
&stripe_client,
stripe_llm_usage_price_id.clone(),
)
.await
.trace_err();
executor.sleep(SYNC_LLM_USAGE_WITH_STRIPE_INTERVAL).await;
}
}
});
}
async fn sync_with_stripe(
app: &Arc<AppState>,
llm_db: &LlmDatabase,
stripe_client: &stripe::Client,
stripe_llm_usage_price_id: Arc<str>,
) -> anyhow::Result<()> {
let subscriptions = app.db.get_active_billing_subscriptions().await?;
for (customer, subscription) in subscriptions {
update_stripe_subscription(
llm_db,
stripe_client,
&stripe_llm_usage_price_id,
customer,
subscription,
)
.await
.log_err();
}
Ok(())
}
async fn update_stripe_subscription(
llm_db: &LlmDatabase,
stripe_client: &stripe::Client,
stripe_llm_usage_price_id: &Arc<str>,
customer: billing_customer::Model,
subscription: billing_subscription::Model,
) -> Result<(), anyhow::Error> {
let monthly_spending = llm_db
.get_user_spending_for_month(customer.user_id, Utc::now())
.await?;
let subscription_id = SubscriptionId::from_str(&subscription.stripe_subscription_id)
.context("failed to parse subscription ID")?;
let monthly_spending_over_free_tier =
monthly_spending.saturating_sub(FREE_TIER_MONTHLY_SPENDING_LIMIT);
let new_quantity = (monthly_spending_over_free_tier.0 as f32 / 100.).ceil();
let current_subscription = Subscription::retrieve(stripe_client, &subscription_id, &[]).await?;
let mut update_params = stripe::UpdateSubscription {
proration_behavior: Some(
stripe::generated::billing::subscription::SubscriptionProrationBehavior::None,
),
..Default::default()
};
if let Some(existing_item) = current_subscription.items.data.iter().find(|item| {
item.price.as_ref().map_or(false, |price| {
price.id == stripe_llm_usage_price_id.as_ref()
})
}) {
update_params.items = Some(vec![stripe::UpdateSubscriptionItems {
id: Some(existing_item.id.to_string()),
quantity: Some(new_quantity as u64),
..Default::default()
}]);
} else {
update_params.items = Some(vec![stripe::UpdateSubscriptionItems {
price: Some(stripe_llm_usage_price_id.to_string()),
quantity: Some(new_quantity as u64),
..Default::default()
}]);
}
Subscription::update(stripe_client, &subscription_id, update_params).await?;
Ok(())
}

View File

@@ -23,7 +23,7 @@ use telemetry_events::{
};
use uuid::Uuid;
static CRASH_REPORTS_BUCKET: &str = "zed-crash-reports";
const CRASH_REPORTS_BUCKET: &str = "zed-crash-reports";
pub fn router() -> Router {
Router::new()
@@ -429,8 +429,6 @@ pub async fn post_events(
country_code.clone(),
checksum_matched,
)),
// Needed for clients sending old copilot_event types
Event::Copilot(_) => {}
Event::InlineCompletion(event) => {
to_upload
.inline_completion_events
@@ -672,13 +670,13 @@ pub struct EditorEventRow {
time: i64,
copilot_enabled: bool,
copilot_enabled_for_language: bool,
historical_event: bool,
architecture: String,
is_staff: Option<bool>,
major: Option<i32>,
minor: Option<i32>,
patch: Option<i32>,
checksum_matched: bool,
is_via_ssh: bool,
}
impl EditorEventRow {
@@ -719,7 +717,7 @@ impl EditorEventRow {
country_code: country_code.unwrap_or("XX".to_string()),
region_code: "".to_string(),
city: "".to_string(),
historical_event: false,
is_via_ssh: event.is_via_ssh,
}
}
}
@@ -1263,6 +1261,7 @@ pub struct EditEventRow {
period_start: i64,
period_end: i64,
environment: String,
is_via_ssh: bool,
}
impl EditEventRow {
@@ -1296,6 +1295,7 @@ impl EditEventRow {
period_start: period_start.timestamp_millis(),
period_end: period_end.timestamp_millis(),
environment: event.environment,
is_via_ssh: event.is_via_ssh,
}
}
}

View File

@@ -0,0 +1,78 @@
/// A number of cents.
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Clone,
Copy,
derive_more::Add,
derive_more::AddAssign,
)]
pub struct Cents(pub u32);
impl Cents {
pub const ZERO: Self = Self(0);
pub const fn new(cents: u32) -> Self {
Self(cents)
}
pub const fn from_dollars(dollars: u32) -> Self {
Self(dollars * 100)
}
pub fn saturating_sub(self, other: Cents) -> Self {
Self(self.0.saturating_sub(other.0))
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn test_cents_new() {
assert_eq!(Cents::new(50), Cents(50));
}
#[test]
fn test_cents_from_dollars() {
assert_eq!(Cents::from_dollars(1), Cents(100));
assert_eq!(Cents::from_dollars(5), Cents(500));
}
#[test]
fn test_cents_zero() {
assert_eq!(Cents::ZERO, Cents(0));
}
#[test]
fn test_cents_add() {
assert_eq!(Cents(50) + Cents(30), Cents(80));
}
#[test]
fn test_cents_add_assign() {
let mut cents = Cents(50);
cents += Cents(30);
assert_eq!(cents, Cents(80));
}
#[test]
fn test_cents_saturating_sub() {
assert_eq!(Cents(50).saturating_sub(Cents(30)), Cents(20));
assert_eq!(Cents(30).saturating_sub(Cents(50)), Cents(0));
}
#[test]
fn test_cents_ordering() {
assert!(Cents(50) > Cents(30));
assert!(Cents(30) < Cents(50));
assert_eq!(Cents(50), Cents(50));
}
}

View File

@@ -35,12 +35,16 @@ use std::{
};
use time::PrimitiveDateTime;
use tokio::sync::{Mutex, OwnedMutexGuard};
use worktree_settings_file::LocalSettingsKind;
#[cfg(test)]
pub use tests::TestDb;
pub use ids::*;
pub use queries::billing_customers::{CreateBillingCustomerParams, UpdateBillingCustomerParams};
pub use queries::billing_preferences::{
CreateBillingPreferencesParams, UpdateBillingPreferencesParams,
};
pub use queries::billing_subscriptions::{
CreateBillingSubscriptionParams, UpdateBillingSubscriptionParams,
};
@@ -766,6 +770,7 @@ pub struct Worktree {
pub struct WorktreeSettingsFile {
pub path: String,
pub content: String,
pub kind: LocalSettingsKind,
}
pub struct NewExtensionVersion {
@@ -783,3 +788,21 @@ pub struct ExtensionVersionConstraints {
pub schema_versions: RangeInclusive<i32>,
pub wasm_api_versions: RangeInclusive<SemanticVersion>,
}
impl LocalSettingsKind {
pub fn from_proto(proto_kind: proto::LocalSettingsKind) -> Self {
match proto_kind {
proto::LocalSettingsKind::Settings => Self::Settings,
proto::LocalSettingsKind::Tasks => Self::Tasks,
proto::LocalSettingsKind::Editorconfig => Self::Editorconfig,
}
}
pub fn to_proto(&self) -> proto::LocalSettingsKind {
match self {
Self::Settings => proto::LocalSettingsKind::Settings,
Self::Tasks => proto::LocalSettingsKind::Tasks,
Self::Editorconfig => proto::LocalSettingsKind::Editorconfig,
}
}
}

View File

@@ -72,6 +72,7 @@ macro_rules! id_type {
id_type!(AccessTokenId);
id_type!(BillingCustomerId);
id_type!(BillingSubscriptionId);
id_type!(BillingPreferencesId);
id_type!(BufferId);
id_type!(ChannelBufferCollaboratorId);
id_type!(ChannelChatParticipantId);

View File

@@ -2,6 +2,7 @@ use super::*;
pub mod access_tokens;
pub mod billing_customers;
pub mod billing_preferences;
pub mod billing_subscriptions;
pub mod buffers;
pub mod channels;

View File

@@ -0,0 +1,75 @@
use super::*;
#[derive(Debug)]
pub struct CreateBillingPreferencesParams {
pub max_monthly_llm_usage_spending_in_cents: i32,
}
#[derive(Debug, Default)]
pub struct UpdateBillingPreferencesParams {
pub max_monthly_llm_usage_spending_in_cents: ActiveValue<i32>,
}
impl Database {
/// Returns the billing preferences for the given user, if they exist.
pub async fn get_billing_preferences(
&self,
user_id: UserId,
) -> Result<Option<billing_preference::Model>> {
self.transaction(|tx| async move {
Ok(billing_preference::Entity::find()
.filter(billing_preference::Column::UserId.eq(user_id))
.one(&*tx)
.await?)
})
.await
}
/// Creates new billing preferences for the given user.
pub async fn create_billing_preferences(
&self,
user_id: UserId,
params: &CreateBillingPreferencesParams,
) -> Result<billing_preference::Model> {
self.transaction(|tx| async move {
let preferences = billing_preference::Entity::insert(billing_preference::ActiveModel {
user_id: ActiveValue::set(user_id),
max_monthly_llm_usage_spending_in_cents: ActiveValue::set(
params.max_monthly_llm_usage_spending_in_cents,
),
..Default::default()
})
.exec_with_returning(&*tx)
.await?;
Ok(preferences)
})
.await
}
/// Updates the billing preferences for the given user.
pub async fn update_billing_preferences(
&self,
user_id: UserId,
params: &UpdateBillingPreferencesParams,
) -> Result<billing_preference::Model> {
self.transaction(|tx| async move {
let preferences = billing_preference::Entity::update_many()
.set(billing_preference::ActiveModel {
max_monthly_llm_usage_spending_in_cents: params
.max_monthly_llm_usage_spending_in_cents
.clone(),
..Default::default()
})
.filter(billing_preference::Column::UserId.eq(user_id))
.exec_with_returning(&*tx)
.await?;
Ok(preferences
.into_iter()
.next()
.ok_or_else(|| anyhow!("billing preferences not found"))?)
})
.await
}
}

View File

@@ -112,6 +112,29 @@ impl Database {
.await
}
pub async fn get_active_billing_subscriptions(
&self,
) -> Result<Vec<(billing_customer::Model, billing_subscription::Model)>> {
self.transaction(|tx| async move {
let mut result = Vec::new();
let mut rows = billing_subscription::Entity::find()
.inner_join(billing_customer::Entity)
.select_also(billing_customer::Entity)
.order_by_asc(billing_subscription::Column::Id)
.stream(&*tx)
.await?;
while let Some(row) = rows.next().await {
if let (subscription, Some(customer)) = row? {
result.push((customer, subscription));
}
}
Ok(result)
})
.await
}
/// Returns whether the user has an active billing subscription.
pub async fn has_active_billing_subscription(&self, user_id: UserId) -> Result<bool> {
Ok(self.count_active_billing_subscriptions(user_id).await? > 0)

View File

@@ -1,3 +1,4 @@
use anyhow::Context as _;
use util::ResultExt;
use super::*;
@@ -527,6 +528,12 @@ impl Database {
connection: ConnectionId,
) -> Result<TransactionGuard<Vec<ConnectionId>>> {
let project_id = ProjectId::from_proto(update.project_id);
let kind = match update.kind {
Some(kind) => proto::LocalSettingsKind::from_i32(kind)
.with_context(|| format!("unknown worktree settings kind: {kind}"))?,
None => proto::LocalSettingsKind::Settings,
};
let kind = LocalSettingsKind::from_proto(kind);
self.project_transaction(project_id, |tx| async move {
// Ensure the update comes from the host.
let project = project::Entity::find_by_id(project_id)
@@ -543,6 +550,7 @@ impl Database {
worktree_id: ActiveValue::Set(update.worktree_id as i64),
path: ActiveValue::Set(update.path.clone()),
content: ActiveValue::Set(content.clone()),
kind: ActiveValue::Set(kind),
})
.on_conflict(
OnConflict::columns([
@@ -800,6 +808,7 @@ impl Database {
worktree.settings_files.push(WorktreeSettingsFile {
path: db_settings_file.path,
content: db_settings_file.content,
kind: db_settings_file.kind,
});
}
}

View File

@@ -735,6 +735,7 @@ impl Database {
worktree.settings_files.push(WorktreeSettingsFile {
path: db_settings_file.path,
content: db_settings_file.content,
kind: db_settings_file.kind,
});
}
}

View File

@@ -1,5 +1,6 @@
pub mod access_token;
pub mod billing_customer;
pub mod billing_preference;
pub mod billing_subscription;
pub mod buffer;
pub mod buffer_operation;

View File

@@ -0,0 +1,30 @@
use crate::db::{BillingPreferencesId, UserId};
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
#[sea_orm(table_name = "billing_preferences")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: BillingPreferencesId,
pub created_at: DateTime,
pub user_id: UserId,
pub max_monthly_llm_usage_spending_in_cents: i32,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::user::Entity",
from = "Column::UserId",
to = "super::user::Column::Id"
)]
User,
}
impl Related<super::user::Entity> for Entity {
fn to() -> RelationDef {
Relation::User.def()
}
}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -11,9 +11,25 @@ pub struct Model {
#[sea_orm(primary_key)]
pub path: String,
pub content: String,
pub kind: LocalSettingsKind,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}
#[derive(
Copy, Clone, Debug, PartialEq, Eq, EnumIter, DeriveActiveEnum, Default, Hash, serde::Serialize,
)]
#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
#[serde(rename_all = "snake_case")]
pub enum LocalSettingsKind {
#[default]
#[sea_orm(string_value = "settings")]
Settings,
#[sea_orm(string_value = "tasks")]
Tasks,
#[sea_orm(string_value = "editorconfig")]
Editorconfig,
}

View File

@@ -1,5 +1,6 @@
pub mod api;
pub mod auth;
mod cents;
pub mod clickhouse;
pub mod db;
pub mod env;
@@ -20,6 +21,7 @@ use axum::{
http::{HeaderMap, StatusCode},
response::IntoResponse,
};
pub use cents::*;
use db::{ChannelId, Database};
use executor::Executor;
pub use rate_limiter::*;
@@ -174,7 +176,8 @@ pub struct Config {
pub slack_panics_webhook: Option<String>,
pub auto_join_channel_id: Option<ChannelId>,
pub stripe_api_key: Option<String>,
pub stripe_price_id: Option<Arc<str>>,
pub stripe_llm_access_price_id: Option<Arc<str>>,
pub stripe_llm_usage_price_id: Option<Arc<str>>,
pub supermaven_admin_api_key: Option<Arc<str>>,
pub user_backfiller_github_access_token: Option<Arc<str>>,
}
@@ -193,6 +196,10 @@ impl Config {
}
}
pub fn is_llm_billing_enabled(&self) -> bool {
self.stripe_llm_usage_price_id.is_some()
}
#[cfg(test)]
pub fn test() -> Self {
Self {
@@ -231,7 +238,8 @@ impl Config {
migrations_path: None,
seed_path: None,
stripe_api_key: None,
stripe_price_id: None,
stripe_llm_access_price_id: None,
stripe_llm_usage_price_id: None,
supermaven_admin_api_key: None,
user_backfiller_github_access_token: None,
}

View File

@@ -4,7 +4,7 @@ mod telemetry;
mod token;
use crate::{
api::CloudflareIpCountryHeader, build_clickhouse_client, db::UserId, executor::Executor,
api::CloudflareIpCountryHeader, build_clickhouse_client, db::UserId, executor::Executor, Cents,
Config, Error, Result,
};
use anyhow::{anyhow, Context as _};
@@ -320,22 +320,31 @@ async fn perform_completion(
chunks
.map(move |event| {
let chunk = event?;
let (input_tokens, output_tokens) = match &chunk {
let (
input_tokens,
output_tokens,
cache_creation_input_tokens,
cache_read_input_tokens,
) = match &chunk {
anthropic::Event::MessageStart {
message: anthropic::Response { usage, .. },
}
| anthropic::Event::MessageDelta { usage, .. } => (
usage.input_tokens.unwrap_or(0) as usize,
usage.output_tokens.unwrap_or(0) as usize,
usage.cache_creation_input_tokens.unwrap_or(0) as usize,
usage.cache_read_input_tokens.unwrap_or(0) as usize,
),
_ => (0, 0),
_ => (0, 0, 0, 0),
};
anyhow::Ok((
serde_json::to_vec(&chunk).unwrap(),
anyhow::Ok(CompletionChunk {
bytes: serde_json::to_vec(&chunk).unwrap(),
input_tokens,
output_tokens,
))
cache_creation_input_tokens,
cache_read_input_tokens,
})
})
.boxed()
}
@@ -361,11 +370,13 @@ async fn perform_completion(
chunk.usage.as_ref().map_or(0, |u| u.prompt_tokens) as usize;
let output_tokens =
chunk.usage.as_ref().map_or(0, |u| u.completion_tokens) as usize;
(
serde_json::to_vec(&chunk).unwrap(),
CompletionChunk {
bytes: serde_json::to_vec(&chunk).unwrap(),
input_tokens,
output_tokens,
)
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
}
})
})
.boxed()
@@ -389,13 +400,13 @@ async fn perform_completion(
.map(|event| {
event.map(|chunk| {
// TODO - implement token counting for Google AI
let input_tokens = 0;
let output_tokens = 0;
(
serde_json::to_vec(&chunk).unwrap(),
input_tokens,
output_tokens,
)
CompletionChunk {
bytes: serde_json::to_vec(&chunk).unwrap(),
input_tokens: 0,
output_tokens: 0,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
}
})
})
.boxed()
@@ -409,6 +420,8 @@ async fn perform_completion(
model,
input_tokens: 0,
output_tokens: 0,
cache_creation_input_tokens: 0,
cache_read_input_tokens: 0,
inner_stream: stream,
})))
}
@@ -425,10 +438,18 @@ fn normalize_model_name(known_models: Vec<String>, name: String) -> String {
}
}
/// The maximum lifetime spending an individual user can reach before being cut off.
/// The maximum monthly spending an individual user can reach on the free tier
/// before they have to pay.
pub const FREE_TIER_MONTHLY_SPENDING_LIMIT: Cents = Cents::from_dollars(5);
/// The default value to use for maximum spend per month if the user did not
/// explicitly set a maximum spend.
///
/// Represented in cents.
const LIFETIME_SPENDING_LIMIT_IN_CENTS: usize = 1_000 * 100;
/// Used to prevent surprise bills.
pub const DEFAULT_MAX_MONTHLY_SPEND: Cents = Cents::from_dollars(10);
/// The maximum lifetime spending an individual user can reach before being cut off.
const LIFETIME_SPENDING_LIMIT: Cents = Cents::from_dollars(1_000);
async fn check_usage_limit(
state: &Arc<LlmState>,
@@ -447,7 +468,19 @@ async fn check_usage_limit(
)
.await?;
if usage.lifetime_spending >= LIFETIME_SPENDING_LIMIT_IN_CENTS {
if state.config.is_llm_billing_enabled() {
if usage.spending_this_month >= FREE_TIER_MONTHLY_SPENDING_LIMIT {
if !claims.has_llm_subscription {
return Err(Error::http(
StatusCode::PAYMENT_REQUIRED,
"Maximum spending limit reached for this month.".to_string(),
));
}
}
}
// TODO: Remove this once we've rolled out monthly spending limits.
if usage.lifetime_spending >= LIFETIME_SPENDING_LIMIT {
return Err(Error::http(
StatusCode::FORBIDDEN,
"Maximum spending limit reached.".to_string(),
@@ -494,7 +527,6 @@ async fn check_usage_limit(
UsageMeasure::RequestsPerMinute => "requests_per_minute",
UsageMeasure::TokensPerMinute => "tokens_per_minute",
UsageMeasure::TokensPerDay => "tokens_per_day",
_ => "",
};
if let Some(client) = state.clickhouse_client.as_ref() {
@@ -553,6 +585,14 @@ async fn check_usage_limit(
Ok(())
}
struct CompletionChunk {
bytes: Vec<u8>,
input_tokens: usize,
output_tokens: usize,
cache_creation_input_tokens: usize,
cache_read_input_tokens: usize,
}
struct TokenCountingStream<S> {
state: Arc<LlmState>,
claims: LlmTokenClaims,
@@ -560,22 +600,26 @@ struct TokenCountingStream<S> {
model: String,
input_tokens: usize,
output_tokens: usize,
cache_creation_input_tokens: usize,
cache_read_input_tokens: usize,
inner_stream: S,
}
impl<S> Stream for TokenCountingStream<S>
where
S: Stream<Item = Result<(Vec<u8>, usize, usize), anyhow::Error>> + Unpin,
S: Stream<Item = Result<CompletionChunk, anyhow::Error>> + Unpin,
{
type Item = Result<Vec<u8>, anyhow::Error>;
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
match Pin::new(&mut self.inner_stream).poll_next(cx) {
Poll::Ready(Some(Ok((mut bytes, input_tokens, output_tokens)))) => {
bytes.push(b'\n');
self.input_tokens += input_tokens;
self.output_tokens += output_tokens;
Poll::Ready(Some(Ok(bytes)))
Poll::Ready(Some(Ok(mut chunk))) => {
chunk.bytes.push(b'\n');
self.input_tokens += chunk.input_tokens;
self.output_tokens += chunk.output_tokens;
self.cache_creation_input_tokens += chunk.cache_creation_input_tokens;
self.cache_read_input_tokens += chunk.cache_read_input_tokens;
Poll::Ready(Some(Ok(chunk.bytes)))
}
Poll::Ready(Some(Err(e))) => Poll::Ready(Some(Err(e))),
Poll::Ready(None) => Poll::Ready(None),
@@ -592,6 +636,8 @@ impl<S> Drop for TokenCountingStream<S> {
let model = std::mem::take(&mut self.model);
let input_token_count = self.input_tokens;
let output_token_count = self.output_tokens;
let cache_creation_input_token_count = self.cache_creation_input_tokens;
let cache_read_input_token_count = self.cache_read_input_tokens;
self.state.executor.spawn_detached(async move {
let usage = state
.db
@@ -601,6 +647,8 @@ impl<S> Drop for TokenCountingStream<S> {
provider,
&model,
input_token_count,
cache_creation_input_token_count,
cache_read_input_token_count,
output_token_count,
Utc::now(),
)
@@ -632,14 +680,23 @@ impl<S> Drop for TokenCountingStream<S> {
model,
provider: provider.to_string(),
input_token_count: input_token_count as u64,
cache_creation_input_token_count: cache_creation_input_token_count
as u64,
cache_read_input_token_count: cache_read_input_token_count as u64,
output_token_count: output_token_count as u64,
requests_this_minute: usage.requests_this_minute as u64,
tokens_this_minute: usage.tokens_this_minute as u64,
tokens_this_day: usage.tokens_this_day as u64,
input_tokens_this_month: usage.input_tokens_this_month as u64,
cache_creation_input_tokens_this_month: usage
.cache_creation_input_tokens_this_month
as u64,
cache_read_input_tokens_this_month: usage
.cache_read_input_tokens_this_month
as u64,
output_tokens_this_month: usage.output_tokens_this_month as u64,
spending_this_month: usage.spending_this_month as u64,
lifetime_spending: usage.lifetime_spending as u64,
spending_this_month: usage.spending_this_month.0 as u64,
lifetime_spending: usage.lifetime_spending.0 as u64,
},
)
.await

View File

@@ -97,6 +97,14 @@ impl LlmDatabase {
.ok_or_else(|| anyhow!("unknown model {provider:?}:{name}"))?)
}
pub fn model_by_id(&self, id: ModelId) -> Result<&model::Model> {
Ok(self
.models
.values()
.find(|model| model.id == id)
.ok_or_else(|| anyhow!("no model for ID {id:?}"))?)
}
pub fn options(&self) -> &ConnectOptions {
&self.options
}

View File

@@ -1,5 +1,6 @@
use crate::db::UserId;
use chrono::Duration;
use crate::llm::Cents;
use chrono::{Datelike, Duration};
use futures::StreamExt as _;
use rpc::LanguageModelProvider;
use sea_orm::QuerySelect;
@@ -14,9 +15,11 @@ pub struct Usage {
pub tokens_this_minute: usize,
pub tokens_this_day: usize,
pub input_tokens_this_month: usize,
pub cache_creation_input_tokens_this_month: usize,
pub cache_read_input_tokens_this_month: usize,
pub output_tokens_this_month: usize,
pub spending_this_month: usize,
pub lifetime_spending: usize,
pub spending_this_month: Cents,
pub lifetime_spending: Cents,
}
#[derive(Debug, PartialEq, Clone)]
@@ -138,6 +141,46 @@ impl LlmDatabase {
.await
}
pub async fn get_user_spending_for_month(
&self,
user_id: UserId,
now: DateTimeUtc,
) -> Result<Cents> {
self.transaction(|tx| async move {
let month = now.date_naive().month() as i32;
let year = now.date_naive().year();
let mut monthly_usages = monthly_usage::Entity::find()
.filter(
monthly_usage::Column::UserId
.eq(user_id)
.and(monthly_usage::Column::Month.eq(month))
.and(monthly_usage::Column::Year.eq(year)),
)
.stream(&*tx)
.await?;
let mut monthly_spending = Cents::ZERO;
while let Some(usage) = monthly_usages.next().await {
let usage = usage?;
let Ok(model) = self.model_by_id(usage.model_id) else {
continue;
};
monthly_spending += calculate_spending(
model,
usage.input_tokens as usize,
usage.cache_creation_input_tokens as usize,
usage.cache_read_input_tokens as usize,
usage.output_tokens as usize,
);
}
Ok(monthly_spending)
})
.await
}
pub async fn get_usage(
&self,
user_id: UserId,
@@ -160,17 +203,26 @@ impl LlmDatabase {
.all(&*tx)
.await?;
let (lifetime_input_tokens, lifetime_output_tokens) = lifetime_usage::Entity::find()
let month = now.date_naive().month() as i32;
let year = now.date_naive().year();
let monthly_usage = monthly_usage::Entity::find()
.filter(
monthly_usage::Column::UserId
.eq(user_id)
.and(monthly_usage::Column::ModelId.eq(model.id))
.and(monthly_usage::Column::Month.eq(month))
.and(monthly_usage::Column::Year.eq(year)),
)
.one(&*tx)
.await?;
let lifetime_usage = lifetime_usage::Entity::find()
.filter(
lifetime_usage::Column::UserId
.eq(user_id)
.and(lifetime_usage::Column::ModelId.eq(model.id)),
)
.one(&*tx)
.await?
.map_or((0, 0), |usage| {
(usage.input_tokens as usize, usage.output_tokens as usize)
});
.await?;
let requests_this_minute =
self.get_usage_for_measure(&usages, now, UsageMeasure::RequestsPerMinute)?;
@@ -178,21 +230,45 @@ impl LlmDatabase {
self.get_usage_for_measure(&usages, now, UsageMeasure::TokensPerMinute)?;
let tokens_this_day =
self.get_usage_for_measure(&usages, now, UsageMeasure::TokensPerDay)?;
let input_tokens_this_month =
self.get_usage_for_measure(&usages, now, UsageMeasure::InputTokensPerMonth)?;
let output_tokens_this_month =
self.get_usage_for_measure(&usages, now, UsageMeasure::OutputTokensPerMonth)?;
let spending_this_month =
calculate_spending(model, input_tokens_this_month, output_tokens_this_month);
let lifetime_spending =
calculate_spending(model, lifetime_input_tokens, lifetime_output_tokens);
let spending_this_month = if let Some(monthly_usage) = &monthly_usage {
calculate_spending(
model,
monthly_usage.input_tokens as usize,
monthly_usage.cache_creation_input_tokens as usize,
monthly_usage.cache_read_input_tokens as usize,
monthly_usage.output_tokens as usize,
)
} else {
Cents::ZERO
};
let lifetime_spending = if let Some(lifetime_usage) = &lifetime_usage {
calculate_spending(
model,
lifetime_usage.input_tokens as usize,
lifetime_usage.cache_creation_input_tokens as usize,
lifetime_usage.cache_read_input_tokens as usize,
lifetime_usage.output_tokens as usize,
)
} else {
Cents::ZERO
};
Ok(Usage {
requests_this_minute,
tokens_this_minute,
tokens_this_day,
input_tokens_this_month,
output_tokens_this_month,
input_tokens_this_month: monthly_usage
.as_ref()
.map_or(0, |usage| usage.input_tokens as usize),
cache_creation_input_tokens_this_month: monthly_usage
.as_ref()
.map_or(0, |usage| usage.cache_creation_input_tokens as usize),
cache_read_input_tokens_this_month: monthly_usage
.as_ref()
.map_or(0, |usage| usage.cache_read_input_tokens as usize),
output_tokens_this_month: monthly_usage
.as_ref()
.map_or(0, |usage| usage.output_tokens as usize),
spending_this_month,
lifetime_spending,
})
@@ -208,6 +284,8 @@ impl LlmDatabase {
provider: LanguageModelProvider,
model_name: &str,
input_token_count: usize,
cache_creation_input_tokens: usize,
cache_read_input_tokens: usize,
output_token_count: usize,
now: DateTimeUtc,
) -> Result<Usage> {
@@ -235,6 +313,10 @@ impl LlmDatabase {
&tx,
)
.await?;
let total_token_count = input_token_count
+ cache_read_input_tokens
+ cache_creation_input_tokens
+ output_token_count;
let tokens_this_minute = self
.update_usage_for_measure(
user_id,
@@ -243,7 +325,7 @@ impl LlmDatabase {
&usages,
UsageMeasure::TokensPerMinute,
now,
input_token_count + output_token_count,
total_token_count,
&tx,
)
.await?;
@@ -255,36 +337,73 @@ impl LlmDatabase {
&usages,
UsageMeasure::TokensPerDay,
now,
input_token_count + output_token_count,
total_token_count,
&tx,
)
.await?;
let input_tokens_this_month = self
.update_usage_for_measure(
user_id,
is_staff,
model.id,
&usages,
UsageMeasure::InputTokensPerMonth,
now,
input_token_count,
&tx,
let month = now.date_naive().month() as i32;
let year = now.date_naive().year();
// Update monthly usage
let monthly_usage = monthly_usage::Entity::find()
.filter(
monthly_usage::Column::UserId
.eq(user_id)
.and(monthly_usage::Column::ModelId.eq(model.id))
.and(monthly_usage::Column::Month.eq(month))
.and(monthly_usage::Column::Year.eq(year)),
)
.one(&*tx)
.await?;
let output_tokens_this_month = self
.update_usage_for_measure(
user_id,
is_staff,
model.id,
&usages,
UsageMeasure::OutputTokensPerMonth,
now,
output_token_count,
&tx,
)
.await?;
let spending_this_month =
calculate_spending(model, input_tokens_this_month, output_tokens_this_month);
let monthly_usage = match monthly_usage {
Some(usage) => {
monthly_usage::Entity::update(monthly_usage::ActiveModel {
id: ActiveValue::unchanged(usage.id),
input_tokens: ActiveValue::set(
usage.input_tokens + input_token_count as i64,
),
cache_creation_input_tokens: ActiveValue::set(
usage.cache_creation_input_tokens + cache_creation_input_tokens as i64,
),
cache_read_input_tokens: ActiveValue::set(
usage.cache_read_input_tokens + cache_read_input_tokens as i64,
),
output_tokens: ActiveValue::set(
usage.output_tokens + output_token_count as i64,
),
..Default::default()
})
.exec(&*tx)
.await?
}
None => {
monthly_usage::ActiveModel {
user_id: ActiveValue::set(user_id),
model_id: ActiveValue::set(model.id),
month: ActiveValue::set(month),
year: ActiveValue::set(year),
input_tokens: ActiveValue::set(input_token_count as i64),
cache_creation_input_tokens: ActiveValue::set(
cache_creation_input_tokens as i64,
),
cache_read_input_tokens: ActiveValue::set(cache_read_input_tokens as i64),
output_tokens: ActiveValue::set(output_token_count as i64),
..Default::default()
}
.insert(&*tx)
.await?
}
};
let spending_this_month = calculate_spending(
model,
monthly_usage.input_tokens as usize,
monthly_usage.cache_creation_input_tokens as usize,
monthly_usage.cache_read_input_tokens as usize,
monthly_usage.output_tokens as usize,
);
// Update lifetime usage
let lifetime_usage = lifetime_usage::Entity::find()
@@ -303,6 +422,12 @@ impl LlmDatabase {
input_tokens: ActiveValue::set(
usage.input_tokens + input_token_count as i64,
),
cache_creation_input_tokens: ActiveValue::set(
usage.cache_creation_input_tokens + cache_creation_input_tokens as i64,
),
cache_read_input_tokens: ActiveValue::set(
usage.cache_read_input_tokens + cache_read_input_tokens as i64,
),
output_tokens: ActiveValue::set(
usage.output_tokens + output_token_count as i64,
),
@@ -316,6 +441,10 @@ impl LlmDatabase {
user_id: ActiveValue::set(user_id),
model_id: ActiveValue::set(model.id),
input_tokens: ActiveValue::set(input_token_count as i64),
cache_creation_input_tokens: ActiveValue::set(
cache_creation_input_tokens as i64,
),
cache_read_input_tokens: ActiveValue::set(cache_read_input_tokens as i64),
output_tokens: ActiveValue::set(output_token_count as i64),
..Default::default()
}
@@ -327,6 +456,8 @@ impl LlmDatabase {
let lifetime_spending = calculate_spending(
model,
lifetime_usage.input_tokens as usize,
lifetime_usage.cache_creation_input_tokens as usize,
lifetime_usage.cache_read_input_tokens as usize,
lifetime_usage.output_tokens as usize,
);
@@ -334,8 +465,11 @@ impl LlmDatabase {
requests_this_minute,
tokens_this_minute,
tokens_this_day,
input_tokens_this_month,
output_tokens_this_month,
input_tokens_this_month: monthly_usage.input_tokens as usize,
cache_creation_input_tokens_this_month: monthly_usage.cache_creation_input_tokens
as usize,
cache_read_input_tokens_this_month: monthly_usage.cache_read_input_tokens as usize,
output_tokens_this_month: monthly_usage.output_tokens as usize,
spending_this_month,
lifetime_spending,
})
@@ -501,18 +635,29 @@ impl LlmDatabase {
fn calculate_spending(
model: &model::Model,
input_tokens_this_month: usize,
cache_creation_input_tokens_this_month: usize,
cache_read_input_tokens_this_month: usize,
output_tokens_this_month: usize,
) -> usize {
) -> Cents {
let input_token_cost =
input_tokens_this_month * model.price_per_million_input_tokens as usize / 1_000_000;
let cache_creation_input_token_cost = cache_creation_input_tokens_this_month
* model.price_per_million_cache_creation_input_tokens as usize
/ 1_000_000;
let cache_read_input_token_cost = cache_read_input_tokens_this_month
* model.price_per_million_cache_read_input_tokens as usize
/ 1_000_000;
let output_token_cost =
output_tokens_this_month * model.price_per_million_output_tokens as usize / 1_000_000;
input_token_cost + output_token_cost
let spending = input_token_cost
+ cache_creation_input_token_cost
+ cache_read_input_token_cost
+ output_token_cost;
Cents::new(spending as u32)
}
const MINUTE_BUCKET_COUNT: usize = 12;
const DAY_BUCKET_COUNT: usize = 48;
const MONTH_BUCKET_COUNT: usize = 30;
impl UsageMeasure {
fn bucket_count(&self) -> usize {
@@ -520,8 +665,6 @@ impl UsageMeasure {
UsageMeasure::RequestsPerMinute => MINUTE_BUCKET_COUNT,
UsageMeasure::TokensPerMinute => MINUTE_BUCKET_COUNT,
UsageMeasure::TokensPerDay => DAY_BUCKET_COUNT,
UsageMeasure::InputTokensPerMonth => MONTH_BUCKET_COUNT,
UsageMeasure::OutputTokensPerMonth => MONTH_BUCKET_COUNT,
}
}
@@ -530,8 +673,6 @@ impl UsageMeasure {
UsageMeasure::RequestsPerMinute => Duration::minutes(1),
UsageMeasure::TokensPerMinute => Duration::minutes(1),
UsageMeasure::TokensPerDay => Duration::hours(24),
UsageMeasure::InputTokensPerMonth => Duration::days(30),
UsageMeasure::OutputTokensPerMonth => Duration::days(30),
}
}

View File

@@ -1,5 +1,6 @@
pub mod lifetime_usage;
pub mod model;
pub mod monthly_usage;
pub mod provider;
pub mod revoked_access_token;
pub mod usage;

View File

@@ -9,6 +9,8 @@ pub struct Model {
pub user_id: UserId,
pub model_id: ModelId,
pub input_tokens: i64,
pub cache_creation_input_tokens: i64,
pub cache_read_input_tokens: i64,
pub output_tokens: i64,
}

View File

@@ -14,6 +14,8 @@ pub struct Model {
pub max_tokens_per_minute: i64,
pub max_tokens_per_day: i64,
pub price_per_million_input_tokens: i32,
pub price_per_million_cache_creation_input_tokens: i32,
pub price_per_million_cache_read_input_tokens: i32,
pub price_per_million_output_tokens: i32,
}

View File

@@ -0,0 +1,22 @@
use crate::{db::UserId, llm::db::ModelId};
use sea_orm::entity::prelude::*;
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
#[sea_orm(table_name = "monthly_usages")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,
pub user_id: UserId,
pub model_id: ModelId,
pub month: i32,
pub year: i32,
pub input_tokens: i64,
pub cache_creation_input_tokens: i64,
pub cache_read_input_tokens: i64,
pub output_tokens: i64,
}
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
pub enum Relation {}
impl ActiveModelBehavior for ActiveModel {}

View File

@@ -9,8 +9,6 @@ pub enum UsageMeasure {
RequestsPerMinute,
TokensPerMinute,
TokensPerDay,
InputTokensPerMonth,
OutputTokensPerMonth,
}
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]

View File

@@ -4,9 +4,9 @@ use crate::{
queries::{providers::ModelParams, usages::Usage},
LlmDatabase,
},
test_llm_db,
test_llm_db, Cents,
};
use chrono::{Duration, Utc};
use chrono::{DateTime, Duration, Utc};
use pretty_assertions::assert_eq;
use rpc::LanguageModelProvider;
@@ -29,16 +29,19 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
.await
.unwrap();
let t0 = Utc::now();
// We're using a fixed datetime to prevent flakiness based on the clock.
let t0 = DateTime::parse_from_rfc3339("2024-08-08T22:46:33Z")
.unwrap()
.with_timezone(&Utc);
let user_id = UserId::from_proto(123);
let now = t0;
db.record_usage(user_id, false, provider, model, 1000, 0, now)
db.record_usage(user_id, false, provider, model, 1000, 0, 0, 0, now)
.await
.unwrap();
let now = t0 + Duration::seconds(10);
db.record_usage(user_id, false, provider, model, 2000, 0, now)
db.record_usage(user_id, false, provider, model, 2000, 0, 0, 0, now)
.await
.unwrap();
@@ -50,9 +53,11 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
tokens_this_minute: 3000,
tokens_this_day: 3000,
input_tokens_this_month: 3000,
cache_creation_input_tokens_this_month: 0,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
@@ -65,14 +70,16 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
tokens_this_minute: 2000,
tokens_this_day: 3000,
input_tokens_this_month: 3000,
cache_creation_input_tokens_this_month: 0,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
let now = t0 + Duration::seconds(60);
db.record_usage(user_id, false, provider, model, 3000, 0, now)
db.record_usage(user_id, false, provider, model, 3000, 0, 0, 0, now)
.await
.unwrap();
@@ -84,9 +91,11 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
tokens_this_minute: 5000,
tokens_this_day: 6000,
input_tokens_this_month: 6000,
cache_creation_input_tokens_this_month: 0,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
@@ -100,13 +109,15 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
tokens_this_minute: 0,
tokens_this_day: 5000,
input_tokens_this_month: 6000,
cache_creation_input_tokens_this_month: 0,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
db.record_usage(user_id, false, provider, model, 4000, 0, now)
db.record_usage(user_id, false, provider, model, 4000, 0, 0, 0, now)
.await
.unwrap();
@@ -118,25 +129,58 @@ async fn test_tracking_usage(db: &mut LlmDatabase) {
tokens_this_minute: 4000,
tokens_this_day: 9000,
input_tokens_this_month: 10000,
cache_creation_input_tokens_this_month: 0,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
let t2 = t0 + Duration::days(30);
let now = t2;
// We're using a fixed datetime to prevent flakiness based on the clock.
let now = DateTime::parse_from_rfc3339("2024-10-08T22:15:58Z")
.unwrap()
.with_timezone(&Utc);
// Test cache creation input tokens
db.record_usage(user_id, false, provider, model, 1000, 500, 0, 0, now)
.await
.unwrap();
let usage = db.get_usage(user_id, provider, model, now).await.unwrap();
assert_eq!(
usage,
Usage {
requests_this_minute: 0,
tokens_this_minute: 0,
tokens_this_day: 0,
input_tokens_this_month: 9000,
requests_this_minute: 1,
tokens_this_minute: 1500,
tokens_this_day: 1500,
input_tokens_this_month: 1000,
cache_creation_input_tokens_this_month: 500,
cache_read_input_tokens_this_month: 0,
output_tokens_this_month: 0,
spending_this_month: 0,
lifetime_spending: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
// Test cache read input tokens
db.record_usage(user_id, false, provider, model, 1000, 0, 300, 0, now)
.await
.unwrap();
let usage = db.get_usage(user_id, provider, model, now).await.unwrap();
assert_eq!(
usage,
Usage {
requests_this_minute: 2,
tokens_this_minute: 2800,
tokens_this_day: 2800,
input_tokens_this_month: 2000,
cache_creation_input_tokens_this_month: 500,
cache_read_input_tokens_this_month: 300,
output_tokens_this_month: 0,
spending_this_month: Cents::ZERO,
lifetime_spending: Cents::ZERO,
}
);
}

View File

@@ -12,11 +12,15 @@ pub struct LlmUsageEventRow {
pub model: String,
pub provider: String,
pub input_token_count: u64,
pub cache_creation_input_token_count: u64,
pub cache_read_input_token_count: u64,
pub output_token_count: u64,
pub requests_this_minute: u64,
pub tokens_this_minute: u64,
pub tokens_this_day: u64,
pub input_tokens_this_month: u64,
pub cache_creation_input_tokens_this_month: u64,
pub cache_read_input_tokens_this_month: u64,
pub output_tokens_this_month: u64,
pub spending_this_month: u64,
pub lifetime_spending: u64,

View File

@@ -1,4 +1,8 @@
use crate::{db::UserId, Config};
use crate::llm::DEFAULT_MAX_MONTHLY_SPEND;
use crate::{
db::{billing_preference, UserId},
Config,
};
use anyhow::{anyhow, Result};
use chrono::Utc;
use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation};
@@ -13,26 +17,25 @@ pub struct LlmTokenClaims {
pub exp: u64,
pub jti: String,
pub user_id: u64,
// This field is temporarily optional so it can be added
// in a backwards-compatible way. We can make it required
// once all of the LLM tokens have cycled (~1 hour after
// this change has been deployed).
#[serde(default)]
pub github_user_login: Option<String>,
pub github_user_login: String,
pub is_staff: bool,
#[serde(default)]
pub has_llm_closed_beta_feature_flag: bool,
pub has_llm_subscription: bool,
pub max_monthly_spend_in_cents: u32,
pub plan: rpc::proto::Plan,
}
const LLM_TOKEN_LIFETIME: Duration = Duration::from_secs(60 * 60);
impl LlmTokenClaims {
#[allow(clippy::too_many_arguments)]
pub fn create(
user_id: UserId,
github_user_login: String,
is_staff: bool,
billing_preferences: Option<billing_preference::Model>,
has_llm_closed_beta_feature_flag: bool,
has_llm_subscription: bool,
plan: rpc::proto::Plan,
config: &Config,
) -> Result<String> {
@@ -47,9 +50,14 @@ impl LlmTokenClaims {
exp: (now + LLM_TOKEN_LIFETIME).timestamp() as u64,
jti: uuid::Uuid::new_v4().to_string(),
user_id: user_id.to_proto(),
github_user_login: Some(github_user_login),
github_user_login,
is_staff,
has_llm_closed_beta_feature_flag,
has_llm_subscription,
max_monthly_spend_in_cents: billing_preferences
.map_or(DEFAULT_MAX_MONTHLY_SPEND.0, |preferences| {
preferences.max_monthly_llm_usage_spending_in_cents as u32
}),
plan,
};

View File

@@ -6,6 +6,7 @@ use axum::{
routing::get,
Extension, Router,
};
use collab::api::billing::sync_llm_usage_with_stripe_periodically;
use collab::api::CloudflareIpCountryHeader;
use collab::llm::{db::LlmDatabase, log_usage_periodically};
use collab::migrations::run_database_migrations;
@@ -29,7 +30,7 @@ use tower_http::trace::TraceLayer;
use tracing_subscriber::{
filter::EnvFilter, fmt::format::JsonFields, util::SubscriberInitExt, Layer,
};
use util::ResultExt as _;
use util::{maybe, ResultExt as _};
const VERSION: &str = env!("CARGO_PKG_VERSION");
const REVISION: Option<&'static str> = option_env!("GITHUB_SHA");
@@ -136,6 +137,29 @@ async fn main() -> Result<()> {
fetch_extensions_from_blob_store_periodically(state.clone());
spawn_user_backfiller(state.clone());
let llm_db = maybe!(async {
let database_url = state
.config
.llm_database_url
.as_ref()
.ok_or_else(|| anyhow!("missing LLM_DATABASE_URL"))?;
let max_connections = state
.config
.llm_database_max_connections
.ok_or_else(|| anyhow!("missing LLM_DATABASE_MAX_CONNECTIONS"))?;
let mut db_options = db::ConnectOptions::new(database_url);
db_options.max_connections(max_connections);
LlmDatabase::new(db_options, state.executor.clone()).await
})
.await
.trace_err();
if let Some(mut llm_db) = llm_db {
llm_db.initialize().await?;
sync_llm_usage_with_stripe_periodically(state.clone(), llm_db);
}
app = app
.merge(collab::api::events::router())
.merge(collab::api::extensions::router())

View File

@@ -191,16 +191,26 @@ impl Session {
}
}
pub async fn current_plan(&self, db: MutexGuard<'_, DbHandle>) -> anyhow::Result<proto::Plan> {
pub async fn has_llm_subscription(
&self,
db: &MutexGuard<'_, DbHandle>,
) -> anyhow::Result<bool> {
if self.is_staff() {
return Ok(proto::Plan::ZedPro);
return Ok(true);
}
let Some(user_id) = self.user_id() else {
return Ok(proto::Plan::Free);
return Ok(false);
};
if db.has_active_billing_subscription(user_id).await? {
Ok(db.has_active_billing_subscription(user_id).await?)
}
pub async fn current_plan(
&self,
_db: &MutexGuard<'_, DbHandle>,
) -> anyhow::Result<proto::Plan> {
if self.is_staff() {
Ok(proto::Plan::ZedPro)
} else {
Ok(proto::Plan::Free)
@@ -459,9 +469,6 @@ impl Server {
.add_request_handler(user_handler(
forward_project_request_for_owner::<proto::TaskContextForLocation>,
))
.add_request_handler(user_handler(
forward_project_request_for_owner::<proto::TaskTemplates>,
))
.add_request_handler(user_handler(
forward_read_only_project_request::<proto::GetHover>,
))
@@ -1739,6 +1746,7 @@ fn notify_rejoined_projects(
worktree_id: worktree.id,
path: settings_file.path,
content: Some(settings_file.content),
kind: Some(settings_file.kind.to_proto().into()),
},
)?;
}
@@ -2220,6 +2228,7 @@ fn join_project_internal(
worktree_id: worktree.id,
path: settings_file.path,
content: Some(settings_file.content),
kind: Some(proto::update_user_settings::Kind::Settings.into()),
},
)?;
}
@@ -3469,7 +3478,7 @@ fn should_auto_subscribe_to_channels(version: ZedVersion) -> bool {
}
async fn update_user_plan(_user_id: UserId, session: &Session) -> Result<()> {
let plan = session.current_plan(session.db().await).await?;
let plan = session.current_plan(&session.db().await).await?;
session
.peer
@@ -4469,7 +4478,7 @@ async fn count_language_model_tokens(
};
authorize_access_to_legacy_llm_endpoints(&session).await?;
let rate_limit: Box<dyn RateLimit> = match session.current_plan(session.db().await).await? {
let rate_limit: Box<dyn RateLimit> = match session.current_plan(&session.db().await).await? {
proto::Plan::ZedPro => Box::new(ZedProCountLanguageModelTokensRateLimit),
proto::Plan::Free => Box::new(FreeCountLanguageModelTokensRateLimit),
};
@@ -4590,7 +4599,7 @@ async fn compute_embeddings(
let api_key = api_key.context("no OpenAI API key configured on the server")?;
authorize_access_to_legacy_llm_endpoints(&session).await?;
let rate_limit: Box<dyn RateLimit> = match session.current_plan(session.db().await).await? {
let rate_limit: Box<dyn RateLimit> = match session.current_plan(&session.db().await).await? {
proto::Plan::ZedPro => Box::new(ZedProComputeEmbeddingsRateLimit),
proto::Plan::Free => Box::new(FreeComputeEmbeddingsRateLimit),
};
@@ -4908,12 +4917,17 @@ async fn get_llm_api_token(
if Utc::now().naive_utc() - account_created_at < MIN_ACCOUNT_AGE_FOR_LLM_USE {
Err(anyhow!("account too young"))?
}
let billing_preferences = db.get_billing_preferences(user.id).await?;
let token = LlmTokenClaims::create(
user.id,
user.github_login.clone(),
session.is_staff(),
billing_preferences,
has_llm_closed_beta_feature_flag,
session.current_plan(db).await?,
session.has_llm_subscription(&db).await?,
session.current_plan(&db).await?,
&session.app_state.config,
)?;
response.send(proto::GetLlmTokenResponse { token })?;

View File

@@ -50,7 +50,7 @@ async fn test_channel_guests(
project_b.read_with(cx_b, |project, _| project.remote_id()),
Some(project_id),
);
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
assert!(project_b.read_with(cx_b, |project, cx| project.is_read_only(cx)));
assert!(project_b
.update(cx_b, |project, cx| {
let worktree_id = project.worktrees(cx).next().unwrap().read(cx).id();
@@ -103,7 +103,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
workspace.active_item_as::<Editor>(cx).unwrap(),
)
});
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
assert!(project_b.read_with(cx_b, |project, cx| project.is_read_only(cx)));
assert!(editor_b.update(cx_b, |e, cx| e.read_only(cx)));
assert!(room_b.read_with(cx_b, |room, _| !room.can_use_microphone()));
assert!(room_b
@@ -127,7 +127,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
cx_a.run_until_parked();
// project and buffers are now editable
assert!(project_b.read_with(cx_b, |project, _| !project.is_read_only()));
assert!(project_b.read_with(cx_b, |project, cx| !project.is_read_only(cx)));
assert!(editor_b.update(cx_b, |editor, cx| !editor.read_only(cx)));
// B sees themselves as muted, and can unmute.
@@ -153,7 +153,7 @@ async fn test_channel_guest_promotion(cx_a: &mut TestAppContext, cx_b: &mut Test
cx_a.run_until_parked();
// project and buffers are no longer editable
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
assert!(project_b.read_with(cx_b, |project, cx| project.is_read_only(cx)));
assert!(editor_b.update(cx_b, |editor, cx| editor.read_only(cx)));
assert!(room_b
.update(cx_b, |room, cx| room.share_microphone(cx))

View File

@@ -262,7 +262,7 @@ async fn test_dev_server_leave_room(
cx1.executor().run_until_parked();
let (workspace, cx2) = client2.active_workspace(cx2);
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected()));
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
}
#[gpui::test]
@@ -308,7 +308,7 @@ async fn test_dev_server_delete(
cx1.executor().run_until_parked();
let (workspace, cx2) = client2.active_workspace(cx2);
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected()));
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
cx1.update(|cx| {
dev_server_projects::Store::global(cx).update(cx, |store, _| {
@@ -418,12 +418,12 @@ async fn test_dev_server_refresh_access_token(
// Assert that the other client was disconnected
let (workspace, cx2) = client2.active_workspace(cx2);
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected()));
cx2.update(|cx| assert!(workspace.read(cx).project().read(cx).is_disconnected(cx)));
// Assert that the owner of the dev server does not see the dev server as online anymore
let (workspace, cx1) = client1.active_workspace(cx1);
cx1.update(|cx| {
assert!(workspace.read(cx).project().read(cx).is_disconnected());
assert!(workspace.read(cx).project().read(cx).is_disconnected(cx));
dev_server_projects::Store::global(cx).update(cx, |store, _| {
assert_eq!(
store.dev_servers().first().unwrap().status,

View File

@@ -114,7 +114,7 @@ async fn test_host_disconnect(
project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
project_b.read_with(cx_b, |project, _| project.is_read_only());
project_b.read_with(cx_b, |project, cx| project.is_read_only(cx));
assert!(worktree_a.read_with(cx_a, |tree, _| !tree.has_update_observer()));

View File

@@ -33,7 +33,7 @@ use project::{
};
use rand::prelude::*;
use serde_json::json;
use settings::SettingsStore;
use settings::{LocalSettingsKind, SettingsStore};
use std::{
cell::{Cell, RefCell},
env, future, mem,
@@ -1389,7 +1389,7 @@ async fn test_unshare_project(
.unwrap();
executor.run_until_parked();
assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
assert!(project_b.read_with(cx_b, |project, cx| project.is_disconnected(cx)));
// Client C opens the project.
let project_c = client_c.join_remote_project(project_id, cx_c).await;
@@ -1402,7 +1402,7 @@ async fn test_unshare_project(
assert!(worktree_a.read_with(cx_a, |tree, _| !tree.has_update_observer()));
assert!(project_c.read_with(cx_c, |project, _| project.is_disconnected()));
assert!(project_c.read_with(cx_c, |project, cx| project.is_disconnected(cx)));
// Client C can open the project again after client A re-shares.
let project_id = active_call_a
@@ -1427,8 +1427,8 @@ async fn test_unshare_project(
project_a.read_with(cx_a, |project, _| assert!(!project.is_shared()));
project_c2.read_with(cx_c, |project, _| {
assert!(project.is_disconnected());
project_c2.read_with(cx_c, |project, cx| {
assert!(project.is_disconnected(cx));
assert!(project.collaborators().is_empty());
});
}
@@ -1560,8 +1560,8 @@ async fn test_project_reconnect(
assert_eq!(project.collaborators().len(), 1);
});
project_b1.read_with(cx_b, |project, _| {
assert!(!project.is_disconnected());
project_b1.read_with(cx_b, |project, cx| {
assert!(!project.is_disconnected(cx));
assert_eq!(project.collaborators().len(), 1);
});
@@ -1661,7 +1661,7 @@ async fn test_project_reconnect(
});
project_b1.read_with(cx_b, |project, cx| {
assert!(!project.is_disconnected());
assert!(!project.is_disconnected(cx));
assert_eq!(
project
.worktree_for_id(worktree1_id, cx)
@@ -1695,9 +1695,9 @@ async fn test_project_reconnect(
);
});
project_b2.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
project_b2.read_with(cx_b, |project, cx| assert!(project.is_disconnected(cx)));
project_b3.read_with(cx_b, |project, _| assert!(!project.is_disconnected()));
project_b3.read_with(cx_b, |project, cx| assert!(!project.is_disconnected(cx)));
buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WaZ"));
@@ -1754,7 +1754,7 @@ async fn test_project_reconnect(
executor.run_until_parked();
project_b1.read_with(cx_b, |project, cx| {
assert!(!project.is_disconnected());
assert!(!project.is_disconnected(cx));
assert_eq!(
project
.worktree_for_id(worktree1_id, cx)
@@ -1788,7 +1788,7 @@ async fn test_project_reconnect(
);
});
project_b3.read_with(cx_b, |project, _| assert!(project.is_disconnected()));
project_b3.read_with(cx_b, |project, cx| assert!(project.is_disconnected(cx)));
buffer_a1.read_with(cx_a, |buffer, _| assert_eq!(buffer.text(), "WXaYZ"));
@@ -3327,8 +3327,16 @@ async fn test_local_settings(
.local_settings(worktree_b.read(cx).id())
.collect::<Vec<_>>(),
&[
(Path::new("").into(), r#"{"tab_size":2}"#.to_string()),
(Path::new("a").into(), r#"{"tab_size":8}"#.to_string()),
(
Path::new("").into(),
LocalSettingsKind::Settings,
r#"{"tab_size":2}"#.to_string()
),
(
Path::new("a").into(),
LocalSettingsKind::Settings,
r#"{"tab_size":8}"#.to_string()
),
]
)
});
@@ -3346,8 +3354,16 @@ async fn test_local_settings(
.local_settings(worktree_b.read(cx).id())
.collect::<Vec<_>>(),
&[
(Path::new("").into(), r#"{}"#.to_string()),
(Path::new("a").into(), r#"{"tab_size":8}"#.to_string()),
(
Path::new("").into(),
LocalSettingsKind::Settings,
r#"{}"#.to_string()
),
(
Path::new("a").into(),
LocalSettingsKind::Settings,
r#"{"tab_size":8}"#.to_string()
),
]
)
});
@@ -3375,8 +3391,16 @@ async fn test_local_settings(
.local_settings(worktree_b.read(cx).id())
.collect::<Vec<_>>(),
&[
(Path::new("a").into(), r#"{"tab_size":8}"#.to_string()),
(Path::new("b").into(), r#"{"tab_size":4}"#.to_string()),
(
Path::new("a").into(),
LocalSettingsKind::Settings,
r#"{"tab_size":8}"#.to_string()
),
(
Path::new("b").into(),
LocalSettingsKind::Settings,
r#"{"tab_size":4}"#.to_string()
),
]
)
});
@@ -3406,7 +3430,11 @@ async fn test_local_settings(
store
.local_settings(worktree_b.read(cx).id())
.collect::<Vec<_>>(),
&[(Path::new("a").into(), r#"{"hard_tabs":true}"#.to_string()),]
&[(
Path::new("a").into(),
LocalSettingsKind::Settings,
r#"{"hard_tabs":true}"#.to_string()
),]
)
});
}
@@ -3788,8 +3816,8 @@ async fn test_leaving_project(
assert_eq!(project.collaborators().len(), 1);
});
project_b2.read_with(cx_b, |project, _| {
assert!(project.is_disconnected());
project_b2.read_with(cx_b, |project, cx| {
assert!(project.is_disconnected(cx));
});
project_c.read_with(cx_c, |project, _| {
@@ -3821,12 +3849,12 @@ async fn test_leaving_project(
assert_eq!(project.collaborators().len(), 0);
});
project_b2.read_with(cx_b, |project, _| {
assert!(project.is_disconnected());
project_b2.read_with(cx_b, |project, cx| {
assert!(project.is_disconnected(cx));
});
project_c.read_with(cx_c, |project, _| {
assert!(project.is_disconnected());
project_c.read_with(cx_c, |project, cx| {
assert!(project.is_disconnected(cx));
});
}
@@ -4409,7 +4437,7 @@ async fn test_formatting_buffer(
file.defaults.formatter = Some(SelectedFormatter::List(FormatterList(
vec![Formatter::External {
command: "awk".into(),
arguments: vec!["{sub(/two/,\"{buffer_path}\")}1".to_string()].into(),
arguments: Some(vec!["{sub(/two/,\"{buffer_path}\")}1".to_string()].into()),
}]
.into(),
)));

View File

@@ -1168,7 +1168,7 @@ impl RandomizedTest for ProjectCollaborationTest {
Some((project, cx))
});
if !guest_project.is_disconnected() {
if !guest_project.is_disconnected(cx) {
if let Some((host_project, host_cx)) = host_project {
let host_worktree_snapshots =
host_project.read_with(host_cx, |host_project, cx| {
@@ -1254,8 +1254,8 @@ impl RandomizedTest for ProjectCollaborationTest {
let buffers = client.buffers().clone();
for (guest_project, guest_buffers) in &buffers {
let project_id = if guest_project.read_with(client_cx, |project, _| {
project.is_local() || project.is_disconnected()
let project_id = if guest_project.read_with(client_cx, |project, cx| {
project.is_local() || project.is_disconnected(cx)
}) {
continue;
} else {

View File

@@ -532,9 +532,9 @@ impl<T: RandomizedTest> TestPlan<T> {
server.allow_connections();
for project in client.dev_server_projects().iter() {
project.read_with(&client_cx, |project, _| {
project.read_with(&client_cx, |project, cx| {
assert!(
project.is_disconnected(),
project.is_disconnected(cx),
"project {:?} should be read only",
project.remote_id()
)

View File

@@ -4,7 +4,7 @@ use fs::{FakeFs, Fs as _};
use gpui::{Context as _, TestAppContext};
use language::language_settings::all_language_settings;
use project::ProjectPath;
use remote::SshSession;
use remote::SshRemoteClient;
use remote_server::HeadlessProject;
use serde_json::json;
use std::{path::Path, sync::Arc};
@@ -24,7 +24,7 @@ async fn test_sharing_an_ssh_remote_project(
.await;
// Set up project on remote FS
let (client_ssh, server_ssh) = SshSession::fake(cx_a, server_cx);
let (client_ssh, server_ssh) = SshRemoteClient::fake(cx_a, server_cx);
let remote_fs = FakeFs::new(server_cx.executor());
remote_fs
.insert_tree(

View File

@@ -25,7 +25,7 @@ use node_runtime::NodeRuntime;
use notifications::NotificationStore;
use parking_lot::Mutex;
use project::{Project, WorktreeId};
use remote::SshSession;
use remote::SshRemoteClient;
use rpc::{
proto::{self, ChannelRole},
RECEIVE_TIMEOUT,
@@ -677,7 +677,8 @@ impl TestServer {
migrations_path: None,
seed_path: None,
stripe_api_key: None,
stripe_price_id: None,
stripe_llm_access_price_id: None,
stripe_llm_usage_price_id: None,
supermaven_admin_api_key: None,
user_backfiller_github_access_token: None,
},
@@ -835,7 +836,7 @@ impl TestClient {
pub async fn build_ssh_project(
&self,
root_path: impl AsRef<Path>,
ssh: Arc<SshSession>,
ssh: Model<SshRemoteClient>,
cx: &mut TestAppContext,
) -> (Model<Project>, WorktreeId) {
let project = cx.update(|cx| {

View File

@@ -111,7 +111,7 @@ impl MessageEditor {
editor.set_show_gutter(false, cx);
editor.set_show_wrap_guides(false, cx);
editor.set_show_indent_guides(false, cx);
editor.set_completion_provider(Box::new(MessageEditorCompletionProvider(this)));
editor.set_completion_provider(Some(Box::new(MessageEditorCompletionProvider(this))));
editor.set_auto_replace_emoji_shortcode(
MessageEditorSettings::get_global(cx)
.auto_replace_emoji_shortcode

Some files were not shown because too many files have changed in this diff Show More