Compare commits

..

607 Commits

Author SHA1 Message Date
Julia Ryan
d631b821e5 Add sentry 2025-07-24 13:13:46 -07:00
Nicolas Rodriguez
be0d9eecb7 Add collapse functionality to outline entries (#33490)
partly Closes #23075 

Release Notes:

- Now provides collapse and enables functionality to outline entries
- Add a new expand_outlines_with_depth setting to customize how deep the
tree is expanded by when a file is opened

part 2 is in #34164 

**Visual examples**

![image](https://github.com/user-attachments/assets/5dcdb83b-6e3e-4bfd-8ef4-76ae2ce4d3e6)

![image](https://github.com/user-attachments/assets/7b786a5a-1a8c-4f34-aaa5-4a8d0afa9668)

![image](https://github.com/user-attachments/assets/1817be06-ac71-4480-8f17-0bd862e913c8)
2025-07-23 18:52:44 +00:00
Umesh Yadav
9863c8a44e agent_ui: Show keybindings for NewThread and NewTextThread in new thread button (#34967)
I believe in this PR: #34829 we moved to context menu entry from action
but the side effect of that was we also removed the Keybindings from
showing it in the new thread button dropdown. This PR fixes that. cc
@danilo-leal

| Before | After |
|--------|--------|
| <img width="900" height="1962" alt="CleanShot 2025-07-23 at 23 36
28@2x"
src="https://github.com/user-attachments/assets/760cbe75-09b9-404b-9d33-1db73785234f"
/> | <img width="850" height="1964" alt="CleanShot 2025-07-23 at 23 37
17@2x"
src="https://github.com/user-attachments/assets/24a7e871-aebc-475c-845f-b76f02527b8f"
/> |

Release Notes:

- N/A
2025-07-23 18:28:05 +00:00
Joseph T. Lyons
a48247a313 Bump Zed to v0.198 (#34964)
Release Notes:

-N/A
2025-07-23 18:14:39 +00:00
Julia Ryan
5f0edd38f8 Add TestPanic feature flag (#34963)
Now the `dev: panic` action can be run on all release channels if the
user has the feature flag enabled.

Release Notes:

- N/A
2025-07-23 18:01:16 +00:00
Anthony Eid
56b64b1d3f keymap ui: Improve resize columns on double click (#34961)
This PR splits the resize logic into separate left/right propagation
methods and improve code organization around column width adjustments.
It also allows resize to work for both the left and right sides as well,
instead of only checking the right side for room

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-23 13:45:49 -04:00
Danilo Leal
fdcd86617a ai onboarding: Add telemetry event capturing (#34960)
Release Notes:

- N/A

Co-authored-by: Katie Geer <katie@zed.dev>
Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>
2025-07-23 17:33:53 +00:00
Michael Sloan
3b428e2ecc Remove !menu from j k binding in initial keymap examples (#34959)
See
https://github.com/zed-industries/zed/pull/34912#issuecomment-3108802582

Release Notes:

- N/A
2025-07-23 17:33:40 +00:00
Anthony Eid
986b446749 keymap ui: Resizable column follow up (#34955)
I cherry picked a small fix that didn't get into the original column
resizable branch PR because I turned on auto merge.

Release Notes:

- N/A
2025-07-23 12:18:55 -04:00
Finn Evers
8713c556d6 keymap_ui: Dim keybinds that are overridden by other keybinds (#34952)
This change dims rows in the keymap editor for which the corresponding
keybind is overridden by other keybinds coming from higher priority
sources.

Release Notes:

- N/A
2025-07-23 16:03:04 +00:00
Mikayla Maki
326fe05b33 Resizable columns (#34794)
This PR adds resizable columns to the keymap editor and the ability to
double-click on a resizable column to set a column back to its default
size.

The table uses a column's width to calculate what position it should be
laid out at. So `column[i]` x position is calculated by the summation of
`column[..i]`. When resizing `column[i]`, `column[i+1]`’s size is
adjusted to keep all columns’ relative positions the same. If
`column[i+1]` is at its minimum size, we keep seeking to the right to
find a column with space left to take.

An improvement to resizing behavior and double-clicking could be made by
checking both column ranges `0..i-1` and `i+1..COLS`, since only one
range of columns is checked for resize capacity.

Release Notes:

- N/A

---------

Co-authored-by: Anthony <anthony@zed.dev>
Co-authored-by: Remco Smits <djsmits12@gmail.com>
2025-07-23 15:44:45 +00:00
claytonrcarter
1f4c9b9427 language: Update block_comment and documentation comment (#34861)
As suggested in https://github.com/zed-industries/zed/pull/34418, this
proposes various changes to language configs to make block comments and
doc-block-style comments more similar. In doing so, it introduces some
breaking changes into the extension schema.

This change is needed to support the changes I'm working on in #34418,
to be able to support `rewrap` in block comments like `/* really long
comment ... */`. As is, we can do this in C-style doc-block comments (eg
`/** ... */`) because of the config in `documentation`, but we can't do
this in regular block comments because we lack the info about what the
line prefix and indentation should be.

And while I was here, I did various other clean-ups, many of which feel
nice but are optional.

I would love special attention on the changes to the schema, version and
related changes; I'm totally unfamiliar with that part of Zed.

**Summary of changes**
- break: changes type of `block_comment` to same type as
`documentation_comment` (**this is the important change**)
- break: rename `documentation` to `documentation_comment` (optional,
but improves consistency w/ `line_comments` and `block_comment`)
- break/refactor?: removes some whitespace in the declaration of
`block_comment` delimiters (optional, may break things, need input; some
langs had no spaces, others did)
- refactor: change `tab_size` from `NonZeroU32` to just a `u32` (some
block comments don't seem to need/want indent past the initial
delimiter, so we need this be 0 sometimes)
- refactor: moves the `documentation_comment` declarations to appear
next to `block_comment`, rearranges the order of the fields in the TOML
for `documentation_comment`, rename backing `struct` (all optional)

**Future scope**
I believe that this will also allow us to extend regular block comments
on newline – as we do doc-block comments – but I haven't looked into
this yet. (eg, in JS try pressing enter in both of these: `/* */` and
`/** */`; the latter should extend w/ a `*` prefixed line, while the
former does not.)

Release Notes:

- BREAKING CHANGE: update extension schema version from 1 to 2, change
format of `block_comment` and rename `documentation_comment`

/cc @smitbarmase
2025-07-23 20:38:52 +05:30
Marshall Bowers
14171e0721 collab: Add POST /users/:id/update_plan endpoint (#34953)
This PR adds a new `POST /users/:id/update_plan` endpoint to Collab to
allow Cloud to push down plan updates to users.

Release Notes:

- N/A
2025-07-23 14:30:08 +00:00
Peter Tripp
326ab5fa3f Improve collab channel organization keybinds (#34821)
Change channel reorganization (move up/down) from `cmd-up/down` (mac) /
`ctrl-up/down` (linux) to `alt-up/down` (both) to match moving lines in
the editor.

Also fix an issue where if you selected channels using down/up in the
filter field, the movement shortcuts would not work (`editing` vs
`not_editing`).

Release Notes:

- N/A
2025-07-23 10:04:53 -04:00
Finn Evers
2bc6e18ac9 Ensure disable_ai is properly respected (#34941)
Quick follow up to #34896 which ensures that the Agent Panel cannot be
caught by actions like `workspace: toggle left dock` when `disable_ai`
is set to true.

Also removes a method that was introduced but unused in the workspace
because `first_enabled_panel_idx` already covers all cases this method
could be useful for.

Release Notes:

- N/A
2025-07-23 12:20:09 +02:00
Piotr Osiewicz
c2c2264a60 gpui: Add tree example (#34942)
This commit adds an example with deep children hierarchy.
The depth of a tree can be tweaked with GPUI_TREE_DEPTH env variable.
With depth=100
<img width="301" height="330" alt="image"
src="https://github.com/user-attachments/assets/844cd285-c5f3-4410-a74e-981bf093ba2e"
/>
With this example, I can trigger a stack overflow at depth=633 (and
higher).


Release Notes:

- N/A
2025-07-23 12:17:23 +02:00
Piotr Osiewicz
6cd3726a5a Revert "chore: Bump taffy to 0.8.3" (#34938)
Reverts zed-industries/zed#34876

From our Slack:
<img width="1694" height="1610" alt="image"
src="https://github.com/user-attachments/assets/c7b8f02a-8609-4ed3-9cd5-7d05d152e40e"
/>


https://github.com/user-attachments/assets/828964be-9b6e-4496-9361-9e3a2e9aa208

Release Notes:
- N/A
2025-07-23 10:28:06 +02:00
tidely
7db110f48d sum_tree: Utilize size_hint in TreeSet::extend (#34936)
Collect the iterator instead of manually looping over it to utilize
possible size hints. Zed usually passes in owned `Vec`'s, meaning we get
to reuse memory as well.

Release Notes:

- N/A
2025-07-23 09:57:57 +02:00
maan2003
6122f46095 project: Fix search filter patterns on remote projects (#34748)
we were join(",") and split(",") to serialize the patterns.

This doesn't work when pattern includes a ","
example: *.{ts,tsx} (very common pattern used by agent)


help needed:

how will this work on version mismatch?

Release Notes:

- Fixed search filter patterns on remote projects.
2025-07-23 00:18:45 -06:00
Joseph T. Lyons
500ceaabcd Add an editor: diff clipboard with selection action (#33283)
https://github.com/user-attachments/assets/d472fbdd-7736-4bd7-8a90-8cca356b2815

This PR adds `editor: diff clipboard with selection` - good for spotting
the differences in eerily-similar code, which is when refactoring code,
as you need to see what needs to be passed in in order to maintain
previous behavior of both snippets.

1. Copy some text from anywhere
2. Highlight some text in Zed
3. Run `editor: diff clipboard with selection`

Like JetBrains' IDEs and VS Code with the `PartialDiff` package, if the
selection is empty, we take the entire buffer as the selection.

Caveats:

- We do not know the language of the text in the clipboard. I went ahead
and just assumed that in most cases, it will be the same language as the
selected text, which does mean we will highlight the old text
incorrectly if they are copying from a different language, but I think
in most cases, it will be the same, and the alternative of always having
no syntax highlighting is worse. PyCharm seems to do the same thing.

Release Notes:

- Added an `editor: diff clipboard with selection` action

---------

Co-authored-by: Junkui Zhang <364772080@qq.com>
Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-23 02:39:32 +00:00
Jason Lee
3e27fa1d92 gpui: Allow Animation to be cloned (#34933)
Release Notes:

- N/A

---

Let `Animation` able to clone, then we can define one to share for
multiple places.

For example:

<img width="914" height="637" alt="image"
src="https://github.com/user-attachments/assets/8eafb318-afba-4399-a975-d83cb7afe74c"
/>
2025-07-23 02:10:40 +00:00
Smit Barmase
11ac83f3d4 workspace: Fix closing remote workspace restores last local workspace on startup (#34931)
Closes #7759

While opening a new SSH project if we are reusing an existing window,
i.e. drop the existing workspace and create a new one, then before
dropping it, we should remove `session_id` from that workspace's
serialized entry. That way:

1. Upon closing (cmd-w) this remote workspace (which also clears
`session_id` for this), and then quitting. No workspace with that
`session_id` is found, and it starts fresh.
2. Upon directly quitting (cmd-q) this remote workspace, only this
workspace exists in db (among two of them) with that `session_id`, and
it restores correctly.
 
Release Notes:

- Fixed an issue while closing remote workspace restores last local
workspace on startup.
2025-07-23 06:48:31 +05:30
Smit Barmase
e90cf0b941 workspace: Fix last removed folder from workspace used to reopen on Zed startup (#34925)
Closes #34924

Now, when `local_paths` are empty, we detach `session_id` from that
workspace serialization item. This way, when we restore it using the
default "last_session", we don't restore this workspace back. This is
same as when we use `cmd-w` to close window, which also sets
`session_id` to `None` before serialization.

Release Notes:

- Fixed an issue where last removed folder from workspace used to reopen
on Zed startup.
2025-07-23 06:46:24 +05:30
Marshall Bowers
056003860a collab: Remove POST /billing/subscriptions endpoint (#34928)
This PR removes the `POST /billing/subscriptions` endpoint, as it has
been moved to `cloud.zed.dev`.

Release Notes:

- N/A
2025-07-22 18:57:07 -04:00
Agus Zubiaga
5d985fa1d8 Improve MCP server responses (#34927)
Release Notes:

- N/A
2025-07-22 22:14:34 +00:00
Marshall Bowers
7f70325a93 language_models: Rename handler to handle in Bedrock provider (#34923)
This PR renames the `handler` field to `handle` on the
`BedrockLanguageModelProvider` and `BedrockModel` structs.

Release Notes:

- N/A
2025-07-22 20:04:08 +00:00
Umesh Yadav
f3c332d839 Fix new crate license symlink (#34922)
The license file is not properly linked to actual license. This was
casued due to new-crate script linking the license to wrong file. Fixed
both of them.

Reference logs:

```
2025-07-22T17:16:19+05:30 ERROR [worktree] error reading target of symlink "/Users/umesh/code/zed/crates/onboarding/LICENSE-GPL": canonicalizing
```

Release Notes:

- N/A
2025-07-22 15:46:25 -04:00
Remco Smits
446d333515 debugger: Fix debug console persist to history when reusing a previous item (#34893)
Closes #34887

Release Notes:

- Debugger: Fix debug console persist to history when reusing a previous
item
2025-07-22 15:40:11 -04:00
Remco Smits
c0f75e1a17 debugger: Fix built-in JavaScript debug tasks were not working due missing type field value (#34894)
Release Notes:

- Debugger: Fix built-in JavaScript debug tasks were not working due
missing `type` field value
2025-07-22 15:39:52 -04:00
Piotr Osiewicz
708c2645d1 collab: Tweak screen selector appearance (#34919)
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>


Release Notes:

- N/A

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-22 18:53:57 +00:00
Danilo Leal
4272c1508e ai onboarding: Copyedit the whole flow (#34916)
Release Notes:

- N/A

Co-authored-by: Katie Geer <katie@zed.dev>
2025-07-22 15:41:12 -03:00
Peter Tripp
99466f4aeb Make zooming from menus not persist (#34910)
Closes: https://github.com/zed-industries/zed/issues/34479
Follow-up to: https://github.com/zed-industries/zed/issues/23505

View->Zoom In / Zoom Out / Reset Zoom were not reverted to match when
the default keybindings were reverted.

Release Notes:

- N/A
2025-07-22 13:57:36 -04:00
Marshall Bowers
9e280d0905 collab: Remove unneeded caching of Stripe price IDs by meter ID (#34915)
This PR removes the caching of Stripe price IDs by meter ID on the
`StripeBilling` object, as we weren't actually reading them anywhere.

Release Notes:

- N/A
2025-07-22 17:42:07 +00:00
Michael Sloan
d81a8178e9 Bind "j k" to NormalBefore in initial keymap examples (#34912)
It looks like typically vim configurations bind "j k" to be the same as
escape, which has the "NormalBefore" behavior positioning the block
cursor on the character before the insertion cursor. The [vim mode
docs](https://zed.dev/docs/vim#useful-contexts-for-vim-mode-key-bindings)
also use NormalBefore here.

Thanks to @omniwrench for mentioning this in
https://github.com/zed-industries/zed/discussions/6661#discussioncomment-13848043
. This was a mistake in #31163.

Release Notes:

- N/A
2025-07-22 11:35:58 -06:00
Ben Kunkle
14cea06f0f keymap_ui: Fix panic in clear keystrokes (#34909)
Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-22 13:18:59 -04:00
Piotr Osiewicz
caa520c499 workspace: Clean up empty panes left over from file opening failures (#34908)
Closes #34583

Release Notes:

- Fixed empty pane being left after a binary file is dropped into a new
pane.s
2025-07-22 16:52:17 +00:00
Piotr Osiewicz
64d0fec699 sum_tree: Store context on cursor (#34904)
This gets rid of the need to pass context to all cursor functions. In
practice context is always immutable when interacting with cursors.

A nicety of this is in the follow-up PR we will be able to implement
Iterator for all Cursors/filter cursors (hell, we may be able to get rid
of filter cursor altogether, as it is just a custom `filter` impl on
iterator trait).
Release Notes:

- N/A
2025-07-22 18:20:48 +02:00
Piotr Osiewicz
fa3e1ccc37 chore: Bump taffy to 0.8.3 (#34876)
That's the latest release. Note that we have an opportunity to simplify
our size types per
https://github.com/DioxusLabs/taffy/blob/main/CHANGELOG.md#highlights-1
(though that's left out of this PR)

<img width="1156" height="603" alt="image"
src="https://github.com/user-attachments/assets/cb9501b9-541a-4080-998a-b6347a0c6887"
/>


Release Notes:

- N/A
2025-07-22 18:19:51 +02:00
tiagoq
56b99f49fd bedrock: Fix remaining streaming delays (#33931)
Closes #26030

*Note: This is my first contribution to Zed*

This addresses a second streaming bottleneck in Bedrock that remained
after the initial fix in #28281 (released in preview 194).

The issue is in the mechanism used to convert Zed's internal `AsyncBody`
into the `SdkBody` expected by the Bedrock language provider. We are
using a non-streaming converter that buffers responses.

**How the fix works:**
The AWS SDK provides streaming-compatible converters to create `SdkBody`
instances, but these require the input body to implement the `Body`
trait from the `http-body` crate.

This PR enables streaming by implementing the required trait and
switching to the streaming-compatible converter.

**Changes (2 commits):**

 * 1st Commit - **Implement http-body Body trait for AsyncBody:**
   - Add `http-body = 1.0` dependency (already an indirect dependency)
   - Implement the `Body` trait for our existing `AsyncBody` type
- Uses `poll_frame` to read data chunks asynchronously, preserving
streaming behavior

 * 2nd Commit - **Use streaming-compatible AWS SDK converter:**
- Create `SdkBody` using `SdkBody::from_body_1_x()` with the new `Body`
trait implementation

**Details/FAQ:**

**Q: Why add another dependency?**
A: We tried to avoid adding a dependency, but the AWS SDK requires the
`Body` trait and `http-body` is where it's defined. The crate is already
an indirect dependency, making this a reasonable solution.

**Q: Why modify the shared `http_client` crate instead of just
`aws_bedrock_client`?**
A: We considered implementing the `Body` trait on a wrapper in
`aws_bedrock_client`, but since `AsyncBody` already uses `http` crate
types, extending support to the companion `http-body` crate seems
reasonable and may benefit other integrations.

**Q: How was this bottleneck discovered?**
A: After @5herlocked's initial streaming fix in #28281, I tested preview
194 and noticed streaming still had issues. I found a way to reproduce
the problem and chatted with @5herlocked about it. He immediately
pinpointed the exact location where the issue was occurring, his
diagnosis made this fix possible.

**Q: How does this relate to the previous fix?**
A: #28281 fixed buffering issues higher in the stack, but unfortunately
there was another bottleneck lower-down in the aws-http-client. This PR
addresses that separate buffering issue.

**Q: Does this use zero-copy or one-copy?**
A: The `Body` implementation includes one copy. Someone more
knowledgeable might be able to achieve a zero-copy approach, but we
opted for a conservative approach. The performance impact should not be
perceptible in typical usage.

**Testing:**
Confirmed that Bedrock streaming now works without buffering delays in a
local build.


Release Notes:

- Improved Bedrock streaming by eliminating response buffering delays

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-07-22 11:55:24 -04:00
Ben Kunkle
2b888e1d30 Fix redo after noop format (#34898)
Closes #31917

Previously, as of #28457 we used a hack, creating an empty transaction
in the history that we then merged formatting changes into in order to
correctly identify concurrent edits to the buffer while formatting was
happening. This caused issues with noop formatting however, as using the
normal API of the buffer history (in an albeit weird way) resulted in
the redo stack being cleared, regardless of whether the formatting
transaction included edits or not, which is the correct behavior in all
other contexts.

This PR fixes the redo issue by codifying the behavior formatting wants,
that being the ability to push an empty transaction to the history with
no other side-effects (i.e. clearing the redo stack) to detect
concurrent edits, with the tradeoff being that it must then manually
remove the transaction later if no changes occurred from the formatting.
The redo stack is still cleared when there are formatting edits, as the
individual format steps use the normal `{start,end}_transaction` methods
which clear the redo stack if the finished transaction isn't empty.

Release Notes:

- Fixed an issue where redo would not work after buffer formatting
(including formatting on save) when the formatting did not result in any
changes
2025-07-22 11:45:42 -04:00
Richard Feldman
96f9942791 Add setting to disable all AI features (#34896)
https://github.com/user-attachments/assets/674bba41-40ac-4a98-99e4-0b47f9097b6a


Release Notes:

- Added setting to disable all AI features
2025-07-22 11:32:39 -04:00
Marshall Bowers
939f9fffa3 collab: Remove unneeded caching of Stripe meters (#34900)
This PR removes the caching of Stripe meters on the `StripeBilling`
object, as we weren't actually reading them anywhere.

Release Notes:

- N/A
2025-07-22 15:27:58 +00:00
Bennet Bo Fenner
230061a6cb Support multiple OpenAI compatible providers (#34212)
TODO
- [x] OpenAI Compatible API Icon
- [x] Docs
- [x] Link to docs in OpenAI provider section about configuring OpenAI
API compatible providers

Closes #33992

Related to #30010

Release Notes:

- agent: Add support for adding multiple OpenAI API compatible providers

---------

Co-authored-by: MrSubidubi <dev@bahn.sh>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-22 12:20:07 -03:00
Ben Kunkle
1a76a6b0bf gpui: Simplify bindings_for_action API (#34857)
Closes #ISSUE

Simplifies the API to no longer have a variant that returns indices. The
downside is that a few places that used to call
`bindings_for_action_with_indices` now compare `Box<dyn Action>` instead
of indices, however the result is the removal of wrapper code and index
handling that is largely unnecessary

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Co-authored-by: Conrad <conrad@zed.dev>
2025-07-22 10:59:51 -04:00
Peter Tripp
2eeab5b0bf textmate: Correct context for 'Editor && mode == full' keybinds (#34895)
Closes https://github.com/zed-industries/zed/issues/34891

Release Notes:

- Fixed textmate keymap misbehaving in certain contexts
2025-07-22 14:52:04 +00:00
Ben Kunkle
30177b87d6 Fix detection of pending bindings when binding in parent context matches (#34856)
Broke in #34664

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Co-authored-by: Conrad <conrad@zed.dev>
2025-07-22 13:51:30 +00:00
Umesh Yadav
31aab89ab0 ai_onboarding: Fix API key onboarding callout not showing properly (#34880)
The current onboarding callout for ApiKeysWithProviders is broken.

| Before | After |
|--------|--------|
| <img width="822" height="1914" alt="CleanShot 2025-07-22 at 16 21
53@2x"
src="https://github.com/user-attachments/assets/5a611a8c-1ca2-4a13-965e-6fbd7cfe757a"
/> | <img width="814" height="1956" alt="CleanShot 2025-07-22 at 16 22
38@2x"
src="https://github.com/user-attachments/assets/3263b804-671a-4637-b5dc-ee7c87befa48"
/> |

cc @danilo-leal 

Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-22 12:54:06 +00:00
Danilo Leal
a3850b3d38 agent: Add use_modifier_to_send section in the settings view (#34866)
This PR also converts all of these switch-based settings to use the new
`SwitchField` component, introduced in
https://github.com/zed-industries/zed/pull/34713.

Release Notes:

- agent: Added the ability to change the `use_modifier_to_send` setting
from the agent panel settings UI.
2025-07-22 09:42:34 -03:00
Oleksiy Syvokon
c7158f0bd7 Improve distinguishing user from agent edits (#34716)
We no longer rely on the `author` field to tell if a change was made by
the user or the agent. The `author` can be set to `User` in many
situations that are not really user-made edits, such as saving a file,
accepting a change, auto-formatting, and more. I started tracking and
fixing some of these cases, but found that inspecting changes in
`diff_base` is a more reliable method.

Also, we no longer show empty diffs. For example, if the user adds a
line and then removes the same line, the final diff is empty, even
though the buffer is marked as user-changed. Now we won't show such
edit.

There are still some issues to address:

- When a user edits within an unaccepted agent-written block, this
change becomes a part of the agent's edit. Rejecting this block will
lose user edits. It won't be displayed in project notifications, either.

- Accepting an agent block counts as a user-made edit.

- Agent start to call `project_notifications` tool after seeing enough
auto-calls.

Release Notes:

- N/A
2025-07-22 14:23:50 +03:00
Ben Brandt
3a651c546b context_server: Change command string field to PathBuf (#34873)
Release Notes:

- N/A
2025-07-22 12:12:07 +02:00
Bret Comnes
87014cec71 theme: Add panel.overlay_background and panel.overlay_hover (#34655)
In https://github.com/zed-industries/zed/pull/33994 sticky scroll was
added to project_panel.

I love this feature! 

This introduces a new element layering not seen before. On themes that
use transparency, the overlapping elements can make it difficult to read
project panel entries. This PR introduces a new selector:
~~panel.sticky_entry.background~~ `panel.overlay_background` This
selector lets you set the background of entries when they become sticky.

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

Before:

<img width="373" height="104" alt="Screenshot 2025-07-17 at 10 19 11 AM"
src="https://github.com/user-attachments/assets/d5bab065-53ca-4b27-b5d8-3b3f8d1f7a81"
/>

After:

<img width="292" height="445" alt="Screenshot 2025-07-17 at 11 46 57 AM"
src="https://github.com/user-attachments/assets/4cd2b87b-2989-4489-972f-872d2dc13a33"
/>

<img width="348" height="390" alt="Screenshot 2025-07-17 at 11 39 57 AM"
src="https://github.com/user-attachments/assets/49c0757f-2c50-4e01-92c6-2ae7e4132a53"
/>

<img width="668" height="187" alt="Screenshot 2025-07-17 at 11 39 29 AM"
src="https://github.com/user-attachments/assets/167536c2-5872-4306-90c6-c6b68276b618"
/>

Release Notes:

- Add `panel.sticky_entry.background` theme selector for modifying
project panel entries when they become sticky when scrolling and overlap
with entries below them.

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2025-07-22 15:20:26 +05:30
Danilo Leal
2b671a46f2 ai onboarding: Don't show API keys section if user is already in Pro (#34867)
Release Notes:

- N/A
2025-07-22 05:39:22 +00:00
Danilo Leal
eaccd542fd Add fast-follows to the AI onboarding flow (#34737)
Follow-up to https://github.com/zed-industries/zed/pull/33738.

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2025-07-22 02:09:05 -03:00
Marshall Bowers
5a530ecd39 zed: Add support for zed://agent links (#34862)
This PR adds support for `zed://agent` links for opening the Agent
Panel.

Release Notes:

- N/A
2025-07-22 01:40:33 +00:00
Daste
233e66d35f Add editor::BlameHover action for triggering the blame popover via keyboard (#32096)
Make the git blame popover available via the keymap by making it an
action. The blame popover stays open after being shown via the action,
similar to the `editor::Hover` action.

I added a default vim-mode key binding for `g b`, which goes in hand
with `g h` for hover. I'm not sure what the keybind would be for regular
layouts, if any would be set by default.

I'm opening this as a draft because I coludn't figure out a way to
position the popover correctly above/under the cursor head. I saw some
uses of `content_origin` in other places for calculating absolute pixel
positions, but I'm not sure how to make use of it here without doing a
big refactor of the blame popover code 🤔. I would appreciate some
help/tips with positioning, because it seems like the last thing to
implement here.

Opening as a draft for now because I think without the correct
positioning this feature is not complete.

Closes https://github.com/zed-industries/zed/discussions/26447

Release Notes:

- Added `editor::BlameHover` action for showing the git blame popover
under the cursor. By default bound to `ctrl-k ctrl-b` and to `g h` in
vim mode.
2025-07-21 19:30:23 -06:00
Marshall Bowers
15353630e4 zed: Add OpenRequestKind (#34860)
This PR refactors the `OpenRequest` to introduce an `OpenRequestKind`
enum.

It seems most of the fields on `OpenRequest` are mutually-exclusive, so
it is better to model it as an enum rather than using a bunch of
`Option`s.

There are likely more of the existing fields that can be converted into
`OpenRequestKind` variants, but I'm being conservative for this first
pass.

Release Notes:

- N/A
2025-07-22 01:11:11 +00:00
Marshall Bowers
5289b815fe ai_onboarding: Send users directly into the trial checkout flow when starting the trial (#34859)
This PR makes it so users will be sent immediately into the trial
checkout flow (by hitting zed.dev/account/start-trial) when they click
the "Start Pro Trial" button.

Release Notes:

- N/A
2025-07-21 23:58:16 +00:00
Danilo Leal
8515487bbc agent: Add new thread start buttons to the empty state (#34829)
Release Notes:

- N/A
2025-07-21 20:39:29 -03:00
Sergei Surovtsev
19ab1eb792 Fix an issue where xkb defined hotkeys for arrows would not work (#34823)
Addresses
https://github.com/zed-industries/zed/pull/34053#issuecomment-3096447601
where custom-defined arrows would stop working in Zed.

How to reproduce:

1. Define custom keyboard layout

```bash
cd /usr/share/X11/xkb/symbols/
sudo nano mykbd
```

```
default partial alphanumeric_keys
xkb_symbols "custom" {

    name[Group1]= "Custom Layout";

    key <AD01> { [ q,  Q,  Escape,     Escape      ] };
    key <AD02> { [ w,  W,  Home,       Home        ] };
    key <AD03> { [ e,  E,  Up,         Up          ] };
    key <AD04> { [ r,  R,  End,        End         ] };
    key <AD05> { [ t,  T,  Tab,        Tab         ] };

    key <AC01> { [ a,  A,  Return,     Return      ] };
    key <AC02> { [ s,  S,  Left,       Left        ] };
    key <AC03> { [ d,  D,  Down,       Down        ] };
    key <AC04> { [ f,  F,  Right,      Right       ] };
    key <AC05> { [ g,  G,  BackSpace,  BackSpace   ] };

    // include a base layout to inherit the rest
    include "us(basic)"
};
```

2. Activate custom layout with win-key as AltGr

```bash
setxkbmap mykbd -variant custom -option lv3:win_switch
```

3. Now Win-S should produce left arrow, Win-F right arrow
4. Test whether it works in Zed

Release Notes:

 - linux: xkb-defined hotkeys for arrow keys should behave as expected.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-21 17:16:44 -06:00
Agus Zubiaga
722a05bc21 Wire up stop button in claude threads (#34839)
Release Notes:

- N/A

---------

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
2025-07-21 20:33:59 +00:00
Finn Evers
5b3e371812 gpui: Round scroll_max to two decimal places (#34832)
Follow up to #31836 

After enabling rounding in the Taffy layout engine, we frequently run
into cases where the bounds produced by Taffy and ours slightly differ
after 5 or more decimal places. This leads to cases where containers
become scrollable for less than 0.0000x Pixels. In case this happens for
e.g. hover popovers, we render a scrollbar due to the container being
technically scrollable, even though the scroll amount here will in
practice never be visible.

This change fixes this by rounding the `scroll_max` by which we clamp
the current scroll position to two decimal places. We don't benefit from
the additional floating point precision here at all and it stops such
containers from becoming scrollable altogether. Furthermore, we now
store the `scroll_max` instead of the `padded_content_size` as the
former gives a much better idea on whether the corresponding container
is scrollable or not.

| `main` | After these changes |
| -- | -- |
| <img width="610" height="316" alt="main"
src="https://github.com/user-attachments/assets/ffcc0322-6d6e-4f79-a916-bd3c57fe4211"
/> | <img width="610" height="316" alt="scroll_max_rounded"
src="https://github.com/user-attachments/assets/5fe530f5-2e21-4aaa-81f4-e5c53ab73e4f"
/> |

Release Notes:

- Fixed an issue where scrollbars would appear in containers where no
scrolling was possible.
2025-07-21 22:24:33 +02:00
Peter Tripp
8eca7f32e2 Fix for vim bindings in Pickers on Linux (#34840)
Closes: https://github.com/zed-industries/zed/issues/34780

Also relocated undo/redo selection in the keymap (no-op) as they are
from Sublime, not VSCode.

Release Notes:

- vim: Fixed an issue so `ctrl-w` / `ctrl-h` and `ctrl-u` work in
pickers on Linux when Vim mode is enabled.
2025-07-21 20:09:02 +00:00
Ben Kunkle
1a1715766f Fix enter to select model in agent panel (#34846)
Broken by #34664

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-21 19:16:47 +00:00
Anthony Eid
241acbe4be Stop onboarding page from showing up instead of welcome page (#34845)
This is from PR #34723 where I was working on developing the onboarding
page, but I forgot to switch the first page back to our current version.

Release Notes:

- N/A
2025-07-21 19:02:02 +00:00
Piotr Osiewicz
6ea09beea8 terminal: Handle spaces in cwds of remote terminals (#34844)
Closes #34807

Release Notes:

- Fixed "Open in terminal" action not working with paths that contain
spaces in SSH projects.
2025-07-21 18:51:27 +00:00
Piotr Osiewicz
3e50d997dd agent: Fix double-lease panic when clicking on thread to jump (#34843)
Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-21 18:44:45 +00:00
Richard Feldman
da8bf9ad79 Auto-retry agent errors by default (#34842)
Now we explicitly carve out exceptions for which HTTP responses we do
*not* retry for, and retry at least once on all others.

Release Notes:

- The Agent panel now automatically retries failed requests under more
circumstances.
2025-07-21 14:32:22 -04:00
Bennet Bo Fenner
589af59dfe collab: Refresh the LLM token once the terms of service have been accepted (#34833)
Release Notes:

- N/A
2025-07-21 20:02:28 +02:00
Kirill Bulatov
254c7a330a Regroup LSP context menu items by the worktree name (#34838)
Also 

* remove the feature gate
* open buffers with an error when no logs are present
* adjust the hover text to indicate that difference

<img width="480" height="380" alt="image"
src="https://github.com/user-attachments/assets/6b2350fc-5121-4b1e-bc22-503d964531a2"
/>

Release Notes:

- N/A
2025-07-21 17:48:07 +00:00
Balboa Codes
b6cf398eab docs: Fix PHP docs typo (#34836)
This fixes a minor typo in the PHP docs.

Release Notes:

- N/A
2025-07-21 17:25:59 +00:00
Anthony Eid
bc5c5cf5d6 onboarding: Create basic onboarding page (#34723)
Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-21 16:20:38 +00:00
Marshall Bowers
bf8aba566c collab: Remove unused billing preferences queries (#34830)
This PR removes some billing preferences queries that are no longer in
use.

Release Notes:

- N/A
2025-07-21 15:47:40 +00:00
Piotr Osiewicz
e14c9479e4 chore: Pin taffy version (#34827)
Follow-up to 34817

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-21 15:36:52 +00:00
Marshall Bowers
97af7e1bd9 collab: Remove PUT /billing/preferences endpoint (#34825)
This PR removes the `PUT /billing/preferences` endpoint, as it has been
moved to `cloud.zed.dev`.

Release Notes:

- N/A
2025-07-21 15:29:16 +00:00
Kamal Ahmad
c251f2a2d4 gpui: Throttle interactive resize events on Wayland (#34760)
Wayland compositors can potentially generate thousands of resize
requests when drag-resizing a window, which Zed is unable to keep up
with. This commit changes the behavior to only resize once per vblank
cycle, which helps significantly when resizing the window with a high
poll-rate mouse (1000Hz is common these days)

Here is an example of the behavior pre and post this commit, with some
print-debugging added for tracking resize calls. I have a wireless mouse
with a 2000Hz polling rate and a 165Hz display:

Before: 


https://github.com/user-attachments/assets/4c657f90-5fd2-4809-97ef-363fd48e81b8

After: 


https://github.com/user-attachments/assets/4a0f5fbd-c3c4-40a1-9f71-3b4358c827cf






Closes #20660

Release Notes:

- Improved: Make resizing smoother on Wayland/Linux
2025-07-21 17:48:01 +03:00
Agus Zubiaga
cc56196152 Fix loading agent server settings (#34662)
Release Notes:

- N/A
2025-07-21 14:26:00 +00:00
Agus Zubiaga
405244d422 Display ACP plans (#34816)
Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-21 11:11:37 -03:00
Piotr Osiewicz
35b4a918c9 chore: Bump taffy to 0.5.1 (#34817)
We've had problems in the past with bumping past 0.5.2 due to perf
regressions reported by @huacnlee; 0.5.1 was fine though.

Hence, let's bump taffy to 0.5.1 as a safe bet and then try to push past
0.5.2 (after we identify the root cause of regression
Related to #19189
Release Notes:

- N/A
2025-07-21 15:43:51 +02:00
Danilo Leal
56fd950d94 thread view: Add ability to expand message editor and fix scroll (#34766)
Release Notes:

- N/A
2025-07-21 09:26:31 -03:00
Piotr Osiewicz
88af35fe47 collab: Add screen selector (#31506)
Instead of selecting a screen to share arbitrarily, we'll now allow user
to select the screen to share. Note that sharing multiple screens at the
time is still not supported (though prolly not too far-fetched).

Related to #4666

![image](https://github.com/user-attachments/assets/1afb664f-3cdb-4e0a-bb29-9d7093d87fa5)

Release Notes:

- Added screen selector dropdown to screen share button

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-21 13:44:51 +02:00
Ben Brandt
57ab09c2da claude: Don't quote executable path in mcp configuration (#34805)
This was generating an invalid string for the configuration, removing
the extra quotes makes it work. This affected the versions of Zed that
have a space in their name.

Release Notes:

- N/A
2025-07-21 09:53:05 +00:00
Jason Lee
caa4b529e4 gpui: Add tab focus support (#33008)
Release Notes:

- N/A

With a `tab_index` and `tab_stop` option to `FocusHandle` to us can
switch focus by `Tab`, `Shift-Tab`.

The `tab_index` is from
[WinUI](https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.control.tabindex?view=winrt-26100)
and [HTML
tabindex](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/tabindex),
only the `tab_stop` is enabled that can be added into the `tab_handles`
list.

- Added `window.focus_next()` and `window.focus_previous()` method to
switch focus.
- Added `tab_index` to `InteractiveElement`.

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


https://github.com/user-attachments/assets/ac4e3e49-8359-436c-9a6e-badba2225211
2025-07-20 16:38:54 -07:00
Michael Sloan
137081f050 Misc code cleanups accumulated while working on other changes (#34787)
Release Notes:

- N/A
2025-07-20 23:22:13 +00:00
Ben Kunkle
7c1040bc93 keymap_ui: Auto complete action arguments (#34785)
Supersedes: #34242

Creates an `ActionArgumentsEditor` that implements the required logic to
have a JSON language server run when editing keybinds so that there is
auto-complete for action arguments.

This is the first time action argument schemas are required by
themselves rather than inlined in the keymap schema. Rather than add all
action schemas to the configuration options we send to the JSON LSP on
startup, this PR implements support for the
`vscode-json-language-server` extension to the LSP whereby the server
will request the client (Zed) to resolve URLs with URI schemes it does
not recognize, in our case `zed://`. This limits the impact on the size
of the configuration options to ~1KB as we send URLs for the language
server to resolve on demand rather than the schema itself. My
understanding is that this is how VSCode handles JSON schemas as well. I
plan to investigate converting the rest of our schema generation logic
to this method in a follow up PR.

Co-Authored-By: Cole <cole@zed.dev>

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-20 16:24:17 -04:00
Michael Sloan
ff79b29f38 Set stripe-mock version to 0.178.0 to match stripe API version used (#34786)
Release Notes:

- N/A
2025-07-20 19:39:04 +00:00
Bennet Bo Fenner
2e41e312ad component preview: Fix Zed AI onboarding young account preview (#34783)
Release Notes:

- N/A
2025-07-20 16:27:18 +00:00
Peter Tripp
5f92ac25a7 docs: Consolidate backend setup docs into local-collaboration.md (#34653)
Simplify docs for mac/linux/windows by consolidating the backend
dependencies (collaboration) docs into local-collaboration.md. Most
users building zed will not need to do this -- streamline them into
getting setup to build the zed client app first.

Release Notes:

- N/A
2025-07-19 12:01:33 -04:00
Peter Tripp
fb88de9223 Fix error in OpenRouter svg logo (#34764)
Fix a spurious error in Zed logs from the OpenRouter svg Logo introduced
in https://github.com/zed-industries/zed/pull/29496:

```log
WARN  [usvg::parser::svgtree] Failed to parse clip-path value: 'url(#clip0_205_3)'.
```

Release Notes:

- N/A
2025-07-19 16:01:18 +00:00
Oleksandr Mykhailenko
29111304dd agent: Fix Mistral tool use error message (#34692)
Closes #32675

Exactly the same changes as in #33640 by @sviande

The PR has been in WIP state for 3 weeks with no activity, and the issue
basically makes Mistral models unusable. I have tested the changes
locally, and it does indeed work. Full credit goes to @sviande, I just
want this feature to be finished.

Release Notes:

- agent: Fixed an issue with tool calling with the Mistral provider
(thanks [@sviande](https://github.com/sviande) and
[@armyhaylenko](https://github.com/armyhaylenko))

Co-authored-by: sviande <sviande@gmail.com>
2025-07-19 11:59:57 -04:00
Vitaly Slobodin
0ffd93774c Fix Tailwind support for HTML/ERB files (#34743)
Closes #27118
Closes #34165

Fix a small issue after we landed
https://github.com/zed-extensions/ruby/pull/113+ where we introduced
`HTML/ERB` and `YAML/ERB` language IDs to improve user experience. Sorry
about that. Thanks!

Release Notes:

- N/A
2025-07-19 11:06:35 -04:00
Mikayla Maki
2da2ae65a0 gpui: Add use state APIs (#34741)
This PR adds a component level state API to GPUI, as well as a few
utilities for simplified interactions with entities

Release Notes:

- N/A
2025-07-19 01:27:54 +00:00
morgankrey
4bdac8026c collab: Enable automatic tax calculation for all new subscriptions (#34720)
Release Notes:

- N/A

---------

Co-authored-by: Marshall Bowers <git@maxdeviant.com>
2025-07-18 21:42:48 +00:00
Peter Tripp
70bde54a2c ci: Lint GitHub Actions workflows with actionlint (#34729)
Added [rhysd/actionlint](https://github.com/rhysd/actionlint/) a static
checker for GitHub Actions workflow files.
Install locally with `brew install actionlint` the run with
`actionlint`.

Inspired by: https://github.com/zed-industries/zed/pull/34704 which
yielded this observation:

> In github actions: 
> 1. strings are truthy
> 2. `${{ }}` will become a string if it doesn't wrap the whole value.
>
> So `if: false && true` becomes `false`
> and `if: ${{ false && true }}` becomes `false`
> but `if: false && ${{ true }}` becomes `"false && true"` which
evaluates true
> The reason you sometimes need `${{ }}` is because YAML doesn't like
`!`
> so `if: !false` is invalid yaml
> and `if: ${{ !false }}` works just fine.

Changes:
- Add `actionlint` job
- Refactor `job_spec` job to be more readable
- Fix all `actionlint` and `shellcheck` errors in Actions workflows (62
in all)
- Add `self-mini-macos` and `self-32vcpu-windows-2022` labels to
self-hosted runners. Not strictly related, but useful if you need to
take a runner out of the rotation (since `macOS`, `self-hosted`, and
`ARM64` are auto-set and cannot be added/removed).
- Change ci.yml macos_relase to target `self-mini-macos` instead of
`bundle` which was previously deprecated.

This would've caught the error fixed in
https://github.com/zed-industries/zed/pull/34704. Here's what that [job
failure](https://github.com/zed-industries/zed/actions/runs/16376993944/job/46279281842?pr=34729)
would've looked like.

Release Notes:

- N/A
2025-07-18 15:15:07 -04:00
Conrad Irwin
43486c416c Fix enter in branch view (#34731)
Broken by #34664

Release Notes:

- N/A
2025-07-18 19:04:05 +00:00
Michael Sloan
d197c96cdc Add stripe-mock to docker compose configuration (#34732)
Release Notes:

- N/A
2025-07-18 18:58:55 +00:00
Peter Tripp
7b6b75b63f ci: Skip generating Windows release artifacts (#34704)
Release Notes:

- N/A
2025-07-18 14:31:08 -04:00
Anthony Eid
fd64ee1bb6 keymap ui: Fix remove key mapping bug (#34683)
Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-18 14:09:28 -04:00
Danilo Leal
e1d28ff957 agent: Add use_modifier_to_send setting (#34709)
When `use_modifier_to_send` is turned on, holding `cmd`/`ctrl` is
necessary to send a message in the agent panel. Text threads already use
`cmd-enter` by default to submit a message, and it was done this way to
have the usual text editing bindings not taken over when writing a
prompt, sort of stimulating more thoughtful writing. While `enter` to
send is still somewhat a huge pattern in chat-like LLM UIs, it still
makes sense to allow this for the new agent panel... hence the existence
of this setting now!

Release Notes:

- agent: Added the `use_modifier_to_send` setting, which makes holding a
modifier (`cmd`/`ctrl`), together with `enter`, required to send a new
message.
2025-07-18 15:03:31 -03:00
Danilo Leal
64ce696aae ui: Add the SwitchField component (#34713)
This will be useful for both the current agent panel and some other
onboarding stuff we're working on. Also ended up removing the
`SwitchWithLabel` as it was unused.

Release Notes:

- N/A
2025-07-18 15:03:14 -03:00
tidely
87555d3f0b project: Remove clones from git blame serialization (#34727)
Release Notes:

- N/A
2025-07-18 20:41:12 +03:00
Finn Evers
5b18ce79ab editor: Ensure topmost buffer header can be properly folded (#34721)
This PR fixes an issue where the topmost header in a multibuffer would
jump when the corresponding buffer was folded.
The issue arose because for the topmost header, the offset within the
scroll anchor is negative, as the corresponding buffer only starts below
the header itself and thus the offset for the scroll position has to be
negative.
However, upon collapsing that buffer, we end up with a negative vertical
scroll position, which causes all kinds of different problems. The issue
has been present for a long time, but became more visible after
https://github.com/zed-industries/zed/pull/34295 landed, as that change
removed the case distinction for buffers scrolled all the way to the
top.

This PR fixes this by clamping just the vertical scroll position upon
return, which ensures the negative offset works as expected when the
buffer is expanded, but the vertical scroll position does not turn
negative once the buffer is folded.

Release Notes:

- Fixed an issue where folding the topmost buffer in a multibuffer would
cause the header to jump slightly.
2025-07-18 19:16:31 +02:00
Smit Barmase
1dd470ca48 editor: Fix double $ sign on completion accept in PHP (#34726)
Closes #33510 https://github.com/zed-extensions/php/issues/29

If certain language servers do not provide an insert/replace range, we
use `surrounding_word` as a fallback for that range, which internally
uses `word_characters`. It makes sense to use
`completion_query_characters` instead of `word_characters` to get that
range, because we use `completion_query_characters` to query completions
in the first place.

That means, for some hypothetical reason (e.g., if the Tailwind server
stops providing insert/replace ranges), we would correctly fall back to
the range "bg-blue-200^" instead of "200^", because
`completion_query_characters` includes "-" in this case.

For this particular fix, right now the default PHP language server
`phpactor` does not provide an insert/replace range, and hence
completion query character is used, which is `$` in this case.

Note that `$` isn't in word characters for reasons mentioned here:
https://github.com/zed-extensions/php/issues/14

Release Notes:

- Fixed an issue where accepting variable completion in PHP would result
in a double $ sign in the prefix.
2025-07-18 22:39:00 +05:30
Finn Evers
8bc8d61fa6 theme_importer: Add missing color imports for the minimap thumb (#34724)
These should have been part of
https://github.com/zed-industries/zed/pull/30785 but I forgot to add
them there.

Release Notes:

- N/A
2025-07-18 16:55:03 +00:00
Marshall Bowers
750ceeb760 collab: Don't use screen-capture feature from gpui (#34725)
This PR removes the `screen-capture` feature from `gpui` when depending
on it in `collab`.

Release Notes:

- N/A
2025-07-18 16:28:58 +00:00
Danilo Leal
4476860664 Add refinements to the AI onboarding flow (#33738)
This includes making sure that both the agent panel and Zed's edit
prediction have a consistent narrative when it comes to onboarding users
into the AI features, considering the possible different plans and
conditions (such as being signed in/out, account age, etc.)

Release Notes:

- N/A

---------

Co-authored-by: Bennet Bo Fenner <53836821+bennetbo@users.noreply.github.com>
Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2025-07-18 18:25:36 +02:00
Joseph T. Lyons
9a20843ba2 Revert "gpui: Improve path rendering & global multisample anti-aliasing" (#34722)
Reverts zed-industries/zed#29718

We've noticed some issues with Zed on Intel-based Macs where typing has
become sluggish, and git bisect has seemed to point towards this PR.
Reverting for now, until we can understand why it is causing this issue.
2025-07-18 16:03:08 +00:00
Conrad Irwin
e421fc7a2d Update keymap context binding behavior of > and ! (#34664)
Now ! means "no ancestors matches this", and > means "any descendent"
not "any child".

Updates #34570

Co-authored-by: Ben Kunkle <ben@zed.dev>

Release Notes:

- *Breaking change*. The context predicates in the keymap file now
handle ! and > differently. Before this change ! meant "this node does
not match", now it means "none of these nodes match". Before this change
> meant "child of", now it means "descendent of". We do not expect these
changes to break many keymaps, but they may cause subtle changes for
complex context queries.

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-18 09:25:18 -06:00
Marshall Bowers
f461290ac3 collab: Add POST /users/:id/refresh_llm_tokens endpoint (#34714)
This PR adds a new `POST /users/:id/refresh_llm_tokens` endpoint to
Collab so that we can refresh LLM tokens from Cloud.

Release Notes:

- N/A
2025-07-18 14:52:42 +00:00
Peter Tripp
6a24b2479c Redact license keys in environment variables from log output (#34711)
Release Notes:

- N/A
2025-07-18 14:28:20 +00:00
Piotr Osiewicz
2ac99e7a11 debugger: Fix attaching with DebugPy (#34706)
@cole-miller found a root cause of our struggles with attach scenarios;
we did not fetch .so files necessary for attaching to work,
as we were downloading DebugPy source tarballs from GitHub.

This PR does away with it by setting up a virtualenv instead that has
debugpy installed.

Closes #34660
Closes #34575

Release Notes:

- debugger: Fixed attaching with DebugPy. DebugPy is now installed
automatically from pip (instead of GitHub), unless it is present in
active virtual environment. Additionally this should resolve any startup
issues with missing .so on Linux.
2025-07-18 14:28:03 +00:00
Peter Tripp
d604b3b291 Fix incorrect minimum_contrast comment (#34710)
Actual default is 45


fd05f17fa7/assets/settings/default.json (L1402)

Release Notes:

- N/A
2025-07-18 10:01:09 -04:00
Bennet Bo Fenner
4002801034 agent: Fix new thread model selection when starting new thread (#34708)
Release Notes:

- agent: Fixed an issue where clicking on "Start New Thread" in the
agent configuration would not always switch to the correct
provider/model
2025-07-18 13:58:44 +00:00
Peter Tripp
fd8480a9dc Document terminal.cursor_shape (#34707)
Release Notes:

- N/A
2025-07-18 13:35:36 +00:00
Danilo Leal
1070de47ec component preview: Add separators between sections in sidebar (#34701)
Small improvement for navigating inside the component preview.

Release Notes:

- N/A
2025-07-18 10:24:57 -03:00
Ben Brandt
cfe1adc792 E2E Claude tests (#34702)
- **Fix cancellation of tool calls**
- **Make tool_call test more resilient**
- **Fix tool call confirmation test**

Release Notes:

- N/A
2025-07-18 13:17:41 +00:00
Lukas Spiss
fd05f17fa7 go: Support raw string subtest names (#34636)
Currently, we're not able to run Go sub-tests that have a raw string
(e.g. we're using multi-line names a lot) via the UI. I added the
changes that are needed, plus a handful of tests to cover the basics.

Quick comparison:

Before:
<img width="901" height="370" alt="before"
src="https://github.com/user-attachments/assets/4e5cadeb-9a0c-49e2-b976-2223e1010f85"
/>



After:
<img width="901" height="505" alt="after"
src="https://github.com/user-attachments/assets/994fc69b-f720-488c-a14b-853a3ca2f53c"
/>


Release Notes:

- Added support for Go subtest runner with raw string names
2025-07-18 13:38:18 +02:00
tidely
7e3fd7bb02 gpui: Use static keyword with LazyLock when loading system fonts (#34555)
Use the `static` keyword to actually make the `LazyLock` static, which
previously would reinitialize on every call to `SvgRenderer::new`.

Related: #26335 

Release Notes:

- N/A
2025-07-18 12:35:38 +02:00
Arseny Kapoulkine
00097df0d5 Improve C/C++ indentation flow for single statement blocks (#34549)
Before this, indentation did not automatically increase after
if/for/while/do/else statements in C++, and only increased after if/for
in C. This led to Zed using last line logic when inserting lines *after*
the indented statement, as well as not indenting the statement itself,
resulting in irregular indentation during typing.

Just adding indentation (similar to C) creates a new problem: now if a
scope is started with a brace on a new line, that brace is indented.
Thus we need to deindent it.

Using else_clause in the indent guide results in the else statement
being indented forward as well, so we need to deindent that too.

Note: the most significant issue for me is the one where indentation
jumps forward when inserting lines after indented lines. Unfortunately,
it appears that fixing that issue requires all of these other changes. I
would have preferred a simpler fix, but I'm not sure if disabling last
line behavior for C/C++ is appropriate as it probably breaks something
else, like cases where the file is incomplete and the statements can't
be parsed properly.

Editing flow before this change:

[Screencast From 2025-07-16
08-31-36.webm](https://github.com/user-attachments/assets/3dea86c5-47bd-47c2-aee8-b0aa613948e6)

Editing flow after this change:

[Screencast From 2025-07-16
08-35-36.webm](https://github.com/user-attachments/assets/7ef23e60-1ee3-49fd-90f9-d53f909ca674)

(note: the "else" snippet is completely breaking the flow here, but I
think that comes from clangd by default? Unfortunately I haven't found a
way to disable it cleanly but that is a separate problem that happens
right now too.)

Release Notes:

- Improve indentation during typing for C/C++ around if/for/while/do
blocks
2025-07-18 12:24:20 +02:00
Andy Waite
c13322397e docs: Document pull diagnostics support for Ruby (#34028)
This is now supported.

Release Notes:

- N/A
2025-07-18 12:46:36 +03:00
Daniel Sauble
c1307cead4 Add ; key binding for Helix mode (#34315)
Closes #34111

In Helix mode, the `;` key should collapse the current selection without
moving the cursor. I've added a new action `vim::HelixCollapseSelection`
to support this behavior.


https://github.com/user-attachments/assets/1a40821a-f56f-456e-9d37-532500bef17b

Release Notes:

- Added `;` key binding to collapse the current text selection in Helix
mode
2025-07-17 22:30:01 -06:00
Danilo Leal
8a7bd5f47b agent: Adjust retry on Burn Mode layout (#34680)
Quick follow-up to https://github.com/zed-industries/zed/pull/34669 so
that the buttons don't look so big in comparison to the callout.

Release Notes:

- N/A
2025-07-18 01:19:27 +00:00
Danilo Leal
c287397a18 Rename "CloseInactiveItems" action to "CloseOtherItems" (#34676)
This is following feedback from folks that were searching the "close
others" action, available in the tab's context menu, and not finding it
because it was actually named "close inactive", which was confusing. So,
this PR makes sure the tab's menu item and the action have consistent
naming.

Release Notes:

- Rename "CloseInactiveItems" action to "CloseOtherItems" for naming
consistency.
2025-07-17 21:40:02 -03:00
Smit Barmase
a7284adafa editor: Fix cursor doesn’t move up and down on arrow keys when no completions are shown (#34678)
Closes #34338

After https://github.com/zed-industries/zed/pull/31872, to avoid
re-querying language servers, we keep the context menu around, which
stores initial query, completions items, etc., even though it may not
contain any items and hence not be rendered on screen. In this state,
up/down arrows try to switch focus in the context menu instead of
propagating it to the editor. Hence blocking buffer movement.

This PR fixes it by changing the context for `menu`,
`showing_completions`, and `showing_code_actions` to only be added when
the menu is actually being rendered (i.e., not empty).

Release Notes:

- Fix an issue where the cursor doesn’t move up and down on arrow keys
when no completions are shown.
2025-07-18 06:07:52 +05:30
Ben Kunkle
4314b35288 keymap_ui: Don't panic on KeybindSource::from_meta (#34652)
Closes #ISSUE

Log error instead of panicking when `from_meta` is passed an invalid
value

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-17 20:03:10 -04:00
Danilo Leal
ed4deaa738 agent: Remove layout shift due to the "waiting for confirmation" label (#34674)
Take 2 on https://github.com/zed-industries/zed/pull/33046.

Release Notes:

- N/A
2025-07-17 20:46:16 -03:00
Danilo Leal
f0a91502a9 keymap_ui: Add some design refinements (#34673)
Mostly small stuff over here.

Release Notes:

- N/A
2025-07-17 20:22:21 -03:00
Richard Feldman
1ab659c71f Retry on burn mode (#34669)
Now we only auto-retry if burn mode is enabled. We also show a "Retry"
button (so you don't have to type "continue") if you think that's the
right remedy, and additionally we show a "Retry and Enable Burn Mode"
button if you don't have it enabled.

<img width="484" height="260" alt="Screenshot 2025-07-17 at 6 25 27 PM"
src="https://github.com/user-attachments/assets/dc5bf1f6-8b11-4041-87aa-4f37c95ea9f0"
/>

<img width="478" height="307" alt="Screenshot 2025-07-17 at 6 22 36 PM"
src="https://github.com/user-attachments/assets/1ed6578a-1696-449d-96d1-e447d11959fa"
/>


Release Notes:

- Only auto-retry Agent requests when Burn Mode is enabled
2025-07-17 23:04:03 +00:00
Richard Feldman
d470411725 Improve upstream error reporting (#34668)
Now we handle more upstream error cases using the same auto-retry logic.

Release Notes:

- N/A
2025-07-17 18:12:48 -04:00
Finn Evers
6c741292df keymap_ui: Fix various keymap editor issues (#34647)
This PR tackles miscellaneous nits for the new keymap editor UI.

Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-17 18:12:10 -04:00
Danilo Leal
29030a243c docs: Add instructions about how to use MCP servers (#34656)
Release Notes:

- N/A
2025-07-17 18:49:44 -03:00
Cole Miller
237ce5c8e8 Report build SHA to Slack for Zed Nightly panics (#34665)
There can be a bunch of nightlies with the same version number and it's
helpful to know exactly which one reported a panic.

Release Notes:

- N/A
2025-07-17 21:38:45 +00:00
Peter Tripp
0c88189aab Refine JetBrains keymaps (#34658)
Follow-up to: https://github.com/zed-industries/zed/pull/34641

Release Notes:

- N/A
2025-07-17 19:23:00 +00:00
Marshall Bowers
1e60ebb2c6 collab: Remove GET /billing/usage endpoint (#34651)
This PR removes the `GET /billing/usage` endpoint, as it has been moved
to `cloud.zed.dev`.

Release Notes:

- N/A
2025-07-17 18:34:04 +00:00
Peter Tripp
9efe9df800 Harmonize buffer_font_size between default.json and initial_settings.json (#34650)
Release Notes:

- N/A
2025-07-17 18:32:04 +00:00
Agus Zubiaga
dab0b3509d Unify agent server settings and extract e2e tests out (#34642)
Release Notes:

- N/A
2025-07-17 17:34:38 +00:00
Smit Barmase
0f72d7ed52 editor: Fix sometimes green (+) cursor style appearing when cmd-clicking in same buffer (#34638)
Follow-up for https://github.com/zed-industries/zed/pull/34557

This PR clears the selection drag state on click, because mouse up
doesn't trigger on click event because of `cx.stop_propagation`. The
issue occurs with similar repro steps as mentioned in the attached PR.

Release Notes:

- Fixed the issue where the green (+) cursor style sometimes appears
when navigating to the definition in buffer.
2025-07-17 22:46:44 +05:30
Peter Tripp
1ceda2babd JetBrains keymap improvements (July 2025) (#34641)
Closes: https://github.com/zed-industries/zed/issues/14639
Closes: https://github.com/zed-industries/zed/issues/33020

If would have ideas for future enhancements, please see:
- https://github.com/zed-industries/zed/discussions/34643

Various Jetbrains keymaps improvements for macOS and Linux/Windows:

| Area | Action | macOS | Linux |
| ------------- | -------------------------- |
--------------------------------- | --------------------------------- |
| Workspace | Toggle Git Panel | `cmd-0` | `ctrl-0` |
| Workspace | Toggle Project Panel | `cmd-1` | `alt-0` |
| Workspace | Toggle Debug Panel | `cmd-5` | `alt-1` |
| Workspace | Toggle Diagnostics | `cmd-6` | `alt-6` |
| Workspace | Toggle Outline Panel | `cmd-7` | `alt-7` |
| Workspace | Toggle Terminal Panel | `alt-f12` | `alt-f12` |
| Workspace | File Finder | `cmd-e` | `ctrl-e` |
| Workspace | Task Spawn | `ctrl-alt-r` | `alt-shift-f10` |
| Workspace | Close All Docks | `ctrl-shift-f12` | `ctrl-shift-f12` |
| Project Panel | Search in Directory | `cmd-shift-f` | `ctrl-shift-f` |
| Search | Replace in Files | `cmd-shift-r` | `ctrl-shift-r` |
| Search | Replace in Buffer | `cmd-r` | `ctrl-r` |
| Search | Toggle Case Sensitive | `ctrl-alt-c` / `alt-c` | `ctrl-alt-c`
|
| Search | Toggle Search in Selection | `ctrl-alt-s` / `alt-s` |
`ctrl-alt-s` |
| Search | Toggle Regex | `ctrl-alt-x` / `alt-x` | `ctrl-alt-x` |
| Search | Toggle Whole Word | `ctrl-alt-w` / `alt-w` | `ctrl-alt-w` |
| Terminal | New Terminal Tab | `cmd-t` | `ctrl-shift-t` |
| Terminal | Scroll Line | `cmd-up` / `cmd-down` | `ctrl-up` /
`ctrl-down` |
| Terminal | Scroll Page | `shift-pageup` / `shift-pagedown` |
`shift-pageup` / `shift-pagedown` |
| Git | Git Panel | `cmd-k` | `ctrl-k` |
| Git | Git Push | `cmd-shift-k` | `ctrl-shift-k` |

In addition, with the help of the recently merged
https://github.com/zed-industries/zed/pull/34495, no matter where you
are mashing `escape` will refocus you back to your most recent editor
buffer similar to the behavior of JetBrains.

Release Notes:

- jetbrains: Added 25+ keybinds to the macOS and Linux/Windows JetBrains
compatibility keymaps
2025-07-17 17:14:24 +00:00
Anthony Eid
ae0d4f6a0d debugger: Add data breakpoint access type support (#34639)
Release Notes:

- Support specifying a data breakpoint's access type - Read, Write, Read
& Write
2025-07-17 17:05:58 +00:00
Piotr Osiewicz
8980526a85 chore: Bump lsp-types rev (#34345)
Closes #ISSUE

Release Notes:

- N/A
2025-07-17 15:58:54 +00:00
Umesh Yadav
b4dc7f8a8a debugger: Add support for running test methods with function receiver in Go (#34613)
![CleanShot 2025-07-17 at 16 35
10](https://github.com/user-attachments/assets/bad794fb-198e-40a1-958c-6ff30a0a4e53)


Closes #33759

Release Notes:

- debugger: Add support for running test methods with function receiver
in Go

Signed-off-by: Umesh Yadav <git@umesh.dev>
2025-07-17 17:44:40 +02:00
Ben Kunkle
b94649ce1e keymap_ui: Show edit icon on hovered and selected row (#34630)
Closes #ISSUE

Improves the behavior of the edit icon in the far left column of the
keymap UI table. It is now shown in both the selected and the hovered
row as an indicator that the row is editable in this configuration. When
hovered a row can be double clicked or the edit icon can be clicked, and
when selected it can be edited via keyboard shortcuts. Additionally, the
edit icon and all other hover tooltips will now disappear when the table
is navigated via keyboard shortcuts.

<details><summary>Video</summary>



https://github.com/user-attachments/assets/6584810f-4c6d-4e6f-bdca-25b16c920cfc

</details>

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-17 11:34:34 -04:00
Ben Kunkle
948c1f22bb keymap_ui: Improve keybind display in menus (#34587)
Closes #ISSUE

Defines keybindings for `keymap_editor::EditBinding` and
`keymap_editor::CreateBinding`, making sure those actions are used in
tooltips.

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Finn <dev@bahn.sh>
2025-07-17 11:10:07 -04:00
Ben Brandt
b0eac4267d Mark glob/grep as code blocks (#34628)
Release Notes:

- N/A
2025-07-17 15:01:02 +00:00
Agus Zubiaga
8e4555455c Claude experiment (#34577)
Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
Co-authored-by: Nathan Sobo <nathan@zed.dev>
Co-authored-by: Oleksiy Syvokon <oleksiy.syvokon@gmail.com>
2025-07-17 14:25:55 +00:00
Kirill Bulatov
5b97cd1900 Better serialize the git panel (#34622)
Follow-up of https://github.com/zed-industries/zed/pull/29874
Closes https://github.com/zed-industries/zed/issues/34618
Closes https://github.com/zed-industries/zed/issues/34611

Release Notes:

- N/A
2025-07-17 12:39:41 +00:00
Kirill Bulatov
ceab139f54 Rework extension-related errors (#34620)
Before:
<img width="1728" height="1079" alt="before"
src="https://github.com/user-attachments/assets/4ab19211-8de4-458d-a835-52de859b7b20"
/>

After:
<img width="1728" height="1079" alt="after"
src="https://github.com/user-attachments/assets/231c9362-a0b0-47ae-b92e-de6742781d36"
/>

Makes clear which path is causing the FS error and removes backtraces
from logging.

Release Notes:

- N/A
2025-07-17 12:20:47 +00:00
Oleksiy Syvokon
4df7f52bf3 agent: Disable project_notifications by default (#34615)
This tool needs more polishing before being generally available.

Release Notes:

- agent: Disabled `project_notifications` tool by default for the time
being
2025-07-17 11:55:38 +00:00
Oleksiy Syvokon
1e67e30034 Fix shortcuts with Shift (#34614)
Closes #34605, #34606, #34609

Release Notes:

- Fixed shortcuts involving Shift
2025-07-17 11:21:20 +00:00
Arseny Kapoulkine
758c5fb955 Allow disabling snippet completion by setting snippet_sort_order to none (#34565)
This mirrors VSCode setting that inspired `snippet_sort_order` to begin
with; VSCode supports inline/top/bottom/none, with none completely
disabling snippet completion. See
https://code.visualstudio.com/docs/editing/intellisense#_snippets-in-suggestions

This is helpful for LSPs that do not allow configuring snippets via
configuration such as clangd.

Release Notes:

- Added `none` as one of the values for `snippet_sort_order` to
completely disable snippet completion.
2025-07-17 16:22:26 +05:30
Oleksiy Syvokon
acb3ecef0c Do not send project notifications when agent creates a file (#34610)
Release Notes:

- N/A
2025-07-17 13:08:20 +03:00
Finn Evers
ad2bfa3edd Disable minimap in the inspector (#34607)
This disables the minimap in the inspector UI as it doesn't bring any
value to it and just takes up unnecessary space.

Release Notes:

- N/A
2025-07-17 09:22:04 +00:00
Eric Cornelissen
1d72fa8e9e git: Add ability to pass --signoff (#29874)
This adds an option for `--signoff` to the git panel and commit modal.
It allows users to enable the [`--signoff`
flag](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt-code--signoffcode)
when committing through Zed. The option is added to the context menu of
the commit button (following the style of the "Editor Controls").

To support this, the commit+amend experience was revamped (following the
ideas of [this
comment](https://github.com/zed-industries/zed/pull/29874#issuecomment-2950848000)).
Amending is now also a toggle in the commit button's dropdown menu. I've
kept some of the original experience such as the changed button text and
ability to cancel outside the context menu.

The tooltip of the commit buttons now also includes the flags that will
be used based on the amending and signoff status (which I couldn't
capture in screenshots unfortunately). So, by default the tooltip will
say `git commit` and if you toggle, e.g., amending on it will say `git
commit --amend`.

| What | Panel | Modal |
| --- | --- | --- |
| Not amending, dropdown | ![git modal preview, not amending,
dropdown](https://github.com/user-attachments/assets/82c2b338-b3b5-418c-97bf-98c33202d7dd)
| ![commit modal preview, not amending,
dropdown](https://github.com/user-attachments/assets/f7a6f2fb-902d-447d-a473-2efb4ba0f444)
|
| Amending, dropdown | ![git modal preview, amending,
dropdown](https://github.com/user-attachments/assets/9e755975-4a27-43f0-aa62-be002ecd3a92)
| ![commit modal preview, amending,
dropdown](https://github.com/user-attachments/assets/cad03817-14e1-46f6-ba39-8ccc7dd12161)
|
| Amending | ![git modal preview,
amending](https://github.com/user-attachments/assets/e1ec4eba-174e-4e5f-9659-5867d6b0fdc2)
| - |

The initial implementation was based on the changeset of
https://github.com/zed-industries/zed/pull/28187.

Closes https://github.com/zed-industries/zed/discussions/26114

Release Notes:

- Added git `--signoff` support.
- Update the git `--amend` experience.
- Improved git panel to persist width as well as amend and signoff on a
per-workspace basis.
2025-07-17 03:39:54 +00:00
Conrad Irwin
1ce384bbda Fix ctrl-q on AZERTY on Linux (#34597)
Closes #ISSUE

Release Notes:

- N/A
2025-07-16 21:27:46 -06:00
Conrad Irwin
9f302df6d6 Don't override ascii graphical shortcuts (#34592)
Closes #34536

Release Notes:

- (preview only) Fix shortcuts on Extended Latin keyboards on Linux
2025-07-16 20:09:38 -06:00
Smit Barmase
ebad5ca50e linux: Fix buttons clicks wouldn’t work on startup until clicked on center pane (#34590)
Closes #31805

This is an issue with Linux currently that `window.focus` is `None` upon
startup in both X11 and Wayland. Specifically, the order in which
[this](8d05a3d389/crates/gpui/src/window.rs (L3116))
and
[this](8d05a3d389/crates/gpui/src/app.rs (L956))
are executed varies between Linux and macOS. That is, one tries to
remove (blur) focus from a window, while other checks window focus to
put that focus id to a frame. In macOS, blur happens afterwards setting
focus on a frame, but in Linux, the inverse of it happens, leading to
`window.focus` to `None`.

For the time being, we handle all visible buttons to take care of this
**focus can be `None`** case, and make it work anyway. But, we should
look at the deeper issue mentioned above with GPUI. Created new issue to
track that https://github.com/zed-industries/zed/issues/34591.

Release Notes:

- Fixed an issue where button clicks wouldn’t work on startup until
clicked on the center pane on Linux.
2025-07-17 06:36:02 +05:30
Cole Miller
b9ff538747 docs: Discuss inlay_hints.show_value_hints in debugger docs (#34581)
This isn't under the `debugger` settings key, but it seems good to
document on the debugger page anyway.

Release Notes:

- N/A
2025-07-16 19:35:30 -04:00
Anthony Eid
c0261a1ea9 keymap ui: Fix keymap editor search bugs (#34579)
Keystroke input now gets cleared when toggling to normal search mode
Main search bar is focused when toggling to normal search mode

This also gets rid of highlight on focus from keystroke_editor because
it also matched the search bool field and was redundant

Release Notes:

- N/A
2025-07-16 18:05:26 -04:00
Marshall Bowers
f43bcc1492 collab: Remove GET /billing/subscriptions endpoint (#34580)
This PR removes the `GET /billing/subscriptions` endpoint, as it has
been moved to `cloud.zed.dev`.

Release Notes:

- N/A
2025-07-16 22:04:53 +00:00
Umesh Yadav
e23a4564cc keymap_ui: Open Keymap editor from settings dropdown (#34576)
@probably-neb I guess we should be opening the keymap editor from title
bar and menu as well. I believe this got missed in this: #34568.

Release Notes:

- Open Keymap editor from settings from menu and title bar.
2025-07-16 17:30:08 -04:00
Peter Tripp
f82ef1f76f agent: Support GEMINI_API_KEY environment variable (#34574)
Google Gemini Docs now recommend usage of `GEMINI_API_KEY` and the
legacy `GOOGLE_AI_API_KEY` variable is no longer supported in the modern
SDKs.

Zed will now accept either.

Release Notes:

- N/A
2025-07-16 20:55:54 +00:00
Richard Feldman
b4c2ae5196 Handle upstream_http_error completion responses (#34573)
Addresses upstream errors such as:
<img width="831" height="100" alt="Screenshot 2025-07-16 at 3 37 03 PM"
src="https://github.com/user-attachments/assets/2aeb0257-6761-4148-b687-25fae93c68d8"
/>

These should now automatically retry like other upstream HTTP error
codes.

Release Notes:

- N/A
2025-07-16 16:31:31 -04:00
Peter Tripp
0023773c68 docs: Add Zed as Git Editor example (#34572)
Release Notes:

- N/A
2025-07-16 19:57:02 +00:00
Anthony Eid
0bde929d54 Add keymap editor UI telemetry events (#34571)
- Search queries
- Keybinding update or removed
- Copy action name
- Copy context name

cc @katie-z-geer 

Release Notes:

- N/A

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-16 19:50:53 +00:00
Joseph T. Lyons
6f60939d30 Bump Zed to v0.197 (#34569)
Release Notes:

-N/A
2025-07-16 18:48:50 +00:00
Ben Kunkle
a6a7a1cc28 keymap_ui: Remove feature flag (#34568)
Closes #ISSUE

Release Notes:

- Rebound the keystroke to open the keymap file, to open the new keymap
editor
2025-07-16 18:28:44 +00:00
Anthony Eid
13f4a093c8 Improve keystroke search in keymap editor (#34567)
This PR improves Keystroke search by:

1.  Allow searching by modifiers without additional keys.
2. Take match count into consideration when deciding if we should show
an action as a search match.
3. Take order into consideration as well.

Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-16 18:19:41 +00:00
Ben Kunkle
573836a654 keymap_ui: Replace zed::NoAction with null (#34562)
Closes #ISSUE

This change applies both to the UI (we render `<null>` as muted text
instead of `zed::NoAction`) as well as how we update the keymap file
(the duplicated binding is bound to `null` instead of `"zed::NoAction"`)

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-16 17:55:58 +00:00
Marshall Bowers
048dc47d87 collab: Remove GET /billing/preferences endpoint (#34566)
This PR removes the `GET /billing/preferences` endpoint, as it has been
moved to `cloud.zed.dev`.

Release Notes:

- N/A
2025-07-16 17:55:01 +00:00
Smit Barmase
ffc69b07e5 editor: Fix sometimes green (+) cursor style appearing when cmd-clicking to navigate and back (#34557)
Regressed in https://github.com/zed-industries/zed/pull/33928

This PR clears the selection drag state when the editor focus is out.

To reproduce: 

1. Select some item in buffer that has a go to definition.
2. Cmd+Click mouse down on it, but don't let go.
3. Wait for 300ms+. 
4. Now cursor changed to green + (valid state, this is for selection
drag-n-drop).
5. Now let go of your mouse down, we switched to a different file.
Cursor looks normal.
6. Come back to the previous buffer, see green + cursor style (BUG!).

Release Notes:

- Fixed the issue where the green (+) cursor style sometimes appears
when navigating to the definition and then back to the previous buffer.
2025-07-16 23:24:02 +05:30
Piotr Osiewicz
dc8d0868ec project: Fix up documentation for Path Trie and add a test for having multiple present nodes (#34560)
cc @cole-miller I was worried with
https://github.com/zed-industries/zed/pull/34460#discussion_r2210814806
that PathTrie would not be able to support nested .git repositories, but
it seems fine.

Release Notes:

- N/A
2025-07-16 17:24:34 +00:00
Ben Kunkle
58807f0dd2 keymap_ui: Create language for Zed keybind context (#34558)
Closes #ISSUE

Creates a new language in the languages crate for the DSL used in Zed
keybinding context. Previously, keybind context was highlighted as Rust
in the keymap UI due to the expression syntax of Rust matching that of
the context DSL, however, this had the side effect of highlighting upper
case contexts (e.g. `Editor`) however Rust types would be highlighted
based on the theme. By extracting only the necessary pieces of the Rust
language `highlights.scm`, `brackets.scm`, and `config.toml`, and
continuing to use the Rust grammar, we get a better result across
different themes

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-16 17:00:47 +00:00
Adam
313f5968eb Improve the read_file tool prompt for long files (#34542)
Closes [#ISSUE](https://github.com/zed-industries/zed/issues/31780)

Release Notes:

- Enhanced `read_file` tool call result message for long files.
2025-07-16 16:32:58 +00:00
Anthony Eid
9ab3d55211 Add exact matching option to keymap editor search (#34497)
We know have the ability to filter matches in the keymap editor search
by exact keystroke matches. This allows user's to have the same behavior
as vscode when they toggle all actions with the same bindings

We also fixed a bug where conflicts weren't counted correctly when
saving a keymapping. This cause issues where warnings wouldn't appear
when they were supposed to.

Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
2025-07-16 12:14:09 -04:00
Oleksiy Syvokon
e339566dab agent: Limit the size of patches generated from user edits (#34548)
Gradually remove details from a patch to keep it within the size limit.
This helps avoid using too much context when the user pastes large
files, generates files, or just makes many changes between agent
notifications.

Release Notes:

- N/A
2025-07-16 15:46:13 +00:00
Umesh Yadav
8ee5bf2c38 open_router: Fix tool_choice getting serialized to null (#34532)
Closes #34314

This PR resolves an issue where serde(untagged) caused Rust None values
to serialize as null, which OpenRouter's Mistral API (when tool_choice
is present) incorrectly interprets as a defined value, leading to a 400
error. By replacing serde(untagged) with serde(snake_case), None values
are now correctly omitted from the serialized JSON, fixing the problem.
P.S. A separate PR will address serde(untagged) usage for other
providers, as null is not expected for them either.

Release Notes:

- Fix ToolChoice getting serialized to null on OpenRouter
2025-07-16 11:44:08 -04:00
Marshall Bowers
b0e0485b32 docs: Add redirects for language pages (#34544)
This PR adds some more docs redirects for language pages.

Release Notes:

- N/A
2025-07-16 14:50:54 +00:00
Danilo Leal
2a49f40cf5 docs: Add some improvements to the agent panel page (#34543)
Release Notes:

- N/A
2025-07-16 11:49:53 -03:00
Ben Kunkle
21b4a2ecdd keymap_ui: Infer use key equivalents (#34498)
Closes #ISSUE

This PR attempts to add workarounds for `use_key_equivalents` in the
keymap UI. First of all it makes it so that `use_key_equivalents` is
ignored when searching for a binding to replace so that replacing a
keybind with `use_key_equivalents` set to true does not result in a new
binding. Second, it attempts to infer the value of `use_key_equivalents`
off of a base binding when adding a binding by adding an optional `from`
parameter to the `KeymapUpdateOperation::Add` variant. Neither
workaround will work when the `from` binding for an add or the `target`
binding for a replace are not in the user keymap.

cc: @Anthony-Eid 

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-16 10:49:16 -04:00
Peter Tripp
2a9a82d757 macos: Add mappings for alt-delete and cmd-delete (#34493)
Closes https://github.com/zed-industries/zed/issues/34484

Release Notes:

- macos: Add default mappings for `alt-delete` and `cmd-delete` in
Terminal (delete word to right; delete to end of line)
2025-07-16 10:45:34 -04:00
Marshall Bowers
6e147b3b91 docs: Organize redirects (#34541)
This PR organizes the docs redirects and adds some instructions for
them.

Release Notes:

- N/A
2025-07-16 14:44:24 +00:00
Umesh Yadav
875c86e3ef agent_ui: Fix token count not getting shown in the TextThread (#34485)
Closes #34319 

In this pr: https://github.com/zed-industries/zed/pull/33462 there was
check added for early return for active_thread and message_editor as
those are not present in the TextThread and only available in the Thread
the token count was not getting triggered for TextThread this pr fixes
that regression by moving the logic specific to Thread inside of thread
view match.

<img width="3024" height="1886" alt="CleanShot 2025-07-15 at 23 50
18@2x"
src="https://github.com/user-attachments/assets/bd74ae8b-6c37-4cdd-ab95-d3c253b8a948"
/>


Release Notes:

- Fix token count not getting shown in the TextThread
2025-07-16 10:39:07 -04:00
Oleksiy Syvokon
406ffb1e20 agent: Push diffs of user edits to the agent (#34487)
This change improves user/agent collaborative editing.

When the user edits files that are used by the agent, the
`project_notification` tool now pushes *diffs* of the changes, not just
file names. This helps the agent to stay up to date without needing to
re-read files.

Release Notes:

- Improved user/agent collaborative editing: agent now receives diffs of
user edits
2025-07-16 14:38:58 +00:00
Marshall Bowers
257bedf09b docs: Add missing extensions to redirects (#34539)
Fixes the redirects added in
https://github.com/zed-industries/zed/pull/34537.

Release Notes:

- N/A
2025-07-16 14:15:33 +00:00
Marshall Bowers
37927a5dc8 docs: Add some more redirects (#34537)
This PR adds some more redirects for the docs.

Release Notes:

- N/A
2025-07-16 10:01:31 -04:00
Smit Barmase
d4110fd2ab linux: Fix spacebar not working with multiple keyboard layouts (#34514)
Closes #26468 #16667

This PR fixes the spacebar not working with multiple keyboard layouts on
Linux X11. I have tested this with Czech, Russian, German, German Neo 2,
etc. It seems to work correctly.

`XkbStateNotify` events correctly update XKB state with complete
modifier info (depressed/latched/locked), but `KeyPress/KeyRelease`
events immediately overwrite that state using `update_mask()` with only
raw X11 modifier bits. This breaks xkb state as we reset `latched_mods`
and `locked_mods` to 0, as well as we might not correctly handle cases
where this new xkb state needs to change.

Previous logic is flawed because `KeyPress/KeyRelease` event only gives
you depressed modifiers (`event.state`) and not others, which we try to
fill in from `previous_xkb_state`. This patch was introduced to fix
capitalization issue with Neo 2
(https://github.com/zed-industries/zed/pull/14466) and later to fix
wrong keys with German layout
(https://github.com/zed-industries/zed/pull/31193), both of which I have
tested this PR with.

Now, instead of manually managing XKB state, we use the `update_key`
method, which internally handles modifier states and other cases we
might have missed.
  
From `update_key` docs:

> Update the keyboard state to reflect a given key being pressed or
released.
>
> This entry point is intended for programs which track the keyboard
state explictly (like an evdev client). If the state is serialized to
you by a master process (like a Wayland compositor) using functions like
`xkb_state_serialize_mods()`, you should use `xkb_state_update_mask()`
instead. **_The two functins should not generally be used together._**
>                
> A series of calls to this function should be consistent; that is, a
call with `xkb::KEY_DOWN` for a key should be matched by an
`xkb::KEY_UP`; if a key is pressed twice, it should be released twice;
etc. Otherwise (e.g. due to missed input events), situations like "stuck
modifiers" may occur.
>              
> This function is often used in conjunction with the function
`xkb_state_key_get_syms()` (or `xkb_state_key_get_one_sym()`), for
example, when handling a key event. In this case, you should prefer to
get the keysyms *before* updating the key, such that the keysyms
reported for the key event are not affected by the event itself. This is
the conventional behavior.

  
Release Notes:

- Fix the issue where the spacebar doesn’t work with multiple keyboard
layouts on Linux X11.
2025-07-16 19:25:13 +05:30
Peter Tripp
3d160a6e26 Don't highlight partial indent guide backgrounds (#34433)
Closes https://github.com/zed-industries/zed/issues/33665

Previously if a line was indented something that was not a multiple of
`tab_size` with `"ident_guides": { "background_coloring": "indent_aware"
} }` the background of characters would be highlighted. E.g. indent of 6
with tab_size 4.

| Before / After |
| - |
| <img width="497" height="77" alt="Screenshot 2025-07-14 at 14 43 46"
src="https://github.com/user-attachments/assets/93923117-047d-4d21-9a4f-488345f1ab89"
/>
| <img width="481" height="84" alt="Screenshot 2025-07-14 at 14 43 09"
src="https://github.com/user-attachments/assets/a5d383cb-50c3-4239-ae8c-f72765ae7287"
/> |

CC: @bennetbo Any idea why this partial indent was enabled in your
initial implementation
[here](https://github.com/zed-industries/zed/pull/11503/files#diff-1781b7848dd9630f3c4f62df322c08af9a2de74af736e7eba031ebaeb4a0e2f4R3156-R3160)?
This looks to be intentional.

Release Notes:

- N/A
2025-07-16 09:10:51 -04:00
Ragul R
c29c46d3b6 Appropriately pick venv activation script (#33205)
when `terminal.detect_venv.activate_script` setting is default, pick the
appropriate activate script as per the `terminal.shell` settings
specified by the user. Previously when the activate_script setting is
default, zed always try to use the `activate` script, which only works
when the user shell is `bash or zsh`. But what if the user is using
`fish` shell in zed?

Release Notes:

- python: value of `activate_script` setting is now automatically
inferred based on the kind of shell the user is running with.

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2025-07-16 12:52:37 +00:00
Piotr Osiewicz
312369c84f debugger: Improve drag-and-scroll in memory views (#34526)
Closes #34508

Release Notes:

- N/A
2025-07-16 10:00:36 +00:00
Stephen Samra
42b2b65241 Document alternative method to providing intelephense license key (#34502)
This PR updates the [Intelephense section in the
docs](https://zed.dev/docs/languages/php#intelephense) to include an
alternative way to provide the premium license key.

Release Notes:

- N/A
2025-07-16 06:14:18 +00:00
someone13574
a529103825 Disable format-on-save for verilog (#34512)
Disables format-on-save by default for the [verilog
extension](https://github.com/someone13574/zed-verilog-extension), since
there isn't a standard style.

Release Notes:

- N/A
2025-07-16 09:08:16 +03:00
Danilo Leal
1ed3f9eb42 Add user handle and plan chip to the user menu (#34522)
A nicer way to visualize in which plan you're in and a bit of
personalization by adding the GitHub handle you're signed with in the
user menu, as a complement to the avatar photo itself. Taking advantage
of the newly added Chip component.

<img width="320" height="476" alt="CleanShot 2025-07-16 at 1  33 08@2x"
src="https://github.com/user-attachments/assets/36718a42-27d1-499e-ac81-1eef2cd00347"
/>

Release Notes:

- N/A
2025-07-16 01:48:01 -03:00
Danilo Leal
59d524427e ui: Add Chip component (#34521)
Possibly the simplest component in our set, but a nice one to have so we
can standardize how it looks across the app.

Release Notes:

- N/A
2025-07-16 01:15:45 -03:00
Danilo Leal
ee4b9a27a2 ui: Fix wrapping in the banner component (#34516)
Also removing the `icon` field as the banner component always renders
with an icon anyway. Hopefully, this fixes any weird text wrapping that
was happening before.

Release Notes:

- N/A
2025-07-15 23:51:12 -03:00
Peter Tripp
ae65ff95a6 ci: Disable FreeBSD builds (#34511)
Recently FreeBSD zed-remote-server builds are failing 90%+ of the time
for unknown reasons.

Temporarily suspend them.

Example failing builds:
- [2025-07-15 16:15 Nightly
Failure](https://github.com/zed-industries/zed/actions/runs/16302777887/job/46042358675)
- [2025-07-15 12:20 Nightly
Success](https://github.com/zed-industries/zed/actions/runs/16297907892/job/46025281518)
- [2025-07-14 08:21 Nightly
Failure](https://github.com/zed-industries/zed/actions/runs/16266193889/job/45923004940)
- [2025-06-17 Nightly
Failure](https://github.com/zed-industries/zed/actions/runs/15700462603/job/44234573761)

Release Notes:

- Temporarily disable FreeBSD zed-remote-server builds due to CI failures.
2025-07-15 21:24:35 -04:00
Conrad Irwin
fc24102491 Tweaks to ACP for the Gemini PR (#34506)
- **Update to use --experimental-acp**
- **Fix tool locations**

Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: mkorwel <matt.korwel@gmail.com>
Co-authored-by: Agus Zubiaga <agus@zed.dev>
2025-07-15 17:52:50 -06:00
Piotr Osiewicz
7ca3d969e0 debugger: Highlight the size of jumped-to memory (#34504)
Closes #ISSUE

Release Notes:

- N/A
2025-07-15 23:32:48 +00:00
Danilo Leal
afbd2b760f agent: Add plan chip in the Zed section within the settings view (#34503)
| Free | Pro |
|--------|--------|
| <img width="1140" height="368" alt="CleanShot 2025-07-15 at 7  50
48@2x"
src="https://github.com/user-attachments/assets/b54fd46d-d823-4689-b099-0a9aef8b1c9a"
/> | <img width="1136" height="348" alt="CleanShot 2025-07-15 at 7  51
45@2x"
src="https://github.com/user-attachments/assets/d291a1f5-511f-43df-9ce2-041c77d1cb86"
/> |

Release Notes:

- agent: Added a chip communicating which Zed plan you're subscribed to
in the agent panel settings view.
2025-07-15 23:10:44 +00:00
Cole Miller
0a3ef40c2f debugger: Interpret user-specified debug adapter binary paths in a more intuitive way for JS and Python (#33926)
Previously we would append `js-debug/src/dapDebugServer.js` to the value
of the `dap.JavaScript.binary` setting and `src/debugpy/adapter` to the
value of the `dap.Debugpy.binary` setting, which isn't particularly
intuitive. This PR fixes that.

Release Notes:

- debugger: Made the semantics of the `dap.$ADAPTER.binary` setting more
intuitive for the `JavaScript` and `Debugpy` adapters. In the new
semantics, this should be the path to `dapDebugServer.js` for
`JavaScript` and the path to the `src/debugpy/adapter` directory for
`Debugpy`.

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
2025-07-15 22:31:28 +00:00
Cole Miller
0ebbeec11c debugger: Remove Start button from the attach modal (#34496)
Right now it doesn't work at all (the PID doesn't get set in the
generated scenario), and it's sort of redundant with the picker
functionality.

Release Notes:

- N/A
2025-07-15 17:06:46 -04:00
Smit Barmase
0ada4ce900 editor: Add ToggleFocus action (#34495)
This PR adds action `editor: toggle focus` which focuses to last active
editor pane item in workspace.

Release Notes:

- Added `editor: toggle focus` action, which focuses to last active
editor pane item.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-16 01:47:40 +05:30
Anthony Eid
572d3d637a Rename action_input to action_arguments in keybinding contexts (#34480)
Release Notes:

- N/A
2025-07-15 16:06:50 -04:00
Conrad Irwin
3751737621 Add zed://extension/{id} links (#34492)
Release Notes:

- Add zed://extension/{id} links to open the extensions UI with a
specific extension
2025-07-15 13:42:25 -06:00
Umesh Yadav
ec52e9281a Add xAI language model provider (#33593)
Closes #30010

Release Notes:

- Add support for xAI language model provider
2025-07-15 15:35:50 -04:00
Cole Miller
af0031ae8b Fix positioning of terminal inline assist after clearing the screen (#34465)
Closes #33945. Here's my attempt to describe what's going on in that
issue and what this fix is doing:

We always render the terminal inline assistant starting on the line
after the cursor, with a height of 4 lines. When deploying it, we scroll
the viewport to the bottom of the terminal so that the assistant will be
in view.

When scrolling while the assistant is deployed (including in that case),
we need to make an adjustment that "pushes up" the terminal content by
the height of the assistant, so that we can scroll to see all the normal
content plus the assistant itself. That quantity is `scroll_top`, which
represents _how much height in the current viewport is occupied by the
assistant that would otherwise be occupied by terminal content_. So when
you scroll up and a line of the assistant's height goes out of view,
`scroll_top` decreases by 1, etc.

When we scroll to the bottom after deploying the assistant, we set
`scroll_top` to the result of calling `max_scroll_top`, which computes
it this way:

```
block.height.saturating_sub(viewport_lines.saturating_sub(terminal_lines))
```

Which, being interpreted, is "the height of the assistant, minus any
viewport lines that are not occupied by terminal content", i.e. the
assistant is allowed to eat up vertical space below the last line of
terminal content without increasing `scroll_top`.

The problem comes when we clear the screen---this adds a full screen to
`terminal_lines`, but the cursor is positioned at the top of the
viewport with blank lines below, just like at the beginning of a session
when `terminal_lines == 1`. Those blank lines should be available to the
assistant, but the `scroll_top` calculation doesn't reflect that.

I've tried to fix this by basing the `max_scroll_top` calculation on the
position of the cursor instead of the raw `terminal_lines` value. There
was also a special case for `viewport_lines == terminal_lines` that I
think can now be removed.

Release Notes:

- Fixed the positioning of the terminal inline assistant when it's
deployed after clearing the terminal.
2025-07-15 15:16:48 -04:00
Ariel Rzezak
b398935081 Fix comment in default.json (#34481)
Update line to properly reference the intended setting.

Release Notes:

- N/A
2025-07-15 19:07:39 +00:00
Michael Sloan
78b7737368 Remove scap from workspace-hack (#34490)
Regression in #34251 which broke remote_server build

Release Notes:

- N/A
2025-07-15 19:07:01 +00:00
Richard Feldman
57e8f5c5b9 Automatically retry in more situations (#34473)
In #33275 I was very conservative about when to retry when there are
errors in language completions in the Agent panel.

Now we retry in more scenarios (e.g. HTTP 5xx and 4xx errors that aren't
in the specific list of ones that we handle differently, such as 429s),
and also we show a notification if the thread halts for any reason.

<img width="441" height="68" alt="Screenshot 2025-07-15 at 12 51 30 PM"
src="https://github.com/user-attachments/assets/433775d0-a8b2-403d-9427-1e296d164980"
/>
<img width="482" height="322" alt="Screenshot 2025-07-15 at 12 44 15 PM"
src="https://github.com/user-attachments/assets/5a508224-0fe0-4d34-9768-25d95873eab8"
/>


Release Notes:

- Automatic retry for more Agent errors
- Whenever the Agent stops, play a sound (if configured) and show a
notification (if configured) if the Zed window was in the background.
2025-07-15 14:22:13 -04:00
Smit Barmase
729cde33f1 project_panel: Add rename, delete and duplicate actions to workspace (#34478)
Release Notes:

- Added `project panel: rename`, `project panel: delete` and `project
panel: duplicate` actions to workspace.

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-15 23:41:53 +05:30
Ben Kunkle
ebbf02e25b keymap_ui: Keyboard navigation for keybind edit modal (#34482)
Adds keyboard navigation to the keybind edit modal. Using up/down arrows
to select the previous/next input editor, and `cmd-enter` to save +
`escape` to exit

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-15 18:03:19 +00:00
Cole Miller
3ecdfc9b5a Remove auto-width editor type (#34438)
Closes #34044

`EditorMode::SingleLine { auto_width: true }` was only used for the
title editor in the rules library, and following
https://github.com/zed-industries/zed/pull/31994 we can replace that
with a normal single-line editor without problems. The auto-width editor
was interacting badly with the recently-added newline visualization
code, causing a panic during layout---by switching it to
`Editor::single_line` the newline visualization works there too.

Release Notes:

- Fixed a panic that could occur when opening the rules library.

---------

Co-authored-by: Finn <finn@zed.dev>
2025-07-15 17:36:09 +00:00
Anthony Eid
f9561da673 Maintain keymap editor position when deleting or modifying a binding (#34440)
When a key binding is deleted we keep the exact same scroll bar
position. When a keybinding is modified we select that keybinding in
it's new position and scroll to it.

I also changed save/modified keybinding to use fs.write istead of
fs.atomic_write. Atomic write was creating two FS events that some
scrollbar bugs when refreshing the keymap editor.

Co-authored-by: Ben \<ben@zed.dev\>

Release Notes:

- N/A
2025-07-15 17:16:29 +00:00
Finn Evers
b3747d9a21 keymap_ui: Add column for conflict indicator and edit button (#34423)
This PR adds a column to the keymap editor to highlight warnings as well
as add the possibility to click the edit icon there for editing the
corresponding entry in the list.

Release Notes:

- N/A

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-15 12:52:21 -04:00
Ben Kunkle
95de2bfc74 keymap_ui: Limit length of keystroke input and hook up actions (#34464)
Closes #ISSUE

Changes direction on the design of the keystroke input. Due to MacOS
limitations, it was decided that the complex repeat keystroke logic
could be avoided by limiting the number of keystrokes so that accidental
repeats were less damaging to ux. This PR follows up on the design pass
in #34437 that assumed these changes would be made, hooking up actions
and greatly improving the keyboard navigability of the keystroke input.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-15 16:03:16 +00:00
teapo
d7bb1c1d0e lsp: Fix workspace diagnostics lag & add streaming support (#34022)
Closes https://github.com/zed-industries/zed/issues/33980
Closes https://github.com/zed-industries/zed/discussions/33979

- Switches to the debounce task pattern for diagnostic summary
computations, which most importantly lets us do them only once when a
large number of DiagnosticUpdated events are received at once.
- Makes workspace diagnostic requests not time out if a partial result
is received.
- Makes diagnostics from workspace diagnostic partial results get
merged.

There might be some related areas where we're not fully complying with
the LSP spec but they may be outside the scope of what this PR should
include.

Release Notes:

- Added support for streaming LSP workspace diagnostics.
- Fixed editor freeze from large LSP workspace diagnostic responses.
2025-07-15 18:41:45 +03:00
Umesh Yadav
5f3e7a5f91 lsp: Wait for shutdown response before sending exit notification (#33417)
Follow up: #18634

Closes #33328

Release Notes:

- Fixed language server shutdown process to prevent race conditions and
improper termination by waiting for shutdown confirmation before closing
connections.
2025-07-15 18:30:57 +03:00
Taylor Beever
0671a4d5ae Allow for venv activation script to use pyenv (#33119)
Release Notes:

- Allows for configuration and use of `pyenv` as a virtual environment provider
2025-07-15 16:44:40 +02:00
tidely
bd78f2c493 project: Use checked_sub for next/previous in search history (#34408)
Use `checked_sub` instead of checking for bounds manually. Also greatly
simplifies the logic for `next` and `previous`. Removing other manual
bounds checks as well

Release Notes:

- N/A
2025-07-15 16:42:37 +02:00
tidely
d1abba0d33 gpui: Reduce manual shifting & other minor improvements (#34407)
Minor cleanup in gpui.

- Reduce manual shifting by using `u32::to_be_bytes`
- Remove eager `Vec` allocation when listing registered actions
- Remove unnecessary return statements
- Replace manual `if let Some(_)` with `.as_deref_mut()`

Release Notes:

- N/A
2025-07-15 16:39:33 +02:00
tidely
05065985e7 cli: Remove manual std::io::copy implementation (#34409)
Removes a manual implementation of `std::io::copy`. The internal buffer
of `std::io::copy` is also 8 kB and behaves exactly the same. On Linux
`std::io::copy` also has access to some better performing file copying.

Release Notes:

- N/A
2025-07-15 16:37:15 +02:00
Ben Brandt
7ab8f431a7 Update to acp 0.0.9 (#34463)
Release Notes:

- N/A
2025-07-15 14:28:27 +00:00
Hilmar Wiegand
050ed85d71 Add severity argument to GoToDiagnostic actions (#33995)
This PR adds a `severity` argument so severity can be defined when
navigating through diagnostics. This allows keybinds like the following:

```json
{
  "] e": ["editor::GoToDiagnostic", { "severity": "error" }],
  "[ e": ["editor::GoToDiagnostic", { "severity": "error" }]
}
```

I've added test comments and a test. Let me know if there's anything
else you need!

Release Notes:

- Add `severity` argument to `editor::GoToDiagnostic`,
`editor::GoToPreviousDiagnostic`, `project_panel::SelectNextDiagnostic`
and `project_panel::SelectPrevDiagnostic` actions
2025-07-15 14:03:57 +00:00
Danilo Leal
858e176a1c Refine keymap UI design (#34437)
Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <Ben.kunkle@gmail.com>
2025-07-15 13:45:59 +00:00
Marshall Bowers
a65c0b2bff collab: Fix typo in log message (#34455)
This PR fixes a small typo in a log message.

Release Notes:

- N/A
2025-07-15 13:16:49 +00:00
Marshall Bowers
848a86a385 collab: Sync model overages for all active Zed Pro subscriptions (#34452)
Release Notes:

- N/A
2025-07-15 13:01:01 +00:00
Piotr Osiewicz
52f2b32557 extension_cli: Copy over snippet file when bundling extensions (#34450)
Closes #30670

Release Notes:

- Fixed snippets from extensions not working.
2025-07-15 11:07:29 +00:00
Alvaro Parker
8dca4d150e Fix border and minimap flickering on pane split (#33973)
Closes #33972

As noted on
https://github.com/zed-industries/zed/pull/31390#discussion_r2147473526,
when splitting panes and having a border size set for the active pane,
or the minimap visibility configured to the active editor only, zed will
shortly show a flicker of the border or the minimap on the pane that's
being deactivated.

Release Notes:

- Fixed an issue where pane activations would sometimes have a brief
delay, causing a flicker in the process.
2025-07-15 10:47:35 +02:00
Peter Tripp
440beb8a90 Improve Java LSP documentation (#34410)
Remove references to
[ABckh/zed-java-eclipse-jdtls](https://github.com/ABckh/zed-java-eclipse-jdtls)
which hasn't seen a new version in 10 months (2024-10-01).

Release Notes:

- N/A
2025-07-14 18:16:43 -04:00
Peter Tripp
ce63a6ddd8 Exclude .repo folders by default (#34431)
These are used by [Google's `repo`
tool](https://android.googlesource.com/tools/repo) used for Android for
managing hundreds of git subprojects.

Originally reported in:
- https://github.com/zed-industries/zed/issues/34302

Release Notes:

- Add Google Repo `.repo` folders to default `file_scan_exclusions`
2025-07-14 18:16:28 -04:00
Finn Evers
26ba6e7e00 editor: Improve minimap performance (#33067)
This PR aims to improve the minimap performace. This is primarily
achieved by disabling/removing stuff that is not shown in the minimal as
well as by assuring the display map is not updated during minimap
prepaint.

This should already be much better in parts, as the block map as well as
the fold map will be less frequently updated due to the minimap
prepainting (optimally, they should never be, but I think we're not
quite there yet).
For this, I had to remove block rendering support for the minimap, which
is not as bad as it sounds: Practically, we were currently not rendering
most blocks anyway, there were issues due to this (e.g. scrolling any
visible block offscreen in the main editor causes scroll jumps
currently) and in the long run, the minimap will most likely need its
own block map or a different approach anyway. The existing
implementation caused resizes to occur very frequently for practically
no benefit. Can pull this out into a separate PR if requested, most
likely makes the other changes here easier to discuss.

This is WIP as we are still hitting some code path here we definitely
should not be hitting. E.g. there seems to be a rerender roughly every
second if the window is unfocused but visible which does not happen when
the minimap is disabled.

While this primarily focuses on the minimap, it also touches a few other
small parts not related to the minimap where I noticed we were doing too
much stuff during prepaint. Happy for any feedback there aswell.

Putting this up here already so we have a place to discuss the changes
early if needed.

Release Notes:

- Improved performance with the minimap enabled.
- Fixed an issue where interacting with blocks in the editor would
sometimes not properly work with the minimap enabled.
2025-07-15 00:29:27 +03:00
Joseph T. Lyons
363a265051 Add test for running Close Others on an inactive item (#34425)
Adds a test for the changes added in:
https://github.com/zed-industries/zed/pull/34355

Release Notes:

- N/A
2025-07-14 20:24:05 +00:00
Michael Sloan
37e73e3277 Only depend on scap x11 feature when gpui x11 feature is enabled (#34251)
Release Notes:

- N/A
2025-07-14 18:34:33 +00:00
Richard Feldman
32f5132bde Fix contrast adjustment for Powerline separators (#34417)
It turns out Starship is using custom Powerline separators in the
Unicode private reserved character range. This addresses some issues
seen in the comments of #34234

Release Notes:

- Fix automatic contrast adjustment for Powerline separators
2025-07-14 18:18:41 +00:00
Anthony Eid
fd5650d4ed debugger: A support for data breakpoint's on variables (#34391)
Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2025-07-14 17:45:46 +00:00
domi
8b6b039b63 vim: Add missing normal mode binding for signature help overload (#34278)
Closes #ISSUE

related https://github.com/zed-industries/zed/pull/33199
2025-07-14 17:20:19 +00:00
Piotr Osiewicz
4848bd705e docs/debugger: Remove mention of onboarding calls (#34414)
Closes #ISSUE

Release Notes:

- N/A
2025-07-14 17:18:09 +00:00
Conrad Irwin
45d0686129 Remove unused KeycodeSource (#34403)
Release Notes:

- N/A
2025-07-14 11:03:16 -06:00
Marshall Bowers
eca36c502e Route all LLM traffic through cloud.zed.dev (#34404)
This PR makes it so all LLM traffic is routed through `cloud.zed.dev`.

We're already routing `llm.zed.dev` to `cloud.zed.dev` on the server,
but we want to standardize on `cloud.zed.dev` moving forward.

Release Notes:

- N/A
2025-07-14 16:03:19 +00:00
Piotr Osiewicz
6673c7cd4c debugger: Add memory view (#33955)
This is mostly setting up the UI for now; I expect it to be the biggest
chunk of work.

Release Notes:

- debugger: Added memory view

---------

Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
Co-authored-by: Mikayla Maki <mikayla@zed.dev>
2025-07-14 16:32:06 +02:00
Peter Tripp
a2f5c47e2d Add editor::ToggleFoldAll action (#34317)
In multibuffers adds the ability to alt-click to fold/unfold all
excepts. In singleton buffers it adds the ability to toggle back and
forth between `editor::FoldAll` and `editor::UnfoldAll`.

Bind it in your keymap with:

```json
  {
    "context": "Editor && (mode == full || multibuffer)",
    "bindings": {
      "cmd-k cmd-o": "editor::ToggleFoldAll"
    }
  },
```

<img width="253" height="99" alt="Screenshot 2025-07-11 at 17 04 25"
src="https://github.com/user-attachments/assets/94de8275-d2ee-4cf8-a46c-a698ccdb60e3"
/>

Release Notes:

- Add ability to fold all excerpts in a multibuffer (alt-click) and in
singleton buffers `editor::ToggleFoldAll`
2025-07-14 13:23:51 +00:00
Peter Tripp
c6a6db9754 emacs: Fix cmd-f not working in Terminal (#34400)
Release Notes:

- N/A
2025-07-14 13:16:25 +00:00
Brian Donovan
6f9e052edb languages: Add JS/TS generator functions to outline (#34388)
Functions like `function* iterateElements() {}` would not show up in the
editor's navigation outline. With this change, they do.

| **Before** | **After**
|-|-|
|<img width="453" height="280" alt="Screenshot 2025-07-13 at 4 58 22 PM"
src="https://github.com/user-attachments/assets/822f0774-bda2-4855-a6dd-80ba82fffaf3"
/>|<img width="564" height="373" alt="Screenshot 2025-07-13 at 4 58
55 PM"
src="https://github.com/user-attachments/assets/f4f6b84f-cd26-49b7-923b-724860eb18ad"
/>|

Note that I decided to use Zed's agent assistance features to do this PR
as a sort of test run. I don't normally code with an AI assistant, but
figured it might be good in this case since I'm unfamiliar with the
codebase. I must say I was fairly impressed. All the changes in this PR
were done by Claude Sonnet 4, though I have done a manual review to
ensure the changes look sane and tested the changes by running the
re-built `zed` binary with a toy project.

Closes #21631

Release Notes:

- Fixed JS/TS outlines to show generator functions.
2025-07-14 07:26:17 -05:00
Oleksiy Syvokon
2edf85f054 evals: Switch disable_cursor_blinking to determenistic asserts (#34398)
Release Notes:

- N/A
2025-07-14 11:26:15 +00:00
vipex
00ec243771 pane: 'Close others' now closes relative to right-clicked tab (#34355)
Closes #33445

Fixed the "Close others" context menu action to close tabs relative to
the right-clicked tab instead of the currently active tab. Previously,
when right-clicking on an inactive tab and selecting "Close others", it
would keep the active tab open rather than the right-clicked tab.

## Before/After

https://github.com/user-attachments/assets/d76854c3-c490-4a41-8166-309dec26ba8a



## Changes

- Modified `close_inactive_items()` method to accept an optional
`target_item_id` parameter
- Updated context menu handler to pass the right-clicked tab's ID as the
target
- Maintained backward compatibility by defaulting to active tab when no
target is specified
- Updated all existing call sites to pass `None` for the new parameter

Release Notes:

- Fixed: "Close others" context menu action now correctly keeps the
right-clicked tab open instead of the active tab
2025-07-14 14:06:40 +03:00
feeiyu
84124c60db Fix cannot select in terminal when copy_on_select is enabled (#34131)
Closes #33989


![terminal_select](https://github.com/user-attachments/assets/5027d2f2-f2b3-43a4-8262-3c266fdc5256)

Release Notes:

- N/A
2025-07-14 14:04:54 +03:00
Umesh Yadav
cf1ce1beed languages: Fix ESLint diagnostics not getting shown (#33814)
Closes #33442

Release Notes:

- Resolved an issue where the ESLint language server returned an empty
string for the CodeDescription.href field in diagnostics, leading to
missing diagnostics in editor.
2025-07-14 13:48:56 +03:00
Oleksiy Syvokon
e4effa5e01 linux: Fix keycodes mapping on Wayland (#34396)
We are already converting Wayland keycodes to X11's; double conversion
results in a wrong mapping.


Release Notes:

- N/A
2025-07-14 09:44:29 +00:00
Sergei Surovtsev
f50041779d Language independent hotkeys (#34053)
Addresses #10972 
Closes #24950
Closes #24499

Adds _key_en_ to _Keystroke_ that is derived from key's scan code. This
is more lightweight approach than #32529

Currently has been tested on x11 and windows. Mac code hasn't been
implemented yet.

Release Notes:

- linux: When typing non-ASCII keys on Linux we will now also match
keybindings against the QWERTY-equivalent layout. This should allow most
of Zed's builtin shortcuts to work out of the box on most keyboard
layouts. **Breaking change**: If you had been using `keysym` names in
your keyboard shortcut file (`ctrl-cyrillic_yeru`, etc.) you should now
use the QWERTY-equivalent characters instead.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-13 23:00:03 -06:00
Smit Barmase
51df8a17ef project_panel: Do not render a single sticky entry when scrolled all the way to the top (#34389)
Fixes root entry not expanding/collapsing on nightly. Regressed in
https://github.com/zed-industries/zed/pull/34367.

Release Notes:

- N/A
2025-07-14 06:59:45 +05:30
Somtoo Chukwurah
85d12548a1 linux: Add file_finder::Toggle key binding (#34380)
This fixes a bug on linux where repeated presses of p while holding down
the ctrl modifier navigates through options in reverse.

Closes #34379 

The main issue is the default biding of ctrl-p on linux is
menu::SelectPrevious hence in context "context": "FileFinder ||
(FileFinder > Picker > Editor)" it would navigate in reverse

Release Notes:

- Fixed `file_finder::Toggle` on Linux not scrolling forward
2025-07-13 23:35:03 +00:00
Finn Evers
0af7d32b7d keymap_ui: Dismiss context menu less frequently (#34387)
This PR fixes an issue where the context menu in the keymap UI would be
immediately dismissed after being opened when using a trackpad on MacOS.

Right clicking on MacOS almost always fires a scroll event with a delta
of 0 pixels right after (which is not the case when using a mouse). The
fired scroll event caused the context menu to be removed on the next
frame. This change ensures the menu is only removed when a vertical
scroll is actually happening.

Release Notes:

- N/A
2025-07-13 21:41:41 +00:00
Smit Barmase
1cadff9311 project_panel: Fix sticky items horizontal scroll and hover propagation (#34367)
Release Notes:

- Fixed horizontal scrolling not working for sticky items in the Project
Panel.
- Fixed issue where hovering over the last sticky item in the Project
Panel showed a hovered state on the entry behind it.
- Improved behavior when clicking a sticky item in the Project Panel so
it scrolls just enough for the item to no longer be sticky.
2025-07-13 06:14:30 +05:30
Anthony Eid
8f6b9f0d65 debugger: Allow users to shutdown debug sessions while they're booting (#34362)
This solves problems where users couldn't shut down sessions while
locators or build tasks are running.

I renamed `debugger::Session::Mode` enum to `SessionState` to be more
clear when it's referenced in other crates. I also embedded the boot
task that is created in `SessionState::Building` variant. This allows
sessions to shut down all created threads in their boot process in a
clean and idiomatic way.

Finally, I added a method on terminal that allows killing the active
task.

Release Notes:

- Debugger: Allow shutting down debug sessions while they're booting up
2025-07-12 19:16:35 -04:00
Cole Miller
970a1066f5 git: Handle shift-click to stage a range of entries in the panel (#34296)
Release Notes:

- git: shift-click can now be used to stage a range of entries in the
git panel.
2025-07-12 19:04:26 +00:00
Remco Smits
833bc6979a debugger: Fix correctly determine replace range for debug console completions (#33959)
Follow-up #33868

This PR fixes a few issues with determining the completion range for
client‑ and variable‑list completions.

1. Non‑word completions
We previously supported only word characters and _, using their combined
length to compute the start offset. In PHP, however, an expression can
contain `$`, `-`, `>`, `[`, `]`, `(`, and `)`. Because these characters
weren’t treated as word characters, the start offset stopped at them,
even when the preceding character was part of a word.

2. Trailing characters inside the search text
When autocompletion occurred in the middle of the search text, we didn’t
account for trailing characters. As a result, the start offset was off
by the number of characters after the cursor. For example, replacing res
with result in print(res) produced `print(rresult)` because the trailing
`)` wasn’t subtracted from the start offset.

The following completions are correctly covered now:

- **Before** `$aut` -> `$aut$author` **After** `$aut` -> `$author`
- **Before** `$author->na` -> `$author->na$author->name` **After**
`$author->na` -> `$author->name`
- **Before** `$author->books[` -> `$author->books[$author->books[0]`
**After** `$author->books[` -> `$author->books[0]`
- **Before** `print(res)` -> `print(rresult)` **After** `print(res)` ->
`print(result)`

**Before**


https://github.com/user-attachments/assets/b530cf31-8d4d-45e6-9650-18574f14314c


https://github.com/user-attachments/assets/52475b7b-2bf2-4749-98ec-0dc933fcc364

**After**


https://github.com/user-attachments/assets/c065701b-31c9-4e0a-b584-d1daffe3a38c


https://github.com/user-attachments/assets/455ebb3e-632e-4a57-aea8-d214d2992c06

Release Notes:

- Debugger: Fixed autocompletion not always replacing the correct search
text
2025-07-12 14:24:49 -04:00
Cole Miller
a8cc927303 debugger: Improve appearance of session list for JavaScript debugging (#34322)
This PR updates the debugger panel's session list to be more useful in
some cases that are commonly hit when using the JavaScript adapter. We
make two adjustments, which only apply to JavaScript sessions:

- For a child session that's the only child of a root session, we
collapse it with its parent. This imitates what VS Code does in the
"call stack" view for JavaScript sessions.
- When a session has exactly one thread, we label the session with that
thread's name, instead of the session label provided by the DAP. VS Code
also makes this adjustment, which surfaces more useful information when
working with browser sessions.

Closes #33072 

Release Notes:

- debugger: Improved the appearance of JavaScript sessions in the debug
panel's session list.

---------

Co-authored-by: Julia <julia@zed.dev>
Co-authored-by: Remco Smits <djsmits12@gmail.com>
2025-07-12 15:56:05 +00:00
Kirill Bulatov
13ddd5e4cb Return back the guards when goto targets are queried for (#34340)
Closes https://github.com/zed-industries/zed/issues/34310
Follow-up of https://github.com/zed-industries/zed/pull/29359

Release Notes:

- Fixed goto definition not working in remote projects in certain
conditions
2025-07-12 18:27:52 +03:00
Cole Miller
1b6e212eba debugger: Fix endless restarts when connecting to TCP adapters over SSH (#34328)
Closes #34323
Closes #34313

The previous PR #33932 introduced a way to "close" the
`pending_requests` buffer of the `TransportDelegate`, preventing any
more requests from being added. This prevents pending requests from
accumulating without ever being drained during the shutdown sequence;
without it, some of our tests hang at this point (due to using a
single-threaded executor).

The bug occurred because we were closing `pending_requests` whenever we
detected the server side of the transport shut down, and this closed
state stuck around and interfered with the retry logic for SSH+TCP
adapter connections.

This PR fixes the bug by only closing `pending_requests` on session
shutdown, and adds a regression test covering the SSH retry logic.

Release Notes:

- debugger: Fixed a bug causing SSH connections to some adapters
(Python, Go, JavaScript) to fail and restart endlessly.
2025-07-12 11:27:18 -04:00
Danilo Leal
46834d31f1 Refine status bar design (#34324)
Experimenting with a set of standardized icons and polishing spacing a
little bit.

Release Notes:

- N/A
2025-07-12 11:48:19 -03:00
Kirill Bulatov
e070c81687 Remove remaining plugin-related language server adapters (#34334)
Follow-up of https://github.com/zed-industries/zed/pull/34208

Release Notes:

- N/A
2025-07-12 11:42:14 +00:00
Cole Miller
5b61b8c8ed agent: Fix crash with pathological fetch output (#34253)
Closes #34029

The crash is due to a stack overflow in our `html_to_markdown`
conversion; I've added a maximum depth of 200 for the recursion in that
crate to guard against this kind of thing.

Separately, we were treating all content-types other than `text/plain`
and `application/json` as HTML; I've changed this to only treat
`text/html` and `application/xhtml+xml` as HTML, and fall back to
plaintext. (In the original crash, the content-type was
`application/octet-stream`.)

Release Notes:

- agent: Fixed a potential crash when fetching large non-HTML files.
2025-07-11 21:01:09 -04:00
Cole Miller
625ce12a3e Revert "git: Intercept signing prompt from GPG when committing" (#34306)
Reverts zed-industries/zed#34096

This introduced a regression, because the unlocked key can't benefit
from caching.

Release Notes:
- N/A
2025-07-11 23:20:35 +00:00
vipex
12bc8907d9 Recall empty, unsaved buffers on app load (#33475)
Closes #33342

This PR implements serialization of pinned tabs regardless of their
state (empty, untitled, etc.)

The root cause was that empty untitled tabs were being skipped during
serialization but their pinned state was still being persisted, leading
to a mismatch between the stored pinned count and actual restorable
tabs, this issue lead to a crash which was patched by @JosephTLyons, but
this PR aims to be a proper fix.

**Note**: I'm still evaluating the best approach for this fix. Currently
exploring whether it's necessary to store the pinned state in the
database schema or if there's a simpler solution that doesn't require
schema changes.

--- 

**Edit from Joseph**

We ended up going with altering our recall logic, where we always
restore all editors, even those that are new, empty, and unsaved. This
prevents the crash that #33335 patched because we are no longer skipping
the restoration of pinned editors that have no text and haven't been
saved, throwing off the count dealing with the number of pinned items.

This solution is rather simple, but I think it's fine. We simply just
restore everything the same, no conditional dropping of anything. This
is also consistent with VS Code, which also restores all editors,
regardless of whether or not a new, unsaved buffers have content or not.

https://github.com/zed-industries/zed/tree/alt-solution-for-%2333342

Release Notes:
- N/A

---------

Co-authored-by: Joseph T. Lyons <JosephTLyons@gmail.com>
2025-07-11 22:23:04 +00:00
Ben Kunkle
67c765a99a keymap_ui: Dual-phase focus for keystroke input (#34312)
Closes #ISSUE

An idea I and @MrSubidubi came up with, to improve UX around the
keystroke input.

Currently, there's a hard tradeoff with what to focus first in the edit
keybind modal, if we focus the keystroke input, it makes keybind
modification very easy, however, if you don't want to edit a keybind,
you must use the mouse to escape the keystroke input before editing
something else - breaking keyboard navigation.

The idea in this PR is to have a dual-phased focus system for the
keystroke input. There is an outer focus that has some sort of visual
indicator to communicate it is focused (currently a border). While the
outer focus region is focused, keystrokes are not intercepted. Then
there is a keybind (currently hardcoded to `enter`) to enter the inner
focus where keystrokes are intercepted, and which must be exited using
the mouse. When the inner focus region is focused, there is a visual
indicator for the fact it is "recording" (currently a hacked together
red pulsing recording icon)


<details><summary>Video</summary>


https://github.com/user-attachments/assets/490538d0-f092-4df1-a53a-a47d7efe157b


</details>

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-11 17:06:06 -05:00
Ben Kunkle
206cce6783 keymap_ui: Support unbinding non-user defined keybindings (#34318)
Closes #ISSUE

Makes it so that `KeymapFile::update_keybinding` treats removals of
bindings that weren't user-defined as creating a new binding to
`zed::NoAction`.


Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-11 21:23:14 +00:00
Julia Ryan
c3edc2cfc1 DAP log view improvements (#34311)
Now DAP logs show the label of each session which makes it much easier
to pick out the right one.

Also "initialization sequence" now shows up correctly when that view is
selected.

Release Notes:

- N/A

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-11 19:34:53 +00:00
Mikayla Maki
625a4b90a5 Tinker with the reporting of telemetry events (#34239)
Release Notes:

- N/A

---------

Co-authored-by: Katie Geer <katie@zed.dev>
2025-07-11 12:02:40 -07:00
Lukas Spiss
fbead09c30 go: Write envFile properties back to env config (#34300)
Closes https://github.com/zed-industries/zed/issues/32984

Note that while https://github.com/zed-industries/zed/pull/33666 did the
reading of the `envFile` just fine, the read values were never passed
along. This was mentioned by [this
comment](https://github.com/zed-industries/zed/pull/33666#issuecomment-3060785970)
and also confirmed by myself.

With the changes here, I successfully debugged a project of mine and all
the environment variables from my `.env` were present.

Release Notes:

- Fix Go debugger ignoring env vars from the envFile setting.
2025-07-11 18:26:46 +00:00
Ben Kunkle
0797f7b66e keymap_ui: Show existing keystrokes as placeholders in edit modal (#34307)
Closes #ISSUE

Previously, the keystroke input would be empty, even when editing an
existing binding. This meant you had to re-enter the bindings even if
you just wanted to edit the context. Now, the existing keystrokes are
rendered as a placeholder, are re-shown if newly entered keystrokes are
cleared, and will be returned from the `KeystrokeInput::keystrokes()`
method if no new keystrokes were entered.

Additionally fixed a bug in `KeymapFile::update_keybinding` where
semantically identical contexts would be treated as unequal due to
formatting differences.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-11 18:07:04 +00:00
Agus Zubiaga
6f6c2915b2 Display and jump to tool locations (#34304)
Release Notes:

- N/A
2025-07-11 14:52:21 -03:00
Julia Ryan
0bd65829f7 Truncate multi-line debug value hints (#34305)
Release Notes:

- Multi-line debug inline values are now truncated.

Co-authored-by: Anthony Eid <hello@anthonyeid.me>
2025-07-11 17:49:52 +00:00
Finn Evers
90bf602ceb Reduce number of snapshots and notifies during editor scrolling (#34228)
We not do not create new snapshots anymore when autoscrolling
horizontally and also do not notify any longer should the new scroll
position match the old one.

Release Notes:

- N/A

---------

Co-authored-by: Michael Sloan <mgsloan@gmail.com>
2025-07-11 17:34:45 +00:00
localcc
cd024b8870 Add licenses.md for Windows build (#34272)
Release Notes:

- N/A
2025-07-11 19:28:48 +02:00
Finn Evers
af71e15ea0 editor: Fix scrolling stuttering at the top of multibuffers (#34295)
Release Notes:

- Fixed an issue where scrolling would stutter at the top of
multibuffers.
2025-07-11 19:10:39 +02:00
Agus Zubiaga
d0e01dbd8f Improve thread message history (#34299)
- Keep history across threads
- Reset position when edited

Release Notes:

- N/A

---------

Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
2025-07-11 16:24:41 +00:00
Danilo Leal
d65855c4a1 git: Change merge conflict button labels (#34297)
Following feedback that "Take Ours" and "Take Theirs" was confusing,
leading to users not knowing what exactly happened with each of these
buttons. It's now "Use HEAD" and "Use Origin", which also match what is
written in Git markers, helping parse them out more easily. Future
improvement is to have the actual branch target name in the "Use Origin"
button.

Release Notes:

- git: Improved merge conflict buttons clarity by changing labels to
"Use HEAD" and "Use Origin".
2025-07-11 13:15:06 -03:00
Alisina Bahadori
70351360d7 Fix bad kerning in integrated terminal (#34292)
Closes #16869

Release Notes:

- (preview only): Fix bad kerning in integrated terminal.
2025-07-11 09:50:48 -06:00
Conrad Irwin
993e0f55ec ACP follow (#34235)
Closes #ISSUE

Release Notes:

- N/A

---------

Co-authored-by: Agus Zubiaga <agus@zed.dev>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
Co-authored-by: Ben Brandt <benjamin.j.brandt@gmail.com>
2025-07-11 12:38:42 -03:00
Ben Kunkle
496bf0ec43 keymap_ui: Ensure keymap UI opens in local workspace (#34291)
Closes #ISSUE

Use `workspace.with_local_workspace` to ensure the keymap UI is opened
in a local workspace, even in remote. This was tested by removing the
feature flag handling code, as with the feature flag logic the action
does not appear which is likely a bug.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-11 11:32:59 -04:00
morgankrey
c09f484ec4 collab: Add ability to add tax ID during Stripe Checkout (#34246)
### 1. **Added Tax ID Collection Types**
- Created a new `StripeTaxIdCollection` struct with an `enabled` field
- Added `tax_id_collection` field to `StripeCreateCheckoutSessionParams`

### 2. **Updated the Stripe Client Interface**
- Modified the real Stripe client to handle tax ID collection conversion
- Updated the fake Stripe client for testing purposes
- Added proper imports across all affected files

### 3. **Enabled Tax ID Collection in Checkout Sessions**
- Both `checkout_with_zed_pro` and `checkout_with_zed_pro_trial` methods
now enable tax ID collection
- The implementation correctly sets `tax_id_collection.enabled = true`
for all checkout sessions

### 4. **Key Implementation Details**
- Tax ID collection will be shown to new customers and existing
customers without tax IDs
- Collected tax IDs will be automatically saved to the customer's
`tax_ids` array in Stripe
- Business names will be saved to the customer's `name` property
- The existing `customer_update.name = auto` setting ensures
compatibility with tax ID collection

Release Notes:

- N/A
2025-07-11 11:26:36 -04:00
Finn Evers
a58a75c0f6 keymap_ui: Hide tooltips when context menu is shown (#34286)
This PR ensures tooltips are dismissed/not shown once the context menu
is opened.

It also ensures the context menu is dismissed once the list is scrolled.

Release Notes:

- N/A
2025-07-11 15:17:34 +00:00
Ben Kunkle
d1a6c5d494 keymap_ui: Hover tooltip for context (#34290)
Closes #ISSUE

Ideally the tooltip would only appear if the context was overflowing
it's column, but for now, we just unconditionally show a tooltip so that
long contexts can be seen.

This PR also includes a change to the tooltip element, allowing for
tooltips with non-text contents which is used here for syntax
highlighting

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Co-authored-by: Anthony <anthony@zed.dev>
2025-07-11 10:54:08 -04:00
Peter Tripp
10028aaae8 Ensure *.json recognized as JSONC if checkout folder not zed (#34289)
Follow-up to: https://github.com/zed-industries/zed/pull/33410

Release Notes:

- N/A
2025-07-11 14:25:09 +00:00
Ben Kunkle
3b9bb521f4 keymap_ui: Only show conflicts between user bindings (#34284)
Closes #ISSUE

This makes it so conflicts are only shown between user bindings. User
bindings that override bindings in the Vim, Base, and Default keymaps
are not identified as conflicts

Release Notes:

- N/A *or* Added/Fixed/Improved ...

Co-authored-by: Anthony <anthony@zed.dev>
2025-07-11 13:51:21 +00:00
Anthony Eid
7eb739d489 Add initial support for search by keystroke to keybinding editor (#34274)
This PR adds preliminary support for searching keybindings by keystrokes
in the keybinding editor.

Release Notes:

- N/A
2025-07-11 09:29:29 -04:00
localcc
b4cbea50bb Fix icon size on Windows (#34277)
Closes #34122

Release Notes:

- N/A
2025-07-11 15:09:10 +02:00
Smit Barmase
153840199e linux: Use randr as fallback for scale factor in X11 (#34265)
Closes #14537

- Adds server-side scale factor detection via `randr` when client-side
detection fails using `xrdb/Xft.dpi`.
- Adds the `GPUI_X11_SCALE_FACTOR` flag to force a scale factor, which
can be a positive number for custom scaling or `randr` for server-side
scale factor detection.

Release Notes:

- Fixed an issue where the scale factor was not detected correctly on
X11 systems when `Xft.dpi` is not defined (mostly in cases involving
window managers).
2025-07-11 14:52:51 +05:30
张小白
8812e7cd14 windows: Fix an issue where dead keys that require holding shift didn’t work properly (#34264)
Closes #34194

Release Notes:

- N/A
2025-07-11 17:19:23 +08:00
Richard Feldman
56d0ae6782 Don't apply contrast adjustment to decorative chars (#34238)
Closes #34234

Release Notes:

- Automatic contrast adjustment in terminal is no longer applied to
decorative characters used in block art.
2025-07-11 02:48:49 +00:00
Danilo Leal
d52f07b77c lsp tool: Make "Restart All Servers" always visible (#34255)
Next step is to have a "Restart Current Buffer Server(s)". 😬 

Release Notes:

- N/A
2025-07-10 22:00:01 -03:00
Max Frai
089ce8f6aa agent: Allow clicking on the read file tool header to jump to the exact file location (#33161)
Release Notes:

- Allow clicking on the header of the read file tool to jump to the
exact file location

When researching code or when the Agent analyzes context by reading
various project files, the read file tool is used. It usually includes
line numbers relevant to the current prompt or task. However, it’s often
frustrating that the read file header isn’t clickable to view the
corresponding code directly. This PR makes the header clickable,
allowing users to jump to the referenced file. If start and end lines
are specified, it will navigate directly to that exact location.


https://github.com/user-attachments/assets/b0125d0b-7166-43dd-924e-dc5585813b0b

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-11 00:43:52 +00:00
Cole Miller
842ac984d5 git: Intercept signing prompt from GPG when committing (#34096)
Closes #30111 

- [x] basic implementation
- [x] implementation for remote projects
- [x] surface error output from GPG if signing fails
- [ ] ~~Windows~~

Release Notes:

- git: Passphrase prompts from GPG to unlock commit signing keys are now
shown in Zed.
2025-07-11 00:38:51 +00:00
Max Brunsfeld
87362c602f Assign checksum seed in windows releases (#34252)
This will allow windows releases to report panics and telemetry.

Release Notes:

- N/A
2025-07-11 00:09:37 +00:00
Michael Sloan
94916cd3b6 Fix screenshare sources error handling, is_sharing_screen() == false on error (#34250)
Release Notes:

- N/A
2025-07-10 23:35:21 +00:00
Ben Kunkle
7915b9f93f keymap_ui: Add ability to delete user created bindings (#34248)
Closes #ISSUE

Adds an action and special handling in `KeymapFile::update_keybinding`
for removals. If the binding being removed is the last in a keymap
section, the keymap section will be removed entirely instead of left
empty.

Still to do is the ability to unbind/remove non-user created bindings
such as those in the default keymap by binding them to `NoAction`,
however, this will be done in a follow up PR.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-10 23:23:26 +00:00
Max Brunsfeld
33f1ac8b34 Use installed trusted signing (#34245)
Fixes windows nightly build failures

Release Notes:

- N/A
2025-07-10 15:09:31 -07:00
Kirill Bulatov
a1188848ef Make inline and regular diagnostics more related (#34237)
Release Notes:

- N/A
2025-07-10 21:11:49 +00:00
Max Brunsfeld
7588280915 Windows screen sharing (#34223)
Release Notes:

- N/A

---------

Co-authored-by: localcc <work@localcc.cc>
Co-authored-by: Peter Tripp <petertripp@gmail.com>
2025-07-10 14:02:00 -07:00
Peter Tripp
f82fdaa0a4 ci: Skip ci.yml checks for script/update_top_ranking_issues (#34241)
Closes https://github.com/zed-industries/zed/issues/19433
Supercedes: https://github.com/zed-industries/zed/pull/33308

cc: @eshasantosh

Release Notes:

- N/A
2025-07-10 21:01:34 +00:00
Finn Evers
41085f8f55 settings_ui: Inform about keybind conflicts in modal (#34205)
This PR updates the keybinding editor modal so that conflicts are
already shown in the modal itself. Notably, this does not add validation
on every keystroke, the update still has to be confirmed. However, if
only a warning is present, on the second confirm the keybind will
actually be updated.

The change also includes a slight update to the displayment of errors,
since we now differentiate between errors and warnings.

| Error | Warning | 
| --- | --- |
| <img width="543" height="332" alt="warning_keybind"
src="https://github.com/user-attachments/assets/867319be-eeb9-40d7-bf32-fbd44aacf0b5"
/> | <img width="543" height="310" alt="error_keybind"
src="https://github.com/user-attachments/assets/858a6c7c-8c9a-4a90-95af-a5103125676f"
/> |


Release Notes:

- N/A
2025-07-10 15:51:36 -05:00
Julia Ryan
8e1d341d09 nix: Fix CI job (#34231)
Fix regex filter

Release Notes:

- N/A
2025-07-10 20:17:49 +00:00
Danilo Leal
9d2b7c8033 agent: Dismiss the agent panel notification if window is closed (#34230)
Closes https://github.com/zed-industries/zed/issues/32951

Release Notes:

- agent: Fixed an issue where the agent panel notification would linger
on even after you closed the window.
2025-07-10 16:45:17 -03:00
Kirill Bulatov
c6603e4fba Stop extensions' servers and message loops before removing their files (#34208)
Fixes an issue that caused Windows to fail when removing extension's
directories, as Zed had never stop any related processes.

Now:

* Zed shuts down and waits until the end when the language servers are
shut down

* Adds `impl Drop for WasmExtension` where does
`self.tx.close_channel();` to stop a receiver loop that holds the "lock"
on the extension's work dir.
The extension was dropped, but the channel was not closed for some
reason.

* Does more unregistration to ensure `Arc<WasmExtension>` with the `tx`
does not leak further

* Tidies up the related errors which had never reported a problematic
path before

Release Notes:

- N/A

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
Co-authored-by: Smit <smit@zed.dev>
2025-07-10 19:25:10 +00:00
localcc
c549b712fd Just Zed instead of Zed Editor (#34146)
Release Notes:

- N/A
2025-07-10 21:08:43 +02:00
Finn Evers
d6bff274eb settings_ui: Ensure selected keymap entry is properly updated (#34229)
This change ensures that we more reliably deploy the context menu in the
keymap editor as well as highlight the selected row quicker.

Release Notes:

- N/A
2025-07-10 17:49:52 +00:00
Marshall Bowers
cfc9cfa4ab language_models: Refresh the list of models when the LLM token is refreshed (#34222)
This PR makes it so we refresh the list of models whenever the LLM token
is refreshed.

This allows us to add or remove models based on the plan in the new
token.

Release Notes:

- Fixed model list not refreshing when subscribing to Zed Pro.

---------

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2025-07-10 17:05:41 +00:00
Michael Sloan
e2e529bd94 Remove redundant autoscroll_horizontally during editor prepaint (#34218)
* Experimentally `scroll_manager.anchor()` appears to be the same before
and after this 2nd call of `autoscroll_horizontally`

* Nothing these depend on seem to be mutated between the calls (and
since this is prepaint, stuff within editor also shouldn't be mutated)

Release Notes:

- N/A

Co-authored-by: Finn <finn@zed.dev>
2025-07-10 11:03:34 -06:00
Joseph T. Lyons
e6c41b577b Add more admin to seed script (#34220)
Release Notes:

- N/A
2025-07-10 16:54:00 +00:00
localcc
f8f827583d Remove default shell breadcrumbs on windows (#34198)
Release Notes:

- N/A
2025-07-10 18:04:13 +02:00
Nathan Brodin
36c325bc60 docs: Add GitHub Copilot Enterprise configuration example (#33902)
### Context

This PR adds documentation for setting up GitHub Copilot Enterprise as
an edit prediction provider in Zed.
There was previously no documentation for this feature, which was
implemented in [PR
#32296](https://github.com/zed-industries/zed/pull/32296).

This follows up on [my
comment](https://github.com/zed-industries/zed/issues/22901#issuecomment-3034817471)
and the response from the[ Zed
team](https://github.com/zed-industries/zed/issues/22901#issuecomment-3034837282),
which clarified the required settings.

### What’s included

- Documents the `enterprise_uri` setting for Copilot Enterprise in
`edit-prediction.md`.
- Explains how to configure the setting and what to expect from the
sign-in flow.

### Notes

- This is a documentation-only change.
- No code or tests are affected.

Release Notes:

- N/A

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-07-10 15:52:31 +00:00
Marshall Bowers
f4106ad404 collab: Send down new usage limits even when the user does not have any usage (#34217)
This PR fixes an issue where the plan usage limits in Zed would not get
updated immediately after the plan has changed.

Previously we were only sending down the usage—which contains the
limits—if there was a usage record in the database. This would be absent
if the user had just changed their plan.

We now always send down the usage in order to update the limits on the
client side.

Release Notes:

- N/A

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2025-07-10 15:52:19 +00:00
Finn Evers
1583dd2d6f settings_ui: Ensure context menu is properly populated (#34213)
This change fixes a small issue where the right-click context menu would
not be populdated on the first right click in the keymap editor and the
selection of the corresponding entry would be slightly delayed.

Release Notes:

- N/A
2025-07-10 15:15:29 +00:00
Finn Evers
d7fd9245cd settings_ui: Open keybinding editing modal on mouse double click (#34193)
Whilst working on the keymap editor, I regularly find myself
double-clicking an entry just to find that nothing happens besides
selecting the given entry. This feels really unintuitive to me. I
checked back with VSCode and they also open the modal when
double-clicking an entry in the list.

Thus, this PR enables double-clicking an entry in the list to open the
editing modal.

Release Notes:

- N/A
2025-07-10 17:01:36 +02:00
Justin Su
5f21a9bd32 Uncomment default settings values (#34179)
Closes https://github.com/zed-industries/zed/issues/34178

Release Notes:

- N/A

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-07-10 14:41:10 +00:00
Peter Tripp
c30e28179a Preserve agent message editor unsent text (#34150)
Closes https://github.com/zed-industries/zed/issues/33687

Release Notes:

- agent: Preserve unsent chat message text when creating a new thread
2025-07-10 10:35:16 -04:00
Kirill Bulatov
8bc1396a55 Suggest powershell extension (#34211)
Release Notes:

- N/A
2025-07-10 14:34:59 +00:00
Danilo Leal
51c24e2010 Reorder items in the quick action bar (#34203)
Namely, putting the diagnostics items in their own little section,
divider from the other "inline" and minimap/edit prediction items. I
feel like this is an easier to parse organization, even though all the
"inlines" made sense to be somewhat close together.

Release Notes:

- N/A
2025-07-10 12:49:19 +00:00
张小白
3169f06404 windows: Don't show cmd window when remoting (#34187)
Release Notes:

- N/A
2025-07-10 09:19:12 +00:00
张小白
76e52ea374 ci: Improve windows_tests description (#34123)
We're running clippy and tests in our ci

Release Notes:

- N/A
2025-07-09 23:26:48 -04:00
Conrad Irwin
ca0f0cc8d1 vim: Fix panic when scrolling beyond last line (#34172)
cc @dinocosta

Release Notes:

- (preview only) vim: Fix panic when scrolling down at end of file
2025-07-10 01:37:16 +00:00
张小白
a133c1311d windows: Fix ctrl-r showing the control character (#34171)
Release Notes:

- N/A
2025-07-10 01:15:33 +00:00
Agus Zubiaga
08ffd9884a Update to acp 0.0.6 (#34159)
Release Notes:

- N/A

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-09 19:14:29 -06:00
Danilo Leal
dc591fe7c7 Hide unused extension types from the extension UI (#34166)
This PR hides "slash commands" and "indexed docs providers" from the
extensions UI as these are virtually completely unused types of
extensions.

Release Notes:

- N/A
2025-07-09 23:57:35 +00:00
Danilo Leal
95784d53ca agent: Fix edit bar's background color when zoomed in (#34163)
When the panel was zoomed in, the edit bar's background color would have
a different color than the rest of the panel. This PR fixes it by using
the `panel_background` color token.

Release Notes:

- N/A
2025-07-09 23:25:56 +00:00
Ben Kunkle
9b63ba6205 gpui: Add cx.intercept_keystrokes API to intercept keystrokes before action dispatch (#34084)
Closes #ISSUE

`cx.intercept_keystrokes` functions as a sibling API to
`cx.observe_keystrokes`. Under the hood the two API's are basically
identical, however, `cx.observe_keystrokes` runs _after_ all event
dispatch handling (including action dispatch) while
`cx.intercept_keystrokes` runs _before_. This allows for
`cx.stop_propagation()` calls within the `cx.intercept_keystrokes`
callback to prevent action dispatch.

The motivating example usage behind this API is also included in this
PR. It is used as part of a keystroke input component that needs to
intercept keystrokes before action dispatch to display them.

cc: @mikayla-maki 

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-09 22:44:32 +00:00
Danilo Leal
862e733ef5 agent: Make all icons used for tool calls consistent (#34160)
Starting to use the `Tool...` family of icons dedicated & designed for
the agent panel.

Release Notes:

- N/A
2025-07-09 19:28:46 -03:00
Smit Barmase
66dda8e368 editor: Fix block comment with same prefix as line comment incorrectly extending on new line (#34156)
Closes #33930

Release Notes:

- Fixed `--[[` incorrectly extending `--` upon a new line in Lua.
2025-07-10 02:54:05 +05:30
Bennet Bo Fenner
16d02cfdb3 agent: Allow thinking in edit file tool (#34155)
Follow up to #34141. As pointed out by @maan2003 changing the thinking
parameters invalidates the message cache
([Docs](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching#what-invalidates-the-cache)).

All the other places where `thinking_allowed ` is set to `false` should
be fine since we do not do any caching there.

Release Notes:

- N/A
2025-07-09 21:08:32 +00:00
Julia Ryan
2c41e10c98 Add button to view dap logs (#34153)
Release Notes:

- N/A
2025-07-09 20:51:45 +00:00
Danilo Leal
9ab5e78b79 Add some UI adjustments to the keymap editor (#34152)
Mostly simple things like spacing and colors.

Release Notes:

- N/A
2025-07-09 17:11:24 -03:00
Danilo Leal
e30e4381de Add chevron icons to the dropdown menus in the LSP log pane (#34149)
A bunch of dropdown menus in this pane that weren't clear that were
menus without chevrons in it. :)

<img
src="https://github.com/user-attachments/assets/fc701a5d-ed89-4de3-a76e-06d22ad9e366"
width="600"/>

Release Notes:

- N/A
2025-07-09 16:33:07 -03:00
Steve Hillier
de627ba04d git_ui: Support "Open Pull Request" for more platforms (#33833)
Hello! It would be great to be able to use the "Open Pull Request"
button that appears after pushing a branch via the git UI on more
platforms (I use Gitlab day to day). Would you be open to adding more
variations of the PR hint text?

I've added the text that Gitlab and Bitbucket use in their push logs
here.

Release Notes:

- Git UI: Support "Open Pull Request" for more platforms
2025-07-09 19:09:59 +00:00
Danilo Leal
80eed63255 agent: Add menu in the plus icon button for creating a new thread (#34143)
Release Notes:

- N/A

---------

Co-authored-by: Agus Zubiaga <agus@zed.dev>
2025-07-09 15:44:45 -03:00
Danilo Leal
974bc4096a agent: Don't always render the markdown/scroll buttons (#34145)
Release Notes:

- N/A

Co-authored-by: Agus Zubiaga <agus@zed.dev>
2025-07-09 15:44:39 -03:00
Max Brunsfeld
642d8bb8f5 Don't upload windows installer to preview releases for now (#34147)
Release Notes:

- N/A
2025-07-09 11:31:11 -07:00
Bennet Bo Fenner
41fe2a2ab4 agent: Disable thinking when using inline assistant/edit file tool (#34141)
This introduces a new field `thinking_allowed` on `LanguageModelRequest`
which lets us control whether thinking should be enabled if the model
supports it.
We permit thinking in the Inline Assistant, Edit File tool and the Git
Commit message generator, this should make generation faster when using
a thinking model, e.g. `claude-sonnet-4-thinking`

Release Notes:

- N/A
2025-07-09 18:05:39 +00:00
Richard Feldman
96ff6d86a3 Fix autocomplete on settings.json after reload (#34142)
Closes #31850


https://github.com/user-attachments/assets/6182ef64-3ce6-49ed-a91b-770c51cb6e94

Release Notes:

- Fixed autocomplete on settings.json after restarting Zed
2025-07-09 13:43:17 -04:00
localcc
6e5763215f Simplify installer by removing a couple pages (#34144)
Release Notes:

- N/A
2025-07-09 19:41:41 +02:00
localcc
de0e6f716c Fix inno dir (#34116)
Fix inno dir for nightly builds

Release Notes:

- N/A
2025-07-09 19:03:53 +02:00
Anthony Eid
93bfae71dc Show conflicts in the keymap editor (#34137)
This PR shows conflicts in a user's keymap editor by adding an error
background to a conflicting row and allows users to filter the keymap
editor by conflicts.

A key binding is determined to have a conflict if any other binding has
the same context and key strokes. In the future, this could be further
improved upon by normalizing bindings’ context so it's not just a string
comparison.


Release Notes:

- N/A

---------

Co-authored-by: MrSubidubi <dev@bahn.sh>
2025-07-09 16:56:33 +00:00
Ben Kunkle
171be7e009 keymap_ui: Render <no arguments> for bindings that take arguments where none are provided (#34140)
Closes #ISSUE

Adds a visual indicator to the `Arguments` column of the keymap table to
help distinguish between actions that don't take arguments, and actions
that take arguments but none were provided.

Currently, the `<no arguments>` indicator is rendered only in the latter
case, when no arguments are provided to an action that could take
arguments, as the inverse results in almost every row containing the
indicator which is quite noisy.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-09 16:48:35 +00:00
Smit Barmase
d5cc1cbaa9 title_bar: Add setting to always show menu for Linux and Windows (#34139)
Closes #22869

Release Notes:

- Added `show_menus` setting to always show menu bar for Linux and
Windows.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-07-09 09:44:11 -07:00
Ben Kunkle
6d26f107dd keymap_ui: Creating keybinds (#34138)
Adds support for creating new keybinds in the keymap UI. "Create" means
two different things for existing bindings, and unbound actions.
- For existing bindings, it is essentially a duplicate + edit
- For unbound actions, it is the creation of a binding

Release Notes:

- N/A
2025-07-09 16:24:33 +00:00
Kristian Gosvig
e2b9dfa89c editor: Add CollapseAllDiffHunks docs (#34124)
## Summary

This PR improves the documentation for diff hunk keyboard shortcuts to
make existing functionality more discoverable to users.

### Problem

Users were unaware that pressing **ESC** already collapses all expanded
diff hunks through the existing `Cancel` action. The functionality
exists but lacks discoverability:

- The `Cancel` action description was too generic: "Cancels the current
operation"
- No documentation existed for diff hunk keyboard shortcuts in the Git
docs
- Users would naturally expect a dedicated keybinding for collapsing
diff hunks

Release Notes:

- N/A
2025-07-09 16:10:35 +00:00
Conrad Irwin
495ec7a109 ACP (#34030)
Implements an ACP client that can be used from the agent panel
2025-07-09 16:02:31 +00:00
Oleksiy Syvokon
b9b42bee99 evals: Fix bug that prevented multiple turns from displaying (#34128)
Release Notes:

- N/A
2025-07-09 15:31:58 +00:00
Peter Tripp
a9b82e1e57 Bump Zed to v0.196 (#34127)
Release Notes:

- N/A
2025-07-09 11:04:13 -04:00
Smit Barmase
81cc1e8f75 project_panel: Improve last sticky item drifting logic (#34119)
- Now instead of drifting directory along with last item of that
directory, it waits till last item is completely consumed.

Release Notes:

- N/A
2025-07-09 20:26:21 +05:30
Bennet Bo Fenner
7114a5ca99 Fix panic in context server configuration (#34118)
Release Notes:

- Fixed a panic that could occur when configuring MCP servers
2025-07-09 16:39:02 +02:00
Kirill Bulatov
45d200f2f8 Wrap back around in context menu properly (#34112)
When navigating back in the context menu, it was not possible to get
past first element, if it was not selectable.
The other way around works, hence the fix.

Release Notes:

- N/A
2025-07-09 11:44:29 +00:00
Daniel Sauble
1569b662ff editor: Change drag_and_drop_selection cursor on delay elapsed + Add drag_and_drop_selection delay setting (#33928)
When [`drag_and_drop_selection` is
true](https://zed.dev/docs/configuring-zed#drag-and-drop-selection),
users can make a selection in the buffer and then drag and drop it to a
new location. However, the editor forces users to wait 300ms after mouse
down before dragging. If users try to drag before this delay has
elapsed, they will create a new text selection instead, which can create
the impression that drag and drop does not work.

I made two changes to improve the UX of this feature:

* If users do not want a delay before drag and drop is enabled, they can
set the `drag_and_drop_selection.delay_ms` setting to 0.
* If the user has done a mouse down on a text selection, the cursor
changes to a copy affordance as soon as the configured delay has
elapsed, rather than waiting for them to start dragging. This way they
don't need to guess at when the delay has elapsed.

The default settings for this feature are now:

```
"drag_and_drop_selection": {
  "enabled": true,
  "delay_ms": 300
}
```

Closes #33915 

Before:


https://github.com/user-attachments/assets/7b2f986f-9c67-4b2b-a10e-757c3e9c934b

After:


https://github.com/user-attachments/assets/726d0dbf-e58b-41ad-93d2-1a758640b422

Release Notes:

- Migrate `drag_and_drop_selection` setting to
`drag_and_drop_selection.enabled`.
- Add `drag_and_drop_selection.delay_ms` setting to configure the delay
that must elapse before drag and drop is allowed.
- Show a ready to drag cursor affordance as soon as the delay has
elapsed

---------

Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2025-07-09 12:38:23 +05:30
Conrad Irwin
4ed206b37c vim: Implement /n and /c in :s (#34102)
Closes #23345

Release Notes:

- vim: Support /n and /c in :s//
2025-07-09 06:14:04 +00:00
Conrad Irwin
6daf888fdb More Tips'n'tricks (#34103)
Document one way to avoid pathological cargo cache problems.

Release Notes:

- N/A
2025-07-09 00:05:46 -06:00
AidanV
acff48fc0d vim: Add :sp[lit] <filename> and :vs[plit] <filename> support (#33686)
Closes #32627

Release Notes:

- Adds `:sp[lit] <filename>` and `:vs[plit] <filename>` support
2025-07-08 23:43:43 -06:00
Joel Courtney
ecf4d5539e helix: Stay in helix normal mode after helix delete (#34093)
Currently, the HelixDelete action switches to (vim) Normal mode instead
of HelixNormal mode. This adds a line to the helix delete action to stay
in helix normal mode.

There was already a commented-out test for this. I've uncommented it and
it now passes.

Release Notes:

- helix: Fixed switching to vim NORMAL mode instead of HELIX_NORMAL mode
after deletion
2025-07-08 21:34:20 -06:00
Conrad Irwin
8e8a772c2d vim: Add U to undo last line (#33571)
Closes #14760

Still TODO:

* Vim actually undoes *many* changes if they're all on the same line.

Release Notes:

- vim: Add `U` to return to the last changed line and undo
2025-07-08 21:24:43 -06:00
张小白
df57754baf windows: Publish nightly (#24800)
The installer, uninstaller, and the Zed binary files are all signed
using Microsoft’s newly launched Trusted Signing service. For
demonstration purposes, I have used my own account for the signing
process.

For more information about Trusted Signing, you can refer to the
following links:
- [Microsoft Security Blog: Trusted Signing is in Public
Preview](https://techcommunity.microsoft.com/blog/microsoft-security-blog/trusted-signing-is-in-public-preview/4103457)
- [Overview of Azure Trusted
Signing](https://learn.microsoft.com/en-us/azure/trusted-signing/overview)

**TODO:**

- [x] `InnoSetup` script to setup an installer
- [x] Signing process
- [x] `Open with Zed` in right click context menu (by using sparse
package)
- [x] Integrate with `cli`
  - [x] Implement `cli` (#25412)
  - [x] Pack `cli.exe` into installer
- [x] Implement auto updating (#25734)
  - [x] Pack autoupdater helper into installer
- [x] Implement dock menus
  - [x] Add `Recent Documents` entries (#26369)
  - [x] Make `zed.exe` aware of sigle instance (#25412)
  - [x] Properly handle dock menu events (#26010)
- [x] Handle `zed://***` uri

**Materials needed:**

- [ ] Icons
  - [ ] App icon for all channels (#9571)
- [ ] Associated file icons, at minimum a default icon
([example](https://github.com/microsoft/vscode/tree/main/resources/win32))
  - [ ] Logos for installer wizard
  - [ ] Icons for appx
- [x] Code signing
- [x] Secrets: AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET,
ACCOUNT_NAME, CERT_PROFILE_NAME
- [x] Other constants: ENDPOINT, Identity Signature (i.e. `CN=Junkui
Zhang, O=Junkui Zhang, L=Wuhan, S=Hubei, C=CN`)





![屏幕截图 2025-02-13
205132](https://github.com/user-attachments/assets/925ec5b2-c8f4-4f0e-8666-26e30278eb3d)



https://github.com/user-attachments/assets/4f1092b4-90fc-4a47-a868-8f2f1a5d8ad8



Release Notes:

- N/A

---------

Co-authored-by: Kate <kate@zed.dev>
Co-authored-by: localcc <work@localcc.cc>
Co-authored-by: Peter Tripp <peter@zed.dev>
Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
2025-07-09 08:57:03 +08:00
Smit Barmase
3a247ee947 project panel: Add indent guides for sticky items (#34092)
- Adds new trait `StickyItemsDecoration` in `sticky_items` which is
implemented by `IndentGuides` from `indent_guides`.

<img width="347" alt="image"
src="https://github.com/user-attachments/assets/577748bc-13f6-41b8-9266-6a0b72349a18"
/>

Release Notes:

- N/A
2025-07-09 05:28:25 +05:30
Danilo Leal
ad8b823555 Improve the LSP popover menu design (#34081)
- Add a slightly different bolt icon SVG so it sits better when with an
indicator
- Attempt to clarify what happens when clicking any of the menu items
- Add descriptions to the tooltips to clarify what each indicator color
means
- Add section titles to clarify in which category each menu item is
sitting on

Release Notes:

- N/A
2025-07-08 19:51:24 -03:00
Dino
139af02737 vim: Fix and improve horizontal scrolling (#33590)
This Pull Request introduces various changes to the editor's horizontal
scrolling, mostly focused on vim mode's horizontal scroll motions (`z
l`, `z h`, `z shift-l`, `z shift-h`). In order to make it easier to
review, the logical changes have been split into different sections.

## Cursor Position Update

Changes introduced on https://github.com/zed-industries/zed/pull/32558
added both `z l` and `z h` to vim mode but it only scrolled the editor's
content, without changing the cursor position. This doesn't reflect the
actual behavior of those motions in vim, so these two commits tackled
that, ensuring that the cursor position is updated, only when the cursor
is on the left or right edges of the editor:

-
ea3b866a76
-
805f41a913

## Horizontal Autoscroll Fix

After introducing the cursor position update to both `z l` and `z h` it
was noted that there was a bug with using `z l`, followed by `0` and
then `z l` again, as on the second use `z l` the cursor would not be
updated. This would only happen on the first line in the editor, and it
was concluded that it was because the
`editor::scroll::autoscroll::Editor.autoscroll_horizontally` method was
directly updating the scroll manager's anchor offset, instead of using
the `editor::scroll::Editor.set_scroll_position_internal` method, like
is being done by the vertical autoscroll
(`editor::scroll::autoscroll::Editor.autoscroll_vertically`).

This wouldn't update the scroll manager's anchor, which would still
think it was at `(0, 1)` so the cursor position would not be updated.
The changes in [this
commit](3957f02e18)
updated the horizontal autoscrolling method to also leverage
`set_scroll_position_internal`.

## Visible Column Count & Page Width Scroll Amount

The changes in
d83652c3ae
add a `visible_column_count` field to `editor::scroll::ScrollManager`
struct, which allowed the introduction of the `ScrollAmount::PageWidth`
enum.

With these changes, two new actions are introduced,
`vim::normal::scroll::HalfPageRight` and
`vim::normal::scroll::HalfPageLeft` (in
7f344304d5),
which move the editor half page to the right and half page to the left,
as well as the cursor position, which have also been mapped to `z
shift-l` and `z shift-h`, respectively.

Closes #17219 

Release Notes:

- Improved `z l` and `z h` to actually move the cursor position, similar
to vim's behavior
- Added `z shift-l` and `z shift-h` to scroll half of the page width's
to the right or to the left, respectively

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-08 14:48:48 -06:00
Ben Kunkle
6b7c30d7ad keymap_ui: Editor for action input in modal (#34080)
Closes #ISSUE

Adds a very simple editor for editing action input to the edit keybind
modal. No auto-complete yet.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-08 14:39:55 -05:00
Marshall Bowers
1220049089 Add feature flag to use cloud.zed.dev instead of llm.zed.dev (#34076)
This PR adds a new `zed-cloud` feature flag that can be used to send
traffic to `cloud.zed.dev` instead of `llm.zed.dev`.

This is just so Zed staff can test the new infrastructure. When we're
ready for prime-time we'll reroute traffic on the server.

Release Notes:

- N/A
2025-07-08 18:44:51 +00:00
Julia Ryan
01bdef130b nix: Fix generate-licenses failure (#34072)
We should maybe add `generate-licenses` to the sensitivity list for
running nix in CI given that nix uses a workaround for it.

Release Notes:

- N/A
2025-07-08 18:05:11 +00:00
Peter Tripp
9a3720edd3 Disable word completions by default for plaintext/markdown (#34065)
This disables word based completions in Plain Text and Markdown buffers
by default.

Word-based completion when typing natural language can be quite
disruptive, in particular at the end of a line (e.g. markdown style
lists) where `enter` will accept word completions rather than insert a
newline (see screenshot). I think the default, empty buffer experience
in Zed should be closer to a zed-mode experience -- just an editor
getting out of your way to let you type and not having to mash
escape/cmd-z repeatedly to undo a over-aggressive completion.

<img width="265" alt="Screenshot 2025-07-08 at 11 57 26"
src="https://github.com/user-attachments/assets/131f73a8-4687-45bf-ad53-f611c0af9387"
/>

- Context:
https://github.com/zed-industries/zed/issues/4957#issuecomment-3049513501
- Follow-up to: https://github.com/zed-industries/zed/pull/26410

Re-enable the existing behavior with:
```json
  "languages": {
    "Plain Text": { "completions": { "words": "fallback" } },
    "Markdown": { "completions": { "words": "fallback" } },
  },
```
Or disable Word based completions everywhere with:
```json
  "completions": { 
    "words": "fallback"
  },
```

Release Notes:

- Disable word-completions by default in Plain Text and Markdown Buffers
2025-07-08 17:49:54 +00:00
fantacell
11ddecb995 helix: Change keymap (#33925)
Might close #33838 for now

Keymaps that work both in vim and helix, but only in normal mode, not
the more general `VimControl` context are written separately. This makes
the file shorter by combining them and also adds one more keymap.

Release Notes:

- N/A
2025-07-08 11:47:39 -06:00
Peter Tripp
684e14e55b Move Perplexity extension to dedicated repository (#34070)
Move Perplexity extension to:
https://github.com/zed-extensions/perplexity

Release Notes:

- N/A
2025-07-08 13:40:00 -04:00
Gwen Lg
263080c4c4 Allow local build of remote_server dev to be deployed to different linux than local (#33395)
setup local build of `remote_server` to not depend of the local linux
libraries by :
- enable `vendored-libgit2` feature of git2
- setup target triple to `unknown-linux-musl` (mirror bundle-linux
script)
- add flag ` -C target-feature=+crt-static` in `RUSTFLAGS` env var
(mirror bundle-linux script)

Bonus:
Add an option to setup mold as linker of local build.

Closes #33341

Release Notes:

 - N/A
2025-07-08 16:31:20 +00:00
Alisina Bahadori
925464cfc6 Improve terminal rendering performance (#33345)
Closes #18263

Improvements:

• **Batch text rendering** - Combine adjacent cells with identical
styling into single text runs to reduce draw calls
• **Throttle hyperlink searches** - Limit hyperlink detection to every
100ms or when mouse moves >5px to reduce CPU usage
• **Pre-allocate collections** - Use `Vec::with_capacity()` for cells,
runs, and regions to minimize reallocations
• **Optimize background regions** - Merge adjacent background rectangles
to reduce number of draw operations
• **Cache selection text** - Only compute terminal selection string when
selection exists

Release Notes:

- Improved terminal rendering performance.

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-08 09:05:01 -06:00
Anthony Eid
bcac748c2b Add support for Nushell in shell builder (#33806)
We also swap out env variables before sending them to shells now in the
task system. This fixed issues Fish and Nushell had where an empty
argument could be sent into a command when no argument should be sent.
This only happened from task's generated by Zed.

Closes #31297 #31240

Release Notes:

- Fix bug where spawning a Zed generated task or debug session with Fish
or Nushell failed
2025-07-08 14:57:37 +00:00
张小白
0ca0914cca windows: Add support for SSH (#29145)
Closes #19892

This PR builds on top of #20587 and improves upon it.

Release Notes:

- N/A

---------

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2025-07-08 14:34:57 +00:00
Danilo Leal
8bd739d869 git panel: Add some design refinements (#34064)
Things like borders, border colors, which icons are being used, button
sizes, and spacing. There is more to do here: polish that we're using a
bunch of divs for spacing, arbitrary pixel values for tokens we have in
the system, etc. This is just a quick pass!

Release Notes:

- git panel: Polished the panel spacing, border colors, and icons.
2025-07-08 11:23:36 -03:00
Joseph T. Lyons
60e9ab8f93 Delete access tokens on user delete (#34036)
Trying to delete a user record from our admin panel throws the following
error:

`update or delete on table "users" violates foreign key constraint
"access_tokens_user_id_fkey" on table "access_tokens"
Detail: Key (id)=(....) is still referenced from table "access_tokens".`

We need to add a cascade delete to the `access_tokens` table.

Release Notes:

- N/A
2025-07-08 10:08:17 -04:00
Danilo Leal
3327f90e0f agent: Add setting to control terminal card expanded state (#34061)
Similar to https://github.com/zed-industries/zed/pull/34040, this PR
allows to control via settings whether the terminal card in the agent
panel should be expanded. It is set to true by default.

Release Notes:

- agent: Added a setting to control whether terminal cards are expanded
in the agent panel, thus showing or hiding the full command output.
2025-07-08 10:43:35 -03:00
curiouslad
5e15c05a9d editor: Fix diagnostic popovers not being scrollable (#33581)
Closes #32673

Release Notes:

- Fixed diagnostic popovers not being scrollable
2025-07-08 16:14:22 +03:00
Smit Barmase
1f3575ad6e project_panel: Only show sticky item shadow when list is scrolled (#34050)
Follow up: https://github.com/zed-industries/zed/pull/34042

- Removes `top_slot_items` from `uniform_list` in favor of using
existing `decorations`
- Add condition to only show shadow for sticky item when list is
scrolled and scrollable

Release Notes:

- N/A
2025-07-08 14:22:24 +05:30
Danilo Leal
f1db3b4e1d agent: Add setting to control edit card expanded state (#34040)
This PR adds the `expand_edit_card` setting, which controls whether edit
cards in the agent panel are expanded, thus showing or not the full diff
of a given file's AI-driven change. I personally prefer to have these
cards collapsed by default as I am mostly reviewing diffs using either
the review multibuffer or the diffs within the file's buffer itself.
Didn't want to change the default behavior as that was intentionally
chosen, so here we are! :)

Open to feedback about the setting name; I've iterated between a few
options and don't necessarily feel like the current one is the best.

Release Notes:

- agent: Added a setting to control whether edit cards are expanded in
the agent panel, thus showing or hiding the full diff of a file's
changes.
2025-07-08 01:19:09 -03:00
Danilo Leal
02d0e725a8 agent: Allow clicking on the whole edit file row to trigger review (#34041)
Just a small quality-of-life type of PR that makes clicking anywhere
until the "Review" button trigger the action that that button triggers
(i.e., opens the review multibuffer).

<img
src="https://github.com/user-attachments/assets/8936ed75-50fd-49f9-89ef-b6c4301a8eba"
width="600" />

Release Notes:

- agent: Added the ability to click the whole file row in the edits bar
to trigger the review multibuffer.
2025-07-08 01:19:00 -03:00
Danilo Leal
211d6205b9 project panel: Add a shadow in the last sticky item (#34042)
Follow-up to https://github.com/zed-industries/zed/pull/33994. This PR
adds a subtle shadow—built from an absolute-positioned div, due to
layering of items—to the last sticky item in the project panel when that
setting is turned on. This helps understand the block of items that is
currently sticky.

<img
src="https://github.com/user-attachments/assets/0e030e93-9bc6-42ff-8d0d-3e46f1986152"
width="300"/>

Would love to add indent guides to the items that are sticky as a next
step.

Release Notes:

- project panel: When `sticky_scroll` is true, the last item will now
have a subtle shadow to help visualizing the block of items that are
currently sticky.
2025-07-08 01:18:52 -03:00
Piotr Osiewicz
4693f16759 debugger: Remove PHP debug adapter (#34020)
This commit removes the PHP debug adapter in favor of a new version
(0.3.0) of PHP extension.
The name of a debug adapter has been changed from "PHP" to "Xdebug",
which makes this a breaking change in user-configured scenarios

Release Notes:

- debugger: PHP debug adapter is no longer shipped in core Zed editor;
it is now available in PHP extension (starting with version 0.3.0). The
adapter has been renamed from `PHP` to `Xdebug`, which might break your
user-defined debug scenarios.
2025-07-08 01:36:32 +02:00
Piotr Osiewicz
c0dc758f24 debugger: Rely on LocalDapCommand in more places (#34035)
- **debugger: Move cacheable property onto LocalDapCommand**
- **debugger/session: Relax method bounds to use LocalDapCommand**


Release Notes:

- N/A
2025-07-07 23:05:37 +00:00
Richard Feldman
9b7632d5f6 Automatically adjust ANSI color contrast (#34033)
Closes #33253 in a way that doesn't regress #32175 - namely,
automatically adjusts the contrast between the foreground and background
text in the terminal such that it's above a certain threshold. The
threshold is configurable in settings, and can be set to 0 to turn off
this feature and use exactly the colors the theme specifies even if they
are illegible.

## One Light Theme Before
<img width="220" alt="Screenshot 2025-07-07 at 6 00 47 PM"
src="https://github.com/user-attachments/assets/096754a6-f79f-4fea-a86e-cb7b8ff45d60"
/>

(Last row is highlighted because otherwise the text is unreadable; the
foreground and background are the same color.)

## One Light Theme After

(This is with the new default contrast adjustment setting.)

<img width="215" alt="Screenshot 2025-07-07 at 6 22 02 PM"
src="https://github.com/user-attachments/assets/b082fefe-76f5-4231-b704-ff387983a3cb"
/>

This approach was inspired by @mitchellh's use of automatic contrast
adjustment in [Ghostty](https://ghostty.org/) - thanks, Mitchell! The
main difference is that we're using APCA's formula instead of WCAG for
[these
reasons](https://khan-tw.medium.com/wcag2-are-you-still-using-it-ui-contrast-visibility-standard-readability-contrast-f34eb73e89ee).

Release Notes:

- Added automatic dynamic contrast adjustment for terminal foreground
and background colors
2025-07-07 22:39:11 +00:00
Ben Kunkle
877ef5e1b1 keymap_ui: Add auto-complete for context in keybind editor (#34031)
Closes #ISSUE

Implements a very basic completion provider that is attached to the
context editor in the keybind editing modal.

The context identifiers used for completions are scraped from the
default, vim, and base keymaps on demand.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-07 21:54:51 +00:00
Bennet Bo Fenner
66a1c356bf agent: Fix max token count mismatch when not using burn mode (#34025)
Closes #31854

Release Notes:

- agent: Fixed an issue where the maximum token count would be displayed
incorrectly when burn mode was not being used.
2025-07-07 23:13:24 +02:00
Julia Ryan
a9107dfaeb Edit debug tasks (#32908)
Release Notes:

- Added the ability to edit LSP provided debug tasks

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-07 14:04:21 -07:00
Oleksiy Syvokon
d549993c73 tools: Send stale file notifications only once (#34026)
Previously, we sent notifications repeatedly until the agent read a
file, which was often inefficient. With this change, we now send a
notification only once (unless the files are modified again, in which
case we'll send another notification).

Release Notes:

- N/A
2025-07-07 22:30:01 +03:00
Cole Miller
e0c860c42a debugger: Fix issues with restarting sessions (#33932)
Restarting sessions was broken in #33273 when we moved away from calling
`kill` in the shutdown sequence. This PR re-adds that `kill` call so
that old debug adapter processes will be cleaned up when sessions are
restarted within Zed. This doesn't re-introduce the issue that motivated
the original changes to the shutdown sequence, because we still send
Disconnect/Terminate to debug adapters when quitting Zed without killing
the process directly.

We also now remove manually-restarted sessions eagerly from the session
list.

Closes #33916 

Release Notes:

- debugger: Fixed not being able to restart sessions for Debugpy and
other adapters that communicate over TCP.
- debugger: Fixed debug adapter processes not being cleaned up.

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
2025-07-07 18:28:59 +00:00
Peter Tripp
2a6ef006f4 Make script/generate-license fail on WARN too (#34008)
Current main shows this on `script/generate-licenses`:
```
[WARN] failed to validate all files specified in clarification for crate ring 0.17.14: checksum mismatch, expected '76b39f9b371688eac9d8323f96ee80b3aef5ecbc2217f25377bd4e4a615296a9'
```

Ring fixed it's licenses ambiguity upstream. This warning was
identifying that their license text (multiple licenses concatenated) had
changed (sha mismatch) and thus our license clarification was invalid.

Tested the script to confirm this [now
fails](https://github.com/zed-industries/zed/actions/runs/16118890720/job/45479355992?pr=34008)
under CI and then removed the ring clarification because it is no longer
required and now passes.

Release Notes:

- N/A
2025-07-07 13:56:53 -04:00
Smit Barmase
38febed02d languages: Fix detents case line after typing : in Python (#34017)
Closes #34002

`decrease_indent_patterns` should only contain mapping which are at same
indent level with each other, which is not true for `match` and `case`
mapping.

Caused in https://github.com/zed-industries/zed/pull/33370

Release Notes:

- N/A
2025-07-07 22:41:29 +05:30
Alex Povel
8cc3b094d2 editor: Add action to sort lines by length (#33622)
This change introduces a new `Action` implementation to sort lines by
their `char`
length. It reuses the same calculation as used for getting the caret
column position,
i.e. `TextSummary`. The motivation is to e.g. handle source code where
this sort of
order matters
([example](fdf537c3d3/tests/readme.rs (L529-L535))).

Tested manually via `cargo build && ./target/debug/zed .`: the new
action shows up in the command palette, and testing it on `.mailmap`
entries turns those from

```text
Agus Zubiaga <agus@zed.dev>
Agus Zubiaga <agus@zed.dev> <hi@aguz.me>
Alex Viscreanu <alexviscreanu@gmail.com>
Alex Viscreanu <alexviscreanu@gmail.com> <alexandru.viscreanu@kiwi.com>
Alexander Mankuta <alex@pointless.one>
Alexander Mankuta <alex@pointless.one> <alex+github@pointless.one>
amtoaer <amtoaer@gmail.com>
amtoaer <amtoaer@gmail.com> <amtoaer@outlook.com>
Andrei Zvonimir Crnković <andrei@0x7f.dev>
Andrei Zvonimir Crnković <andrei@0x7f.dev> <andreicek@0x7f.dev>
Angelk90 <angelo.k90@hotmail.it>
Angelk90 <angelo.k90@hotmail.it> <20476002+Angelk90@users.noreply.github.com>
Antonio Scandurra <me@as-cii.com>
Antonio Scandurra <me@as-cii.com> <antonio@zed.dev>
Ben Kunkle <ben@zed.dev>
Ben Kunkle <ben@zed.dev> <ben.kunkle@gmail.com>
Bennet Bo Fenner <bennet@zed.dev>
Bennet Bo Fenner <bennet@zed.dev> <53836821+bennetbo@users.noreply.github.com>
Bennet Bo Fenner <bennet@zed.dev> <bennetbo@gmx.de>
Boris Cherny <boris@anthropic.com>
Boris Cherny <boris@anthropic.com> <boris@performancejs.com>
Brian Tan <brian.tan88@gmail.com>
Chris Hayes <chris+git@hayes.software>
Christian Bergschneider <christian.bergschneider@gmx.de>
Christian Bergschneider <christian.bergschneider@gmx.de> <magiclake@gmx.de>
Conrad Irwin <conrad@zed.dev>
Conrad Irwin <conrad@zed.dev> <conrad.irwin@gmail.com>
Dairon Medina <dairon.medina@gmail.com>
Danilo Leal <danilo@zed.dev>
Danilo Leal <danilo@zed.dev> <67129314+danilo-leal@users.noreply.github.com>
Edwin Aronsson <75266237+4teapo@users.noreply.github.com>
Elvis Pranskevichus <elvis@geldata.com>
Elvis Pranskevichus <elvis@geldata.com> <elvis@magic.io>
Evren Sen <nervenes@icloud.com>
Evren Sen <nervenes@icloud.com> <146845123+evrensen467@users.noreply.github.com>
Evren Sen <nervenes@icloud.com> <146845123+evrsen@users.noreply.github.com>
Fernando Tagawa <tagawafernando@gmail.com>
Fernando Tagawa <tagawafernando@gmail.com> <fernando.tagawa.gamail.com@gmail.com>
Finn Evers <dev@bahn.sh>
Finn Evers <dev@bahn.sh> <75036051+MrSubidubi@users.noreply.github.com>
Finn Evers <dev@bahn.sh> <finn.evers@outlook.de>
Gowtham K <73059450+dovakin0007@users.noreply.github.com>
Greg Morenz <greg-morenz@droid.cafe>
Greg Morenz <greg-morenz@droid.cafe> <morenzg@gmail.com>
Ihnat Aŭtuška <autushka.ihnat@gmail.com>
Ivan Žužak <izuzak@gmail.com>
Ivan Žužak <izuzak@gmail.com> <ivan.zuzak@github.com>
Joseph T. Lyons <JosephTLyons@gmail.com>
Joseph T. Lyons <JosephTLyons@gmail.com> <JosephTLyons@users.noreply.github.com>
Julia <floc@unpromptedtirade.com>
Julia <floc@unpromptedtirade.com> <30666851+ForLoveOfCats@users.noreply.github.com>
Kaylee Simmons <kay@the-simmons.net>
Kaylee Simmons <kay@the-simmons.net> <kay@zed.dev>
Kaylee Simmons <kay@the-simmons.net> <keith@the-simmons.net>
Kaylee Simmons <kay@the-simmons.net> <keith@zed.dev>
Kirill Bulatov <kirill@zed.dev>
Kirill Bulatov <kirill@zed.dev> <mail4score@gmail.com>
Kyle Caverly <kylebcaverly@gmail.com>
Kyle Caverly <kylebcaverly@gmail.com> <kyle@zed.dev>
Lilith Iris <itslirissama@gmail.com>
Lilith Iris <itslirissama@gmail.com> <83819417+Irilith@users.noreply.github.com>
LoganDark <contact@logandark.mozmail.com>
LoganDark <contact@logandark.mozmail.com> <git@logandark.mozmail.com>
LoganDark <contact@logandark.mozmail.com> <github@logandark.mozmail.com>
Marko Kungla <marko.kungla@gmail.com>
Marko Kungla <marko.kungla@gmail.com> <marko@mkungla.dev>
Marshall Bowers <git@maxdeviant.com>
Marshall Bowers <git@maxdeviant.com> <elliott.codes@gmail.com>
Marshall Bowers <git@maxdeviant.com> <marshall@zed.dev>
Matt Fellenz <matt@felle.nz>
Matt Fellenz <matt@felle.nz> <matt+github@felle.nz>
Max Brunsfeld <maxbrunsfeld@gmail.com>
Max Brunsfeld <maxbrunsfeld@gmail.com> <max@zed.dev>
Max Linke <maxlinke88@gmail.com>
Max Linke <maxlinke88@gmail.com> <kain88-de@users.noreply.github.com>
Michael Sloan <michael@zed.dev>
Michael Sloan <michael@zed.dev> <mgsloan@gmail.com>
Michael Sloan <michael@zed.dev> <mgsloan@google.com>
Mikayla Maki <mikayla@zed.dev>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@gmail.com>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@icloud.com>
Morgan Krey <morgan@zed.dev>
Muhammad Talal Anwar <mail@talal.io>
Muhammad Talal Anwar <mail@talal.io> <talalanwar@outlook.com>
Nate Butler <iamnbutler@gmail.com>
Nate Butler <iamnbutler@gmail.com> <nate@zed.dev>
Nathan Sobo <nathan@zed.dev>
Nathan Sobo <nathan@zed.dev> <nathan@warp.dev>
Nathan Sobo <nathan@zed.dev> <nathansobo@gmail.com>
Nigel Jose <nigelmjose@gmail.com>
Nigel Jose <nigelmjose@gmail.com> <nigel.jose@student.manchester.ac.uk>
Peter Tripp <peter@zed.dev>
Peter Tripp <peter@zed.dev> <petertripp@gmail.com>
Petros Amoiridis <petros@hey.com>
Petros Amoiridis <petros@hey.com> <petros@zed.dev>
Piotr Osiewicz <piotr@zed.dev>
Piotr Osiewicz <piotr@zed.dev> <24362066+osiewicz@users.noreply.github.com>
Pocæus <github@pocaeus.com>
Pocæus <github@pocaeus.com> <pseudomata@proton.me>
Rashid Almheiri <r.muhairi@pm.me>
Rashid Almheiri <r.muhairi@pm.me> <69181766+huwaireb@users.noreply.github.com>
Richard Feldman <oss@rtfeldman.com>
Richard Feldman <oss@rtfeldman.com> <richard@zed.dev>
Robert Clover <git@clo4.net>
Robert Clover <git@clo4.net> <robert@clover.gdn>
Roy Williams <roy.williams.iii@gmail.com>
Roy Williams <roy.williams.iii@gmail.com> <roy@anthropic.com>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev> <sebastijan.kelneric@vichava.com>
Sergey Onufrienko <sergey@onufrienko.com>
Shish <webmaster@shishnet.org>
Shish <webmaster@shishnet.org> <shish@shishnet.org>
Smit Barmase <0xtimsb@gmail.com>
Smit Barmase <0xtimsb@gmail.com> <smit@zed.dev>
Thomas <github.thomaub@gmail.com>
Thomas <github.thomaub@gmail.com> <thomas.aubry94@gmail.com>
Thomas <github.thomaub@gmail.com> <thomas.aubry@paylead.fr>
Thomas Heartman <thomasheartman+github@gmail.com>
Thomas Heartman <thomasheartman+github@gmail.com> <thomas@getunleash.io>
Thomas Mickley-Doyle <tmickleydoyle@gmail.com>
Thomas Mickley-Doyle <tmickleydoyle@gmail.com> <thomas@zed.dev>
Thorben Kröger <dev@thorben.net>
Thorben Kröger <dev@thorben.net> <thorben.kroeger@hexagon.com>
Thorsten Ball <mrnugget@gmail.com>
Thorsten Ball <mrnugget@gmail.com> <me@thorstenball.com>
Thorsten Ball <mrnugget@gmail.com> <thorsten@zed.dev>
Tristan Hume <tris.hume@gmail.com>
Tristan Hume <tris.hume@gmail.com> <tristan@anthropic.com>
Uladzislau Kaminski <i@uladkaminski.com>
Uladzislau Kaminski <i@uladkaminski.com> <uladzislau_kaminski@epam.com>
Vitaly Slobodin <vitaliy.slobodin@gmail.com>
Vitaly Slobodin <vitaliy.slobodin@gmail.com> <vitaly_slobodin@fastmail.com>
Will Bradley <williambbradley@gmail.com>
Will Bradley <williambbradley@gmail.com> <will@zed.dev>
WindSoilder <WindSoilder@outlook.com>
张小白 <364772080@qq.com>
````

into

```text
张小白 <364772080@qq.com>
Ben Kunkle <ben@zed.dev>
Finn Evers <dev@bahn.sh>
Agus Zubiaga <agus@zed.dev>
amtoaer <amtoaer@gmail.com>
Peter Tripp <peter@zed.dev>
Pocæus <github@pocaeus.com>
Danilo Leal <danilo@zed.dev>
Matt Fellenz <matt@felle.nz>
Morgan Krey <morgan@zed.dev>
Nathan Sobo <nathan@zed.dev>
Robert Clover <git@clo4.net>
Conrad Irwin <conrad@zed.dev>
Ivan Žužak <izuzak@gmail.com>
Mikayla Maki <mikayla@zed.dev>
Piotr Osiewicz <piotr@zed.dev>
Shish <webmaster@shishnet.org>
Evren Sen <nervenes@icloud.com>
Kirill Bulatov <kirill@zed.dev>
Michael Sloan <michael@zed.dev>
Angelk90 <angelo.k90@hotmail.it>
Max Linke <maxlinke88@gmail.com>
Smit Barmase <0xtimsb@gmail.com>
Thorben Kröger <dev@thorben.net>
Antonio Scandurra <me@as-cii.com>
Bennet Bo Fenner <bennet@zed.dev>
Brian Tan <brian.tan88@gmail.com>
Julia <floc@unpromptedtirade.com>
Nigel Jose <nigelmjose@gmail.com>
Petros Amoiridis <petros@hey.com>
Rashid Almheiri <r.muhairi@pm.me>
Thomas <github.thomaub@gmail.com>
Boris Cherny <boris@anthropic.com>
Nate Butler <iamnbutler@gmail.com>
Thorsten Ball <mrnugget@gmail.com>
Tristan Hume <tris.hume@gmail.com>
Richard Feldman <oss@rtfeldman.com>
Greg Morenz <greg-morenz@droid.cafe>
Kaylee Simmons <kay@the-simmons.net>
Lilith Iris <itslirissama@gmail.com>
Marshall Bowers <git@maxdeviant.com>
Muhammad Talal Anwar <mail@talal.io>
Kyle Caverly <kylebcaverly@gmail.com>
Marko Kungla <marko.kungla@gmail.com>
WindSoilder <WindSoilder@outlook.com>
Alexander Mankuta <alex@pointless.one>
Chris Hayes <chris+git@hayes.software>
Max Brunsfeld <maxbrunsfeld@gmail.com>
Dairon Medina <dairon.medina@gmail.com>
Elvis Pranskevichus <elvis@geldata.com>
Agus Zubiaga <agus@zed.dev> <hi@aguz.me>
Alex Viscreanu <alexviscreanu@gmail.com>
Ihnat Aŭtuška <autushka.ihnat@gmail.com>
Joseph T. Lyons <JosephTLyons@gmail.com>
Uladzislau Kaminski <i@uladkaminski.com>
Will Bradley <williambbradley@gmail.com>
LoganDark <contact@logandark.mozmail.com>
Roy Williams <roy.williams.iii@gmail.com>
Sergey Onufrienko <sergey@onufrienko.com>
Andrei Zvonimir Crnković <andrei@0x7f.dev>
Fernando Tagawa <tagawafernando@gmail.com>
Vitaly Slobodin <vitaliy.slobodin@gmail.com>
Nathan Sobo <nathan@zed.dev> <nathan@warp.dev>
Thomas Mickley-Doyle <tmickleydoyle@gmail.com>
Ben Kunkle <ben@zed.dev> <ben.kunkle@gmail.com>
Smit Barmase <0xtimsb@gmail.com> <smit@zed.dev>
Finn Evers <dev@bahn.sh> <finn.evers@outlook.de>
Robert Clover <git@clo4.net> <robert@clover.gdn>
amtoaer <amtoaer@gmail.com> <amtoaer@outlook.com>
Nate Butler <iamnbutler@gmail.com> <nate@zed.dev>
Thomas Heartman <thomasheartman+github@gmail.com>
Kaylee Simmons <kay@the-simmons.net> <kay@zed.dev>
Peter Tripp <peter@zed.dev> <petertripp@gmail.com>
Petros Amoiridis <petros@hey.com> <petros@zed.dev>
Pocæus <github@pocaeus.com> <pseudomata@proton.me>
Antonio Scandurra <me@as-cii.com> <antonio@zed.dev>
Bennet Bo Fenner <bennet@zed.dev> <bennetbo@gmx.de>
Matt Fellenz <matt@felle.nz> <matt+github@felle.nz>
Michael Sloan <michael@zed.dev> <mgsloan@gmail.com>
Nathan Sobo <nathan@zed.dev> <nathansobo@gmail.com>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev>
Shish <webmaster@shishnet.org> <shish@shishnet.org>
Kaylee Simmons <kay@the-simmons.net> <keith@zed.dev>
Kyle Caverly <kylebcaverly@gmail.com> <kyle@zed.dev>
Max Brunsfeld <maxbrunsfeld@gmail.com> <max@zed.dev>
Michael Sloan <michael@zed.dev> <mgsloan@google.com>
Ivan Žužak <izuzak@gmail.com> <ivan.zuzak@github.com>
Richard Feldman <oss@rtfeldman.com> <richard@zed.dev>
Thorsten Ball <mrnugget@gmail.com> <thorsten@zed.dev>
Conrad Irwin <conrad@zed.dev> <conrad.irwin@gmail.com>
Kirill Bulatov <kirill@zed.dev> <mail4score@gmail.com>
Marshall Bowers <git@maxdeviant.com> <marshall@zed.dev>
Will Bradley <williambbradley@gmail.com> <will@zed.dev>
Christian Bergschneider <christian.bergschneider@gmx.de>
Elvis Pranskevichus <elvis@geldata.com> <elvis@magic.io>
Greg Morenz <greg-morenz@droid.cafe> <morenzg@gmail.com>
Thorsten Ball <mrnugget@gmail.com> <me@thorstenball.com>
Edwin Aronsson <75266237+4teapo@users.noreply.github.com>
Gowtham K <73059450+dovakin0007@users.noreply.github.com>
Marko Kungla <marko.kungla@gmail.com> <marko@mkungla.dev>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@gmail.com>
Mikayla Maki <mikayla@zed.dev> <mikayla.c.maki@icloud.com>
Tristan Hume <tris.hume@gmail.com> <tristan@anthropic.com>
Thomas <github.thomaub@gmail.com> <thomas.aubry@paylead.fr>
Boris Cherny <boris@anthropic.com> <boris@performancejs.com>
Kaylee Simmons <kay@the-simmons.net> <keith@the-simmons.net>
Thomas <github.thomaub@gmail.com> <thomas.aubry94@gmail.com>
Muhammad Talal Anwar <mail@talal.io> <talalanwar@outlook.com>
Roy Williams <roy.williams.iii@gmail.com> <roy@anthropic.com>
Marshall Bowers <git@maxdeviant.com> <elliott.codes@gmail.com>
Thorben Kröger <dev@thorben.net> <thorben.kroeger@hexagon.com>
Andrei Zvonimir Crnković <andrei@0x7f.dev> <andreicek@0x7f.dev>
Thomas Mickley-Doyle <tmickleydoyle@gmail.com> <thomas@zed.dev>
Alexander Mankuta <alex@pointless.one> <alex+github@pointless.one>
LoganDark <contact@logandark.mozmail.com> <git@logandark.mozmail.com>
Max Linke <maxlinke88@gmail.com> <kain88-de@users.noreply.github.com>
Alex Viscreanu <alexviscreanu@gmail.com> <alexandru.viscreanu@kiwi.com>
Finn Evers <dev@bahn.sh> <75036051+MrSubidubi@users.noreply.github.com>
Nigel Jose <nigelmjose@gmail.com> <nigel.jose@student.manchester.ac.uk>
Uladzislau Kaminski <i@uladkaminski.com> <uladzislau_kaminski@epam.com>
LoganDark <contact@logandark.mozmail.com> <github@logandark.mozmail.com>
Thomas Heartman <thomasheartman+github@gmail.com> <thomas@getunleash.io>
Christian Bergschneider <christian.bergschneider@gmx.de> <magiclake@gmx.de>
Evren Sen <nervenes@icloud.com> <146845123+evrsen@users.noreply.github.com>
Piotr Osiewicz <piotr@zed.dev> <24362066+osiewicz@users.noreply.github.com>
Vitaly Slobodin <vitaliy.slobodin@gmail.com> <vitaly_slobodin@fastmail.com>
Danilo Leal <danilo@zed.dev> <67129314+danilo-leal@users.noreply.github.com>
Angelk90 <angelo.k90@hotmail.it> <20476002+Angelk90@users.noreply.github.com>
Bennet Bo Fenner <bennet@zed.dev> <53836821+bennetbo@users.noreply.github.com>
Rashid Almheiri <r.muhairi@pm.me> <69181766+huwaireb@users.noreply.github.com>
Evren Sen <nervenes@icloud.com> <146845123+evrensen467@users.noreply.github.com>
Joseph T. Lyons <JosephTLyons@gmail.com> <JosephTLyons@users.noreply.github.com>
Lilith Iris <itslirissama@gmail.com> <83819417+Irilith@users.noreply.github.com>
Fernando Tagawa <tagawafernando@gmail.com> <fernando.tagawa.gamail.com@gmail.com>
Julia <floc@unpromptedtirade.com> <30666851+ForLoveOfCats@users.noreply.github.com>
Sebastijan Kelnerič <sebastijan.kelneric@sebba.dev> <sebastijan.kelneric@vichava.com>
```

which looks good. There's a bit of Unicode in there -- though no
grapheme clusters.
Column number calculations do not seem to handle grapheme clusters
either (?) so I
thought this is OK.

Open questions are:

- should this be added to vim mode as well?
- is `TextSummary` the way to go here? Is it perhaps too expensive? (it
seems fine -- manually counting `char`s seems more brittle -- this way
it will stay in sync with column number calculations)

---

Team, I realize you [ask for a discussion to be opened
first](86161aa427/CONTRIBUTING.md (L32)),
so apologies for not doing that!

It turned out hacking on Zed was much easier than expected (it's really
nice!), and this change is small, adding a variation to an existing
feature. Hope that's fine.

Release Notes:

- Added feature to sort lines by their length

---------

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-07-07 11:02:35 -06:00
Oleksiy Syvokon
d87603dd60 agent: Send stale file notifications using the project_notifications tool (#34005)
This commit introduces the `project_notifications` tool, which
proactively pushes notifications to the agent.

Unlike other tools, `Thread` automatically invokes this tool on every
turn, even when the LLM doesn't ask for it. When notifications are
available, the tool use and results are inserted into the thread,
simulating an LLM tool call.

As with other tools, users can disable `project_notifications` in
Profiles if they do not want them.

Currently, the tool only notifies users about stale files: that is,
files that have been edited by the user while the agent is also working
on them. In the future, notifications may be expanded to include
compiler diagnostics, long-running processes, and more.

Release Notes:

- Added `project_notifications` tool
2025-07-07 19:48:18 +03:00
Ben Kunkle
de9053c7ca keymap_ui: Add ability to edit context (#34019)
Closes #ISSUE

Adds a context input to the keybind edit modal. Also fixes some bugs in
the keymap update function to handle context changes gracefully. The
current keybind update strategy implemented in this PR is
* when the context doesn't change, just update the binding in place
* when the context changes, but the binding is the only binding in the
keymap section, update the binding _and_ context in place
* when the context changes, and the binding is _not_ the only binding in
the keymap section, remove the existing binding and create a new section
with the update context and binding so as to avoid impacting other
bindings

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-07 16:44:19 +00:00
Hilmar Wiegand
ddf3d99265 Add g-w rewrap keybind for vim visual mode (#33853)
There are both `g q` and `g w` keybinds for rewrapping in normal mode,
but `g w` is missing in visual mode. This PR adds that keybind.

Release Notes:

- Add `g w` rewrap keybind for vim visual mode
2025-07-07 10:18:55 -06:00
Richard Feldman
c35af6c2e2 Fix panic with Helix mode changing case (#34016)
Closes #33750

Release Notes:

- Fixed a panic when trying to change case in Helix mode
2025-07-07 15:51:45 +00:00
Piotr Osiewicz
6cb382c49f debugger: Make exception breakpoints persistent (#34014)
Closes #33053
Release Notes:

- Exception breakpoint state is now persisted across debugging sessions.
2025-07-07 17:40:14 +02:00
Oleksiy Syvokon
966e75b610 tools: Ensure properties always exists in JSON Schema (#34015)
OpenAI API requires `properties` to be present, even if it's empty.

Release Notes:

- N/A
2025-07-07 15:34:14 +00:00
Peter Tripp
861ca05fb9 Support loading environment from plan9 rc shell (#33599)
Closes: https://github.com/zed-industries/zed/issues/33511

Add support for loading environment from Plan9 shell
Document esoteric shell behavior.
Remove two useless tests.

Follow-up to: 
- https://github.com/zed-industries/zed/pull/32702
- https://github.com/zed-industries/zed/pull/32637

Release Notes:

- Add support for loading environment variables from Plan9 `rc` shell.
2025-07-07 10:56:38 -04:00
Peter Tripp
f785853239 ssh: Fix incorrect handling of ssh paths that exist locally (#33743)
- Closes: https://github.com/zed-industries/zed/issues/33733

I also tested that remote canonicalization of symlink directories still
works. (e.g. `zed ssh://hostname/~/foo` where `foo -> foobar` will open
`~/foobar` on the remote).

I believe this has been broken since 2024-10-11 from
https://github.com/zed-industries/zed/pull/19057. CC: @SomeoneToIgnore.
I guess I'm the only person silly enough to run `zed
ssh://hostname/tmp`.

Release Notes:

- ssh: Fixed an issue where Zed incorrectly canonicalized paths locally
prior to connecting to the ssh remote.
2025-07-07 10:55:37 -04:00
Kirill Bulatov
82aee6bcf7 Another lsp tool UI migration (#34009)
https://github.com/user-attachments/assets/54182f0d-43e9-4482-89b9-94db5ddaabf8

Release Notes:

- N/A
2025-07-07 14:28:18 +00:00
Cole Miller
955580dae6 Adjust Go outline query for method definition to avoid pesky whitespace (#33971)
Closes #33951 

There's an adjustment that kicks in to extend `name_ranges` when we
capture more than one `@name` for an outline `@item`. That was happening
here because we captured both the parameter name for the method receiver
and the name of the method as `@name`. It seems like only the second one
should have that annotation.

Release Notes:

- Fixed extraneous leading space in `$ZED_SYMBOL` when used with Go
methods.
2025-07-07 09:51:30 -04:00
张小白
c99e42a3d6 windows: Properly handle surrogates (#34006)
Closes #33791

Surrogate pairs are now handled correctly, so input from tools like
`WinCompose` is properly received.

Release Notes:

- N/A
2025-07-07 20:21:48 +08:00
Bennet Bo Fenner
018dbfba09 agent: Show line numbers of symbols when using @symbol (#34004)
Closes #ISSUE

Release Notes:

- N/A
2025-07-07 10:53:59 +00:00
Umesh Yadav
30a441b714 agent_ui: Fix disabled context servers not showing in agent setting (#33856)
Previously if I set enabled: false for one the context servers in
settings.json it will not show up in the settings in agent panel when I
start zed. But if I enabled it from settings it properly showed up. We
were filtering the configuration to only get the enabled context servers
from settings.json. This PR adds fetching all of them.

Release Notes:

- agent: Show context servers which are disabled in settings in agent
panel settings.
2025-07-07 12:02:33 +02:00
Liam
83562fca77 copilot: Indicate whether a request is initiated by an agent to Copilot API (#33895)
Per [GitHub's documentation for VSCode's agent
mode](https://docs.github.com/en/copilot/how-tos/chat/asking-github-copilot-questions-in-your-ide#agent-mode),
a premium request is charged per user-submitted prompt. rather than per
individual request the agent makes to an LLM. This PR matches Zed's
functionality to VSCode's, accurately indicating to GitHub's API whether
a given request is initiated by the user or by an agent, allowing a user
to be metered only for prompts they send.

See also: #31068

Release Notes:

- Improve Copilot premium request tracking
2025-07-07 10:24:17 +02:00
Smit Barmase
6b456ede49 languages: Fix string override to match just string_fragment part of template_string (#33997)
Closes #33703

`template_string` consists of `template_substitution` and
`string_fragment` chunks. `template_substitution` should not be
considered a string.

```ts
const variable = `this is a string_fragment but ${this.is.template_substitution}`;
```

Release Notes:

- Fixed auto-complete not showing on typing `.` character in template
literal string in JavaScript and TypeScript files.
2025-07-07 11:45:54 +05:30
Smit Barmase
6efc5ecefe project_panel: Add Sticky Scroll (#33994)
Closes #7243

- Adds `top_slot_items` to `uniform_list` component to offset list
items.
- Adds `ToPosition` scroll strategy to `uniform_list` to scroll list to
specified index.
- Adds `sticky_items` component which can be used along with
`uniform_list` to add sticky functionality to any view that implements
uniform list.


https://github.com/user-attachments/assets/eb508fa4-167e-4595-911b-52651537284c

Release Notes:

- Added sticky scroll to the project panel, which keeps parent
directories visible while scrolling. This feature is enabled by default.
To disable it, toggle `sticky_scroll` in settings.
2025-07-07 08:32:42 +05:30
feeiyu
2246b01c4b Allow remote loading for DAP-only extensions (#33981)
Closes #ISSUE


![image](https://github.com/user-attachments/assets/8e1766e4-5d89-4263-875d-ad0dff5c55c2)


Release Notes:

- Allow remote loading for DAP-only extensions
2025-07-06 14:52:16 +02:00
Remco Smits
01295aa687 debugger: Fix the JavaScript debug terminal scenario (#33924)
There were a couple of things preventing this from working:

- our hack to stop the node REPL from appearing broke in recent versions
of the JS DAP that started passing `--experimental-network-inspection`
by default
- we had lost the ability to create a debug terminal without specifying
a program

This PR fixes those issues. We also fixed environment variables from the
**runInTerminal** request not getting passed to the spawned program.

Release Notes:

- Debugger: Fix RunInTerminal not working for JavaScript debugger.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-05 19:48:55 -04:00
Remco Smits
66e45818af debugger: Improve debug console autocompletions (#33868)
Partially fixes:
https://github.com/zed-industries/zed/discussions/33777#discussioncomment-13646294

### Improves debug console autocompletion behavior

This PR fixes a regression in completion trigger support for the debug
console, as we only looked if a completion trigger, was in the beginning
of the search text, but we also had to check if the current text is a
word so we also show completions for variables/input that doesn't start
with any of the completion triggers.

We now also leverage DAP provided information to sort completion items
more effectively. This results in improved prioritization, showing
variable completions above classes and global scope types.

I also added for completion the documentation field, that directly comes
from the DAP server. NOTE: I haven't found an adapter that returns this,
but it needs to have.

**Before**
<img width="1200" alt="Screenshot 2025-07-03 at 21 00 19"
src="https://github.com/user-attachments/assets/611e8d38-e302-4995-a425-ce2c0a1843d4"
/>

**After**
<img width="1200" alt="Screenshot 2025-07-03 at 20 59 38"
src="https://github.com/user-attachments/assets/ab1312db-bbad-49b7-872d-712d6ec708d7"
/>

Release Notes:

- Debugger: Improve autocompletion sorting for debug console
- Debugger: Fix autocompletion menu now shown when you type
- Debugger: Fix completion item showing up twice for some adapters
2025-07-05 16:20:41 +02:00
Smit Barmase
76fe33245f project_panel: Fix indent guide collapse on secondary click for multiple worktrees (#33939)
Release Notes:

- Fixed issue where `cmd`/`ctrl` click on indent guide would not
collapse directory in case of multiple projects.
2025-07-05 05:57:37 +05:30
Alvaro Parker
44d1f512f8 Use /usr/bin/env to run bash restart script (#33936)
Closes #33935

Release Notes:

- Use `/usr/bin/env` to launch the bash restart script
2025-07-05 00:27:21 +00:00
abhimanyu maurya
69fd23e947 Fix path parsing for goto syntax provided by Haskell language server (#33697)
path parsing for multiline errors provided by haskell language server
where not working correctly

<img width="875" alt="image"
src="https://github.com/user-attachments/assets/967d2e03-e167-4055-9c8e-31531cca1471"
/>

while its being parsed correctly in vscode

<img width="934" alt="image"
src="https://github.com/user-attachments/assets/a881cf0e-f06e-4b44-8363-6295bcc825fd"
/>

Release Notes:

- Fixed path parsing paths in the format of the Haskell language server
2025-07-05 02:54:43 +03:00
Vitaly Slobodin
4ad47fc9cc emmet: Enable in HTML/ERB files (#33865)
Closes [#133](https://github.com/zed-extensions/ruby/issues/133)

This PR enables the Emmet LS in `HTML/ERB` files that we added in the
https://github.com/zed-extensions/ruby/pull/113. Let me know if I picked
the right approach here.

Thanks!

Release Notes:

- N/A
2025-07-05 02:51:25 +03:00
Vitaly Slobodin
0555bbd0ec ruby: Document how to use erb-formatter for ERB files (#33872)
Hi! This is a small pull request that adds a new section about
configuring the `erb-formatter` for formatting ERB files. Thanks.

Release Notes:

- N/A
2025-07-05 02:50:51 +03:00
Jacob Duba
d3da0a809e Update documentation for tailwindcss language server now that HTML/ERB is it's own file. (#33684)
Hello,

Recently my tailwind auto completion broke in ERB files. I noticed that
HTML/ERB is it's own file type now. It used to be ERB. This broke the
previous tailwindcss ERB configuration. I made the attached change to my
configuration and it works now.
2025-07-05 02:50:09 +03:00
xdBronch
31ec7ef2ec Debugger: check for supports_single_thread_execution_requests in continue (#33937)
i found this to break my ability to continue with an lldb fork i use

Release Notes:

- N/A
2025-07-04 22:26:20 +00:00
Ryan Hawkins
75928f4859 Sync extension debuggers to remote host (#33876)
Closes #33835

Release Notes:

- Fixed debugger extensions not working in remote projects.
2025-07-04 23:26:09 +02:00
Cole Miller
543a7b123a debugger: Fix errors in JavaScript DAP schema (#33884)
`program` isn't required, and in fact our built-in `JavaScript debug
terminal` configuration doesn't have it.

Also add `node-terminal` to the list of allowed types.

Co-authored-by: Michael <michael@zed.dev>

Release Notes:

- N/A
2025-07-04 13:33:10 -04:00
Bennet Bo Fenner
8fecacfbaa settings: Remove version keys from default settings (#33921)
Follow up to #33372

Release Notes:

- N/A
2025-07-04 16:30:21 +00:00
Bennet Bo Fenner
59cdea00c5 agent: Fix context server restart when settings unchanged (#33920)
Closes #33891

Release Notes:

- agent: Fix an issue where configuring an MCP server would not restart
the underlying server correctly
2025-07-04 16:27:11 +00:00
Bennet Bo Fenner
3d7e012e09 gemini: Fix issue with builtin tool schemas (#33917)
Closes #33894

After #33635 Gemini Integration was broken because we now produce
`const` fields for enums, which are not supported.
Changing this to `openapi3` fixes the issue.

Release Notes:

- Fixed an issue where Gemini Models would not work because of
incompatible tool schemas
2025-07-04 15:11:38 +00:00
Piotr Osiewicz
8ebea17a9c debugger: Add history to console's query bar (#33914)
Closes #[33457](https://github.com/zed-industries/zed/discussions/33457)

Release Notes:

- debugger: Added query history to the console
2025-07-04 12:25:08 +00:00
Danilo Leal
5253702200 Move the LoadingLabel component to the UI crate (#33893)
So we can use it in other places and don't require them to depend on the
`agent_ui`. This PR also renames it from `AnimatedLabel` to
`LoadingLabel`.

Release Notes:

- N/A
2025-07-04 04:49:11 +00:00
Michael Sloan
ed7552d3e3 Default `#[schemars(deny_unknown_fields)] for json-language-server schemas (#33883)
Followup to #33678, doing the same thing for all JSON Schema files
provided to json-language-server

Release Notes:

* Added warnings for unknown fields when editing `tasks.json` /
`snippets.json`.
2025-07-04 00:57:43 +00:00
Cole Miller
38544e514a debugger: Use debugpy's suggested names for child sessions (#33885)
Just like vscode-js-debug, debugpy uses the `name` key in
StartDebuggingRequestArguments for this:


0d65353cc6/src/debugpy/adapter/clients.py (L753)

Release Notes:

- debugger: Made the names of Python subprocesses in the session list
more helpful.
2025-07-04 00:15:02 +00:00
Richard Feldman
03ca2f4d2b Fix yaml comment indent (#33882)
Closes #33761

The problem was that in the indentation regex we were treating lines
that had `:` in them as requiring an indent on the next line, even if
that `:` was inside a comment.

Release Notes:

- Fixed YAML indentation for lines containing comments with `:` in them
2025-07-03 23:57:57 +00:00
Piotr Osiewicz
91bfe6f968 debugger: Improve performance with large # of output (#33874)
Closes #33820

Release Notes:

- Improved performance of debug console when there are lots of output
events.

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-04 01:12:12 +02:00
Taras Martyniuk
0ebf7f54bb Fix Shift+Enter to send newline instead of carriage return in terminal (#33859)
Closes #33858

Changes Shift+Enter in the built-in terminal to send line feed (`\x0a`)
instead of carriage return (`\x0d`), enabling multi-line input in Claude
Code and other terminal applications.

Release Notes:

- Fixed the issue where Claude Code and other multi-line terminal
applications couldn't use Shift+Enter for newlines.
2025-07-03 15:25:11 -07:00
Michael Sloan
7a2593e520 Fix JSON Schema definitions path used for debug task (#33873)
Regression in #33678

Release Notes:

- (Preview Only) Fixed invalid json schema for `debug.json`.
2025-07-03 21:04:33 +00:00
Richard Feldman
fcd9da6cef Fix panic on inlay split (#33676)
Closes #33641

Release Notes:

- Fixed panic when trying to split on multibyte UTF-8 sequences.
2025-07-03 20:48:51 +00:00
Ben Kunkle
fcdd99e244 keymap_ui: Syntax highlight context (#33864)
Closes #ISSUE

Uses Rust for syntax highlighting of context in the keymap editor.
Future pass will improve color choice to make colors less abrasive

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-03 13:26:35 -04:00
Ben Kunkle
4e6b7ee3ea keymap_ui: Hover tooltip for action documentation (#33862)
Closes #ISSUE

Show the documentation for an action when hovered. As a bonus, also show
the humanized command palette name!

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-03 16:35:20 +00:00
Danilo Leal
34322ef1cd agent: Fix bug that prevented MCP servers to appear in the settings view (#33857)
Closes https://github.com/zed-industries/zed/issues/33827

After #33644 was merged, we would not start MCP servers coming from
extensions correctly anymore. The optimization uncovered a bug in the
implementation of `ContextServerDescriptorRegistry`, because we never
called `cx.notify()` when adding/removing context servers.
`ContextServerStore` listens for these events, and before #33644 this
was just working because of aace condition.

Release Notes:

- agent: Fixed bug that prevented MCP servers to appear in the settings
view.

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>
2025-07-03 15:05:29 +00:00
Oleksiy Syvokon
cc0d8a411e Add Danger check for changes to eval fixtures (#33852)
Also, revert unintentional changes to fixtures.

Changes to test fixtures are intentional and necessary.

Release Notes:

- N/A
2025-07-03 14:27:49 +00:00
Ben Kunkle
12ab53b804 Fix documentation of view release notes actions (#33851)
Follow up for: #33809 

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-03 14:22:28 +00:00
Umesh Yadav
b46e961991 agent_ui: Clear error message callout when message is edited or added in same thread (#33768)
Currently if error occurs in the agent thread and user updates the same
messages or sends a new message the error callout is still present and
is not cleared. In this PR we are clearing the last error in case user
sends a new messages or resend the previous message after editing.

Before:


https://github.com/user-attachments/assets/44994004-4cf0-45bc-8b69-88546f037372

After:


https://github.com/user-attachments/assets/993a2a63-8295-47d3-bbda-a2669dee2d5f

Release Notes:

- Fix bug in agent panel error callout not getting removed when a
message is edited or new a message is send.
2025-07-03 10:47:26 -03:00
Danilo Leal
42aca4189a agent: Improve provider section spacing in settings view (#33850)
Some design polish here as a follow-up to making the provider accordion
header entirely clickable.

Release Notes:

- agent: Improved design in the provider section by refining spacing.
2025-07-03 10:42:15 -03:00
Jason Lee
f34a7abf17 gpui: Add shadow_xs, shadow_2xs and fix shadow values to match Tailwind CSS (#33361)
Release Notes:

- N/A

---

https://tailwindcss.com/docs/box-shadow

| name | value |
| -- | -- |
| shadow-2xs | box-shadow: var(--shadow-2xs); /* 0 1px rgb(0 0 0 / 0.05)
*/ |
| shadow-xs | box-shadow: var(--shadow-xs); /* 0 1px 2px 0 rgb(0 0 0 /
0.05) */ |
| shadow-sm | box-shadow: var(--shadow-sm); /* 0 1px 3px 0 rgb(0 0 0 /
0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) */ |
| shadow-md | box-shadow: var(--shadow-md); /* 0 4px 6px -1px rgb(0 0 0
/ 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) */ |
| shadow-lg | box-shadow: var(--shadow-lg); /* 0 10px 15px -3px rgb(0 0
0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1) */ |
| shadow-xl | box-shadow: var(--shadow-xl); /* 0 20px 25px -5px rgb(0 0
0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1) */ |
| shadow-2xl | box-shadow: var(--shadow-2xl); /* 0 25px 50px -12px rgb(0
0 0 / 0.25) */ |

## Before

<img width="1112" alt="SCR-20250625-nnxn"
src="https://github.com/user-attachments/assets/3bd44938-5de8-4d67-b323-c444b023a4b6"
/>

## After

<img width="1112" alt="SCR-20250625-nnrt"
src="https://github.com/user-attachments/assets/a5bf2401-f808-4712-9cc6-299f530f9165"
/>
2025-07-03 09:50:26 -03:00
Danilo Leal
2bf2c5c580 Add more refinements to the keymap edit UI (#33847)
Quick follow-up to https://github.com/zed-industries/zed/pull/33816,
tidying it up some things a bit more.

Release Notes:

- N/A
2025-07-03 12:39:03 +00:00
Kirill Bulatov
a6ee4a18c4 Fix remote binary bundling (#33845)
Follow-up of https://github.com/zed-industries/zed/pull/32937
Fixes remote server bundling:
https://github.com/zed-industries/zed/actions/runs/16043840539/job/45271137215#step:6:2079

Excludes `screen-capture` feature from Zed's default, use it only in the
components that need it.

Release Notes:

- N/A
2025-07-03 12:17:54 +00:00
张小白
cdb7564d89 windows: More precise handling of WM_SETTINGCHANGE and appearance updates (#33829)
This PR adds more fine-grained handling of the `WM_SETTINGCHANGE`
message.
Plus, we now only trigger the `appearance_changed` callback when the
actual window appearance has changed, rather than calling it every time.


Release Notes:

- N/A
2025-07-03 17:27:27 +08:00
marius851000
968587a745 worspace: Add partial window bound fix when switching between CSD and SSD on Wayland (#31335)
Partial fix for #31330

It fix the problem that the inset stay on after switching to SSD, but it
still have the problem that after that first redraw, it have the wrong
size. Just resizing it even once work. I guess the relevant code to fix
that would be ``handle_toplevel_decoration_event`` of
``crates/gpui/src/platform/linux/wayland/window.rs``, but trying to call
resize here does not seems to work correctly (might be just wrong
argument), and I would like to take a break on that for now.

Release Notes:

- N/A

(better wait for that to be completely fixed before adding it in the
changelog)

---------

Co-authored-by: Michael Sloan <michael@zed.dev>
2025-07-03 12:26:00 +03:00
Kirill Bulatov
48c8555076 Show more info in the UI and logs (#33841)
Addresses the `The binding is not displayed, though:` part from
https://github.com/zed-industries/zed/discussions/29498#discussioncomment-13649543

Release Notes:

- N/A
2025-07-03 09:15:50 +00:00
Finn Evers
06ddc74917 editor: Reapply fix for wrap guide positioning (#33776)
Reapplies the fix from #33514 which was removed in #33554. Wrap guides
are currently drifting again due to this on main.

Slightly changed the approach here so that we now actually only save the
wrap guides in the `EditorLayout` that will actually be painted. Also
ensures that we paint indent guides that were previously hidden behind
the vertical scrollbar once it auto-hides.

I wanted to add tests for this, however, I am rather sure this depends
on the work/fixes in #33590 and thus I'd prefer to add these later so we
can have this fix in the next release.

Release Notes:

- N/A
2025-07-03 11:44:17 +03:00
chico ferreira
5c88e9c66b terminal: Expose selection in context and add keep_selection_on_copy setting (#33491)
Closes #21262

Introduces a new setting `keep_selection_on_copy`, which controls
whether the current text selection is preserved after copying in the
terminal. The default behavior remains the same (`true`), but setting it
to `false` will clear the selection after the copy operation, matching
VSCode's behavior.

Additionally, the terminal context now exposes a `selection` flag
whenever text is selected.

This allows users to match VSCode and other terminal's smart copy
behavior.

Release Notes:

- Expose `selection` to terminal context when there is text selected in
the terminal
- Add `keep_selection_on_copy` terminal setting. Can be set to false to
clear the text selection when copying text.

**VSCode Behavior Example:**

**settings.json:**
```json
  "terminal": {
    "keep_selection_on_copy": false
  },
```
**keymap.json:**
```json
  {
    "context": "Terminal && selection",
    "bindings": {
      "ctrl-c": "terminal::Copy"
    }
  }
```
2025-07-03 09:37:27 +03:00
Conrad Irwin
2a8121fbfc Clean up project repositories / repository statuses too (#33803)
Co-authored-by: Cole Miller <cole@zed.dev>

Closes #ISSUE

Release Notes:

- N/A

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-02 21:36:12 -06:00
Ben Kunkle
6cd4dbdea1 gpui: Store action documentation (#33809)
Closes #ISSUE

Adds a new `documentation` method to actions, that is extracted from doc
comments when using the `actions!` or derive macros.

Additionally, this PR adds doc comments to as many action definitions in
Zed as possible.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-02 21:14:33 -04:00
Cole Miller
def8bab5a8 Fix script/symbolicate for Linux panic reports (#33822)
Release Notes:

- N/A
2025-07-03 01:04:27 +00:00
Michael Sloan
32d058d95e Fix remote server (ssh) crash when editing json (#33818)
Closes #33807

Release Notes:

- (Preview Only) Fixes a remote server (ssh) crash when editing json
files

---------

Co-authored-by: Cole <cole@zed.dev>
2025-07-03 00:21:39 +00:00
Danilo Leal
77c4530e12 Add refinements to the keymap UI (#33816)
This includes mostly polishing up the keystroke editing modal, and some
other bits like making the keystroke rendering function more composable.

Release Notes:

- Added refinements to the keymap UI design.

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Ben Kunkle <Ben.kunkle@gmail.com>
2025-07-02 19:48:49 -03:00
Remco Smits
fbc4256732 debugger: Fix update inline values on settings change (#33808)
Release Notes:

- Debugger: fixed that inline values would not update (hide/show) on
settings change
2025-07-02 16:55:42 -04:00
Cole Miller
82fac9da82 debugger: Always use runtimeExecutable for node-terminal scenarios (#33794)
cc @afgomez 

Release Notes:

- debugger: Fixed `node-terminal` debug configurations not working with
some commands.
2025-07-02 16:37:52 -04:00
Cole Miller
e224da8522 Disambiguate package.json tasks by parent directory as needed (#33798)
Closes #33701, cc @afgomez 

Release Notes:

- Added the parent directory to the label as needed to disambiguate
tasks from package.json
2025-07-02 16:37:36 -04:00
Cole Miller
610f4605d8 Switch to ctrl-f11 for debugger::StepInto on macOS (#33799)
Plain `f11` is a system keybinding. We already use `ctrl-f11` for this
on Linux.

Release Notes:

- debugger: Switched the macOS keybinding for `debugger::StepInto` from
`f11` to `ctrl-f11`.
2025-07-02 16:36:25 -04:00
Bennet Bo Fenner
0553dc0d49 agent: Fix issue with duplicated tool names from MCP servers (#33811)
Closes #33792

Follow up to #33237 - Turns out my fix for this was not correct

Release Notes:

- agent: Fixed an issue where tools would not work when two MCP servers
provided a tool with the same name
2025-07-02 20:32:07 +00:00
Kirill Bulatov
f27b508e4b Improve workspace bindings (#33765)
* Add a "close item"-like binding to close the active dock, if present

Now, cmd/ctrl-w can be used close the focused dock before the Zed window

* Add defaults to MoveItem* actions to make it appear in the command
palette

Release Notes:

- N/A
2025-07-02 23:31:32 +03:00
Richard Feldman
64c413b9b6 Reopen windows concurrently (#33784)
Closes #21130

Release Notes:

- Now when Zed reopens windows, they all reopen concurrently instead of
one after another.
2025-07-02 14:54:20 -04:00
Iha Shin (신의하)
5f70a9cf59 Query multiple LSPs for more types of requests (#29359)
This fixes an issue where lower-priority language servers cannot provide
contentful responses even when the first capable server returned empty
responses.

Most of the diffs are copypasted since the existing implementations were
also copypasted.

Release Notes:

- Improved Go to Definition / Declaration / Type Definition /
Implementation and Find All References to include all results from
different language servers
2025-07-02 20:51:19 +03:00
Shuhei Kadowaki
105acacff9 lsp: Complete overloaded signature help implementation (#33199)
This PR revives zed-industries/zed#27818 and aims to complete the
partially implemented overloaded signature help feature.

The first commit is a rebase of zed-industries/zed#27818, and the
subsequent commit addresses all review feedback from the original PR.

Now the overloaded signature help works like


https://github.com/user-attachments/assets/e253c9a0-e3a5-4bfe-8003-eb75de41f672

Closes #21493

Release Notes:

- Implemented signature help for overloaded items. Additionally, added a
support for rendering signature help documentation.

---------

Co-authored-by: Fernando Tagawa <tagawafernando@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Kirill Bulatov <mail4score@gmail.com>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2025-07-02 20:51:08 +03:00
Peter Tripp
aa60647fe8 Bump Zed to v0.195 (#33783)
Release Notes:

- N/A
2025-07-02 17:36:53 +00:00
Piotr Osiewicz
4cc06bfb4e debugger: Fix wrong cwd in Rust tests (#33788)
This commit introduces a new task variable RUST_MANIFEST_DIRNAME which
points at the parent directory of the manifest for the current package.
Previously we were running `cargo test` inside of parent dir of a
currently focused source file, which happened to work with non-debug
stuff (as `cargo test` itself fixed cwd for us), but that no longer
works with debug scenarios - they are compiled separately and so we no
longer have cargo doing the heavy lifting for us

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>

Closes #33751

Release Notes:

- debugger: Fixed wrong cwd in automatically-generated Rust test debug
sessions

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
2025-07-02 17:36:35 +00:00
Ben Kunkle
11cb9ddeb9 keymap_ui: Fix crash when using a base keymap (#33795)
Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-02 17:23:57 +00:00
Piotr Osiewicz
169620632a task: Refactor ShellBuilder to allow for special-casing shells (#33793)
- **task: Start refactoring shell builder**
- **Unify Windows implementation of shell builder so that it's treated
like any other kind of a "custom" shell.**
- **Rename task/lib.rs to task/task.rs**

Release Notes:

- N/A

---------

Co-authored-by: Remco Smits <djsmits12@gmail.com>
Co-authored-by: Anthony Eid <hello@anthonyeid.me>
2025-07-02 13:07:09 -04:00
Cole Miller
f9bd54b4b1 debugger: Truncate long session and thread names (#33790)
Related to #33072 

Release Notes:

- debugger: Fixed long session and thread names eating up excessive
space in the control strip.
2025-07-02 12:58:07 -04:00
Sunli
4fdda8d5a1 gpui: Improve path rendering & global multisample anti-aliasing (#29718)
Currently, the rendering path required creating a texture for each path,
which wasted a large amount of video memory. In our application, simply
drawing some charts resulted in video memory usage as high as 5G.

I removed the step of creating path textures and directly drew the paths
on the rendering target, adding post-processing global multi-sampling
anti-aliasing. Drawing paths no longer requires allocating any
additional video memory and also improves the performance of path
rendering.

Release Notes:

- N/A

---------

Co-authored-by: Jason Lee <huacnlee@gmail.com>
2025-07-02 09:41:42 -07:00
Hilmar Wiegand
9dc3ac9657 gpui: Make screen capture dependency optional (#32937)
Add `screen-capture` feature to gpui to enable screen capture support.  The motivation for this is to make dependencies on scap / x11 / xcb optional.

Release Notes:

- N/A

---------

Co-authored-by: Michael Sloan <michael@zed.dev>
2025-07-02 10:15:06 -06:00
Ben Kunkle
6d09f3fa40 keymap_ui: Add default sort to keymap table (#33781)
Closes #ISSUE

Adds a default sort when no filter query is provided in the keymap
editor.

The default sorting algorithm sorts by the source of the binding
(roughly in order of precedence)
 
- User
- Vim
- Base
- Default
- None (unbound actions) 

within each source it sorts by action name alphabetically.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-02 15:00:18 +00:00
Antonio Scandurra
132bba8d8b Never run transactions using serializable isolation (#33780)
We believe this is causing the database to execute certain queries very
slowly, and it's unclear whether we're actually benefitting from it.

Release Notes:

- N/A
2025-07-02 14:30:38 +00:00
Richard Feldman
903212b7f5 Respect NO_PROXY env var (#33742)
Closes #22991

Release Notes:

- Added support for respecting the NO_PROXY environment variable when
any HTTP proxy is configured. For the exact NO_PROXY env var strings
that are supported, see [NoProxy in the reqwest
docs](https://docs.rs/reqwest/latest/reqwest/struct.NoProxy.html#method.from_env).

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-07-02 10:05:34 -04:00
Xavier Lau
c15d02454e Add ability to manage dock size via command/shortcut (#31366)
Closes https://github.com/zed-industries/zed/issues/29856
This idea originates from
https://github.com/microsoft/vscode/issues/158603.

Adds a
```jsonc
"ctrl-alt-0": "workspace::ResetActiveDockSize",
"ctrl-alt--": ["workspace::DecreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-=": ["workspace::IncreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-)": "workspace::ResetOpenDocksSize",
"ctrl-alt-_": ["workspace::DecreaseOpenDocksSize", { "px": 0 }],
"ctrl-alt-+": ["workspace::IncreaseOpenDocksSize", { "px": 0 }],
```

set of actions to manipulate dock sizes:


https://github.com/user-attachments/assets/0428f5ce-1156-449b-838f-a774b935458f

Release Notes:
- Add ability to manipulate dock size with
`workspace::Decrease/IncreaseActiveDockSize`,
`workspace::ResetActiveDockSize`,
`workspace::Decrease/IncreaseOpenDocksSize` and
`workspace::ResetOpenDocksSize` commands

---------

Signed-off-by: Xavier Lau <x@acg.box>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
2025-07-02 10:27:52 +00:00
Daniel Sauble
f000dfebd2 Add page up/down bindings to the Markdown preview (#33403)
First time contributor here. 😊

I settled on markdown::MovePageUp and markdown::MovePageDown to match
the names the editor uses for the same functionality.

Closes #30246

Release Notes:

- Support PgUp/PgDown in Markdown previews
2025-07-02 12:14:34 +03:00
Ian Mitchell
123a25c58c Expand Prettier config list (#33744)
Improves the prettier config file detection by adding missing entries
that are allowed per the docs: https://prettier.io/docs/configuration

Release Notes:

- Improved Prettier config file detection
2025-07-02 08:44:14 +00:00
Ben Kunkle
79f3cb1225 keymap_ui: Add context menu for table rows (#33747)
Closes #ISSUE

Adds a right click context menu to table rows, refactoring the table API
to support more general row rendering in the process, and creating
actions for the couple of operations available in the context menu.

Additionally includes an only partially related change to the context
menu API, which makes it easier to have actions that are disabled based
on a boolean value.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-02 03:06:45 +00:00
Piotr Osiewicz
faca128304 debugger: Fix zoomed panel size regression (#33746)
Co-authored-by: Cole <cole@zed.dev>

Release Notes:

- N/A

Co-authored-by: Cole <cole@zed.dev>
2025-07-01 23:17:55 +00:00
localcc
3f0f316f4d Fix windows manifest inclusion (#33745)
Fixes a regression which prevented zed from starting on windows due to
the lack of the embedded manifest. Caused by #bff5d85

Release Notes:

- N/A
2025-07-02 00:45:05 +02:00
Cole Miller
9d6b2e8a32 debugger: Don't take JS adapter's suggested child session name if it's empty (#33739)
Related to #33072 

We use the JS adapter's suggested names for child sessions, but
sometimes it sends us `""`, so don't use that one.

Release Notes:

- debugger: Fixed nameless child sessions appearing with the JavaScript
adapter.
2025-07-01 21:09:19 +00:00
Cathal
1d74fdc59f debugger: Filter test executables by metadata profile in Cargo locator (#33126)
Closes #33114

Release Notes:

- debugger: Ensure Cargo locator only targets relevant executables.
2025-07-01 16:23:55 -04:00
Cole Miller
b7bfdd3383 Move language-specific debugging docs to the page for each language (#33692)
Release Notes:

- N/A
2025-07-01 20:02:12 +00:00
Anthony Eid
0e2e5b8b0d debugger: Debug sessions rerun build tasks by default when restarting (#33724)
We reworked the debug modal spawning to use the task context from past
debug sessions when spawning a debug scenario based on task inventory
history.

We changed restart session keybinding to rerun session too.

Closes #31369

Release Notes:

- Restarting a debug session now reruns build tasks that are associated
with the session

---------

Co-authored-by: Cole Miller <cole@zed.dev>
2025-07-01 15:43:58 -04:00
Peter Tripp
6b06685723 Revert "settings: Remove version field migration" (#33729)
- Reverts zed-industries/zed#33711

I think we should just make this a breaking change with v0.194.x.
Forwards compatibility is hard, we should build abstractions that make
this easier (next time).

See also:
- https://github.com/zed-industries/zed/pull/33372

Release Notes:

- N/A
2025-07-01 14:21:26 -04:00
Marshall Bowers
8d894dd1df collab: Add logs to Stripe usage sync job (#33731)
This PR adds some additional logs to the Stripe usage sync job for
monitoring purposes.

Release Notes:

- N/A
2025-07-01 18:10:00 +00:00
Ben Kunkle
0eee768e7b keymap_ui: Separate action input into separate column and highlight as JSON (#33726)
Closes #ISSUE

Separates the action input in the Keymap UI into it's own column, and
wraps the input in an `impl RenderOnce` element that highlights it as
JSON.

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-07-01 17:58:38 +00:00
Michael Sloan
f1f19a32fb Use version equality constraint for zed_llm_client dependency (#33728)
Closes #33578

Release Notes:

- N/A
2025-07-01 17:56:24 +00:00
Michael Sloan
2ff155d5a2 Fix language settings formatter regression - formatter list can be a single formatter not wrapped in an array (#33721)
Fixes a regression from #33635

Release Notes:

- N/A
2025-07-01 17:47:19 +00:00
Piotr Osiewicz
eb74df632b debugger: Do not set exception breakpoints in initialization sequence in certain conditions (#33723)
As pointed out in https://github.com/probe-rs/probe-rs/issues/3333, we
violate the spec by sending setExceptionBreakpoints even when the
adapter does not define any exceptions.


Release Notes:

- N/A
2025-07-01 16:58:55 +00:00
Julia Ryan
0068de0386 debugger: Handle the envFile setting for Go (#33666)
Fixes #32984

Release Notes:

- The Go debugger now respects the `envFile` setting.
2025-07-01 09:14:59 -07:00
Julia Ryan
a11647d07f ci: Block PRs on Nix build failures (#33688)
Closes #17458

For now we're being conservative and only running CI on changes to the
following files:
- `flake.{nix,lock}`
- `Cargo.{lock,toml}`
- `nix/*`
- `.cargo/config.toml`
- `rust-toolchain.toml`

Release Notes:

- N/A
2025-07-01 09:14:25 -07:00
Peter Tripp
274f2e90da Add support for more python operators (#33720)
Closes: https://github.com/zed-industries/zed/issues/33683

| Before | After |
| - | - |
| <img width="571" alt="Screenshot 2025-07-01 at 11 42 56"
src="https://github.com/user-attachments/assets/5ef79304-37bb-42a1-8891-d19a55a5095e"
/> | <img width="592" alt="Screenshot 2025-07-01 at 11 44 45"
src="https://github.com/user-attachments/assets/f28aa2a8-6306-4294-86e1-8f089f57b825"
/> |

Release Notes:

- python: Properly highlight additional operators ("&=", "<<=", ">>=",
"@=", "^=" and "|=")
2025-07-01 12:12:46 -04:00
Alex Shi
31b7786be7 Fix IndentGuides story (#32781)
This PR updates the `Model` to `Entity` also fixes the
`IndentGuidesStory`. In this
[commit](6fca1d2b0b),
`Entity<T>` replaces `View<T>`/`Model<T>`.

Other than this, I noticed the storybook fails on my MacOS and Ubuntu,
see error below

```
thread 'main' panicked at crates/gpui/src/colors.rs:99:15:
called `Result::unwrap()` on an `Err` value: no state of type gpui::colors::GlobalColors exists
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```

This was resolved by explicitly specifying `GlobalColors` in Storybook.

Release Notes:

- N/A
2025-07-01 15:43:39 +00:00
G36maid
351ba5023b docs: Add FreeBSD build instructions and current status (#33617)
This adds documentation for building Zed on FreeBSD.
Notice WebRTC/LiveKit remains unsupported on this platform for now.

Follow-up to:
- #33162
- #30981

Release Notes:

- N/A

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-07-01 15:18:34 +00:00
Abdelhakim Qbaich
3041de0cdf Suggest Typst extension for .typ files (#33632)
Release Notes:

- N/A
2025-07-01 17:54:53 +03:00
Marshall Bowers
52c42125a7 language_models: Fix casing of ZedAiConfiguration (#33712)
This PR fixes the casing of the `ZedAiConfiguration` identifier.

Release Notes:

- N/A
2025-07-01 13:29:43 +00:00
Bennet Bo Fenner
62e8f45304 settings: Remove version field migration (#33711)
This reverts some parts of #33372, as it will break the settings for
users running stable and preview at the same time. We can add it back
once the changes make it to stable.

Release Notes:

- N/A
2025-07-01 13:17:36 +00:00
Vitaly Slobodin
0fe73a99e5 ruby: Add basic documentation about debugging (#33572)
Hi, this pull request adds basic documentation about debugging feature
available in the Ruby extension.


Release Notes:

- N/A
2025-07-01 09:12:08 -04:00
Umesh Yadav
6e9c6c5684 git_ui: Fix list in git commit message (#33409)
Follow up: #32114

Closes #33274

Use the new support for language-specific rewrap_prefixes added in
https://github.com/zed-industries/zed/pull/33702.

Release Notes:

- Fix git commit message line break getting stripped after committing.

---------

Signed-off-by: Umesh Yadav <git@umesh.dev>
2025-07-01 08:05:08 -04:00
Danilo Leal
42f788185a agent: Use callout for displaying errors instead of toasts (#33680)
This PR makes all errors in the agent panel to use the `Callout`
component instead of toasts. Reason for that is because the toasts
obscured part of the panel's UI, which wasn't ideal. We can also be more
expressive here with a background color, which I think helps with
parsing the message.

Release Notes:

- agent: Improved how we display errors in the panel.
2025-07-01 09:00:20 -03:00
Cole Miller
a5b2428897 debugger: Fix Go locator for subtests (#33694)
Closes #33054 

Release Notes:

- Fixed debugging Go subtests.
2025-07-01 11:34:50 +00:00
Bennet Bo Fenner
0629804390 agent: Clarify upgrade path when starting trial (#33706)
Release Notes:

- N/A
2025-07-01 11:32:14 +00:00
Smit Barmase
3151b5efc1 languages: Fix ( wouldn’t autocomplete when . is preceded by it in Markdown (#33705)
Closes #5092

Release Notes:

- Fixed issue where `(` wouldn’t autocomplete when `.` is preceded by it
in Markdown.
2025-07-01 16:51:46 +05:30
Bennet Bo Fenner
782fbfad90 agent: Add component preview for Zed AI configuration (#33704)
As we are in the process of improving our Onboarding UX for Zed AI, I
added component previews for the Zed AI Configuration section. This
should make it easier to inspect the different states we can run into.

<img width="1198" alt="image"
src="https://github.com/user-attachments/assets/eb774f27-9091-450d-bfae-c688d533c25e"
/>


Release Notes:

- N/A
2025-07-01 11:12:51 +00:00
Piotr Osiewicz
2caa19214b debugger: Do not include Rust in default value for sourceLanguages (CodeLLDB config) (#33670)
- **debugger: Update exception breakpoints list on capability update**
- **Do not prefill codelldb sourcelanguages by default**

Release Notes:

- debugger: CodeLLDB no longer enables pretty-printers for Rust by
default. This fixes pretty-printers for C++. This is a breaking change
for user-defined debug scenarios from debug.json; in order to enable
Rust pretty printing when using CodeLLDB, add `"sourceLanguages":
["rust"]` to your debug configuration. This change does not affect
scenarios automatically inferred by Zed.

---------

Co-authored-by: Anthony Eid <anthony@zed.dev>
2025-07-01 11:03:40 +00:00
Sunli
bff5d85ff4 gpui: Add the windows-manifest feature to embed manifest, enable by default (#32440)
Gpui's build.rs will embed a manifest file into the Windows binary, but
sometimes we want to customize it, so I added a feature called
`no-windows-manifest` to disable this behavior.

Release Notes:

- N/A
2025-07-01 13:00:14 +02:00
Bedis Nbiba
abe5d523e1 dap_adapters: Add attachSimplePort to JS DAP schema (#31412)
taken from
https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md?plain=1

Release Notes:

- debugger: Added attachSimplePort to JavaScript DAP schema

---------

Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
2025-07-01 12:28:01 +02:00
Smit Barmase
8fb3199a84 editor: Improve rewrap of markdown lists, todos, and block quotes (#33702)
Closes #19644 #18151

Now, rewrapping markdown lists (unordered, ordered, and to-do lists) and
block quotes wrap them separately, without merging them together.
Additionally, it correctly indents subsequent lines.

With this input: 

```md
1. This is a list item that is short.
2. This list item is a bit longer because I want to see if it wraps correctly after a rewrap operation in Zed. What do you think?
3. another short item
```

Output would be:

```md
1. This is a list item that is short.
2. This list item is a bit longer because I want to see if it wraps correctly
   after a rewrap operation in Zed. What do you think?
3. another short item
```

Instead of:

```md
1. This is a list item that is short. 2. This list item is a bit longer because 
I want to see if it wraps correctly after a rewrap operation in Zed. What 
do you think? 3. another short item
```

Release Notes:

- Improved rewrap for markdown lists, todos, and block quotes.
2025-07-01 15:34:39 +05:30
Shardul Vaidya
0d809c21ba bedrock: Fix bedrock not streaming (#28281)
Closes #26030 

Release Notes:

- Fixed Bedrock bug causing streaming responses to return as one big
chunk

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-07-01 12:51:09 +03:00
Michael Sloan
93b1e95a5d agent: Make AgentSettings::default_model optional (#33695)
It's already effectively optional and the the old default of gpt-4
doesn't really get used in practice

Release Notes:

- N/A
2025-07-01 00:46:01 -06:00
maan2003
49bc2e61da gpui: Fix slow scrolling in lists (#33608)
matches editor element's behavior


https://github.com/user-attachments/assets/f70912e1-5adb-403b-a98c-63e2e89929ac


- in first version editor scrolls like 1.5 pages, but agent panel only
scrolls half a page.
- in second version, agent panel also scrolls like 1.5 pages.

Release Notes:

- Fixed skipping of some scroll events in the non-uniform list UI element, which fixes slow scrolling of the agent panel.
2025-07-01 00:44:19 -06:00
mslzed
9a4bcd11a2 Remove callout for hiring (#33674)
Closes #ISSUE

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-06-30 23:35:00 -07:00
Michael Sloan
2ee5bedfa9 agent: Only consider zed provider authenticated if TOS is accepted (#33693)
Also now auto-expands the zed provider section when TOS is not accepted

Release Notes:

- N/A
2025-07-01 04:51:32 +00:00
Michael Sloan
d497f52e17 agent: Improve error handling and retry for zed-provided models (#33565)
* Updates to `zed_llm_client-0.8.5` which adds support for `retry_after`
when anthropic provides it.

* Distinguishes upstream provider errors and rate limits from errors
that originate from zed's servers

* Moves `LanguageModelCompletionError::BadInputJson` to
`LanguageModelCompletionEvent::ToolUseJsonParseError`. While arguably
this is an error case, the logic in thread is cleaner with this move.
There is also precedent for inclusion of errors in the event type -
`CompletionRequestStatus::Failed` is how cloud errors arrive.

* Updates `PROVIDER_ID` / `PROVIDER_NAME` constants to use proper types
instead of `&str`, since they can be constructed in a const fashion.

* Removes use of `CLIENT_SUPPORTS_EXA_WEB_SEARCH_PROVIDER_HEADER_NAME`
as the server no longer reads this header and just defaults to that
behavior.

Release notes for this is covered by #33275

Release Notes:

- N/A

---------

Co-authored-by: Richard Feldman <oss@rtfeldman.com>
Co-authored-by: Richard <richard@zed.dev>
2025-06-30 21:01:32 -06:00
Michael Sloan
f022a13091 Add #[serde(deny_unknown_fields)] to action structs that didn't have it (#33679)
Release Notes:

- N/A
2025-07-01 00:20:02 +00:00
Michael Sloan
c74ecb4654 Warn about unknown fields when editing settings json (#33678)
Closes #30017

* While generating the settings JSON schema, defaults all schema
definitions to reject unknown fields via `additionalProperties: false`.

* Uses `unevaluatedProperties: false` at the top level to check fields
that remain after the settings field names + release stage override
field names.

* Changes json schema version from `draft07` to `draft_2019_09` to have
support for `unevaluatedProperties`.

Release Notes:

- Added warnings for unknown fields when editing `settings.json`.
2025-06-30 23:34:25 +00:00
Mikayla Maki
7609ca7a8d Sketch in a table for the keybindings UI (#32436)
Adds the initial semblance of a keymap UI. It is currently gated behind the `settings-ui` feature flag. Follow up PRs will add polish and missing features.

Release Notes:

- N/A

---------

Co-authored-by: Ben Kunkle <ben@zed.dev>
Co-authored-by: Anthony <anthony@zed.dev>
2025-06-30 19:25:11 -04:00
Umesh Yadav
32906bfa7c Update Cargo.lock (#33667)
Followup to: https://github.com/zed-industries/zed/pull/32208

Release Notes:

- N/A
2025-06-30 15:12:02 -06:00
Michael Sloan
5fafab6e52 Migrate to schemars version 1.0 (#33635)
The major change in schemars 1.0 is that now schemas are represented as
plain json values instead of specialized datatypes. This allows for more
concise construction and manipulation.

This change also improves how settings schemas are generated. Each top
level settings type was being generated as a full root schema including
the definitions it references, and then these were merged. This meant
generating all shared definitions multiple times, and might have bugs in
cases where there are two types with the same names.

Now instead the schemar generator's `definitions` are built up as they
normally are and the `Settings` trait no longer has a special
`json_schema` method. To handle types that have schema that vary at
runtime (`FontFamilyName`, `ThemeName`, etc), values of
`ParameterizedJsonSchema` are collected by `inventory`, and the schema
definitions for these types are replaced.

To help check that this doesn't break anything, I tried to minimize the
overall [schema
diff](https://gist.github.com/mgsloan/1de549def20399d6f37943a3c1583ee7)
with some patches to make the order more consistent + schemas also
sorted with `jq -S .`. A skim of the diff shows that the diffs come
from:

* `enum: ["value"]` turning into `const: "value"`
* Differences in handling of newlines for "description"
* Schemas for generic types no longer including the parameter name, now
all disambiguation is with numeric suffixes
* Enums now using `oneOf` instead of `anyOf`.

Release Notes:

- N/A
2025-06-30 21:07:28 +00:00
Conrad Irwin
a2e786e0f9 Allow repeat in visual mode (#33569)
Release Notes:

- vim: Allow `.` in visual mode.
2025-06-30 14:04:28 -06:00
Alejandro Fernández Gómez
b0086b472f Fix an interaction between vim's linewise yank and editor's paste (#33555)
Closes #32397

This PR fixes an issue when pasting text with the `editor::Paste`
command that was copied with `vim::Yank`'s linewise selection.

The change stops setting the `is_entire_line` setting when copying from
with vim linewise selections (<kbd>⇧v</kbd>) and motions (i.e.
<kbd>y2j</kbd>).

This flag is used when cutting/copying text without being selected (so,
place a cursor on line without selecting anything, and press
<kbd>⌘X</kbd>). When cutting/copying text in this manner, [the editor
pastes the text above the
cursor](36941253ee/crates/editor/src/editor.rs (L11936-L11947)).
However, this behaviour is not needed when cutting/copying with vim
motions.

Pasting with vim operations is not affected by this change. [They are
handled
elsewhere](36941253ee/crates/vim/src/normal/paste.rs)
and they don't consider the `is_entire_line` flag at all.

Note for maintainers: I'm not familiar with this codebase 🙃. This change
fixes the issue. I don't see anything breaking... but let me know if
it's not the case and a more thorough change is needed.

**Before:**

The text is copied above the first line, before the cursor.


https://github.com/user-attachments/assets/0c2f111a-5da0-4775-a7a0-2e4fb6f78bfc


**After:**
The text is copied at the cursor location:


https://github.com/user-attachments/assets/60a17985-fe8b-4149-a77b-d72bf531bf85


Release Notes:

- Fixed an issue when pasting text that was yanked with vim's linewise
selections.
2025-06-30 14:03:55 -06:00
fantacell
d10cc13924 helix: Add more tests (#33582)
These tests cover more edge cases

Release Notes:

- N/A
2025-06-30 13:57:20 -06:00
Alvaro Parker
2680a78f9c Support vim-mode in git commit editor (#33222)
Release Notes:

- Added support for vim-mode on git commit editor (modal included)

Side notes: 
- Maybe in the future (or even on this PR) a config could be added to
let the user choose whether to enable vim-mode on this editor or not?
And on the agent message editor as well.
2025-06-30 13:55:45 -06:00
Kirill Bulatov
197828980c Properly register initialized default prettier (#33669)
Stop doing useless prettier-related work when doing a project search.

Before, project search might cause

<img width="1728" alt="not_pretty"
src="https://github.com/user-attachments/assets/5f8b935f-962d-488e-984f-50dfbaee97ba"
/>

but now we debounce the prettier-related task first, and actually set
the "installed" state for the default prettier, when there's no install
needed.

Release Notes:

- N/A
2025-06-30 19:08:50 +00:00
Conrad Taylor
7c4da37322 emmet: Fix expansion for HEEx and H sigil files (#32208)
Closes #14149

Release Notes:

- Added support for the Emmet LSP in Elixir heex files
2025-06-30 12:45:10 -04:00
Julia Ryan
ce164f5e65 Remove ruby debug adapter (#33541)
Now that the extension version has been bumped we can remove our in-tree
one to avoid having duplicate debug adapters.

Release Notes:

- The ruby debug adapter has been moved to the [ruby
extension](https://github.com/zed-extensions/ruby), if you have any
saved debug scenarios you'll need to change `"adapter": "Ruby"` to
`"adapter": "rdbg"`.
2025-06-30 09:15:56 -07:00
Piotr Osiewicz
42c59014a9 debugger: Fix global debug tasks not being picked up (#33664)
Release Notes:

- Fixed a bug which caused global debug scenarios (from global
.zed/debug.json) to not be picked up.
2025-06-30 15:53:34 +00:00
Danilo Leal
3db452eec7 agent: Use a banner for the auto-retry message (#33661)
Follow-up to https://github.com/zed-industries/zed/pull/33275 so we use
the Banner component to display the auto-retry messages in the thread.

Release Notes:

- N/A
2025-06-30 15:34:28 +00:00
Kirill Bulatov
6e77e8405b Revert "languages: Bump ESLint LSP server to version 3.0.10 (#32717)" (#33659)
This reverts commit 1edaeebae5.

Based on an elevated number of ESLint-related issues, reverting the
upgrade.
Many people upvoted the issues and did not share any repro details, so
cannot be certain what's more broken: seems relatively generic as
related to *.ts ESLint configs.

Checked the revert on 2 projects from the issues below:

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

With https://github.com/adamhl8/zed-33425 as an example repo: there,
both eslint configurations worked for me when I stopped Zed and opened a
project.
Somehow, switching various Zed's with different vscode-eslint package
versions, eventually I get
`Error: Cannot find module
'~/.local/share/zed/languages/eslint/vscode-eslint-3.0.10/vscode-eslint/server/out/eslintServer.js'`-ish
error.

Not very related to issues with newer vscode-eslint integration, but
worth mentioning as is related to the package updates.


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

With a good example of
https://github.com/florian-lackner365/zed-eslint-bug monorepo project.
The monorepo part seems not to be related, but somehow,
`eslint.config.js` is involved as the newer vscode-eslint fails to find
a config.
Works well with the older vscode-eslint.

Release Notes:

- Downgraded to vscode-eslint-2.4.4 as a ESLint language server
2025-06-30 15:19:00 +00:00
Alejandro Fernández Gómez
465f64da7e Make the preview button the same as the other buttons (#33658)
This fixes a tiny visual defect I noticed today. The "Preview" button is
slightly smaller and has less padding than the other buttons in the
quick action bar.

**Before:**

Note how there is a small gap between the black guides and the button.


https://github.com/user-attachments/assets/04d3d83a-9193-47b1-80d8-94a5d1fbd750

**After:**


https://github.com/user-attachments/assets/98f878cc-c5e3-491c-abe9-9ef0d5cf678a



Release Notes:

- N/A
2025-06-30 15:16:01 +00:00
Piotr Osiewicz
e5a8cc7aab debugger: Fix DAP Logs mangling sessions across multiple Zed windows (#33656)
Release Notes:

- Fixed an issue with Debug Adapter log showing sessions from other Zed
windows in the dropdown.
2025-06-30 15:01:54 +00:00
Peter Tripp
bdf29bf76f Allow disabling tools when 'enable_all_context_servers = true' (#33536)
Closes https://github.com/zed-industries/zed/issues/33519

Release Notes:

- agent: Improved support for explicitly disabling individual tools when
`enable_all_context_servers` is true. (e.g. enable all tools except
XYZ).
2025-06-30 10:56:25 -04:00
Danilo Leal
402c61c00d Add small UI tweak to the inline color preview square (#33655)
Follow-up to https://github.com/zed-industries/zed/pull/33605 so it is
just a bit more subtle and smaller.

Release Notes:

- N/A
2025-06-30 11:19:58 -03:00
Mikal Sande
59e88ce82b Show regex query error under the search bar (#33638)
Closes #17223

Release Notes:

- Show regex parsing errors under the search bar for buffer and project
search.

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-06-30 11:05:33 -03:00
Peter Tripp
22ab4c53d1 R docs: Remove non-working configuration (#33654)
This config was meant to be commented out in #33594 because it does not
work.

Release Notes:

- N/A
2025-06-30 14:03:09 +00:00
Danilo Leal
f106ea7641 docs: Update custom MCP format template (#33649)
To match the new format added in
https://github.com/zed-industries/zed/pull/33539.

Release Notes:

- N/A
2025-06-30 10:42:38 -03:00
Kirill Bulatov
e37ef2a991 Use more generic error messages in gpui (#33651)
Follow-up of https://github.com/zed-industries/zed/pull/32537

Release Notes:

- N/A
2025-06-30 13:40:31 +00:00
Danilo Leal
1c05062482 agent: Always focus on to the active model in the picker (#33567)
Release Notes:

- agent: Improved the model selector by ensuring the active model is
always focused on open.
2025-06-30 10:32:27 -03:00
Piotr Osiewicz
8c04f12499 debugger: Tighten up breakpoint list (#33645)
Release Notes:

- N/A
2025-06-30 14:49:09 +02:00
Bennet Bo Fenner
aa7ccecc49 agent: Reduce log spam for context servers (#33644)
Previously we would always run `maintain_servers` even if the settings
did not change. While this would not cause any MCP servers to restart,
we would still go through all configured servers and call the
`command(...)` function on each installed MCP extension. This can cause
lots of logs to show up when an MCP server is not configured correctly.

Release Notes:

- N/A
2025-06-30 10:26:14 +00:00
Umesh Yadav
f4aeeda2d9 script: Fix license symlink and path in new-crate.sh (#33620)
While creating a new crate I realised the License symlink and path are
broken. The symlink was broken for LICENSE-GPL. Also the file created in
the new crate was not using the expected file name as per the
check-license script which was failing due to wrong filename in the new
crate. I fixed that as well.

Release Notes:

- N/A

Signed-off-by: Umesh Yadav <git@umesh.dev>
2025-06-30 09:51:58 +00:00
Bennet Bo Fenner
ca0bd53bed agent: Fix an issue with messages containing trailing whitespace (#33643)
Seeing this come up in our server logs when sending requests to
Anthropic: `final assistant content cannot end with trailing
whitespace`.


Release Notes:

- agent: Fixed an issue where Anthropic requests would sometimes fail
because of malformed assistant messages
2025-06-30 09:31:40 +00:00
Kirill Bulatov
ae6237178c Further improve color inlay hints in multi buffers (#33642)
Follow-up of https://github.com/zed-industries/zed/pull/33605

Release Notes:

- N/A
2025-06-30 09:18:43 +00:00
Bennet Bo Fenner
ac3328adb6 agent: Fix issue where web search could return 401 (#33639)
Closes #33524

Release Notes:

- agent: Fix an issue where performing a web search request would
sometimes fail
2025-06-30 11:12:12 +02:00
Bennet Bo Fenner
d63909c598 agent: Use standardized MCP configuration format in settings (#33539)
Changes our MCP settings from:

```json
{
  "context_servers": {
    "some-mcp-server": {
      "source": "custom",
      "command": {
        "path": "npx",
        "args": [
          "-y",
          "@supabase/mcp-server-supabase@latest",
          "--read-only",
          "--project-ref=<project-ref>",
        ],
        "env": {
          "SUPABASE_ACCESS_TOKEN": "<personal-access-token>",
        },
      },
    },
  },
}

```

to:
```json
{
  "context_servers": {
    "some-mcp-server": {
      "source": "custom",
      "command": "npx",
      "args": [
        "-y",
        "@supabase/mcp-server-supabase@latest",
        "--read-only",
        "--project-ref=<project-ref>",
      ],
      "env": {
        "SUPABASE_ACCESS_TOKEN": "<personal-access-token>",
      },
    },
  },
}
```


Which seems to be somewhat of a standard now (VSCode, Cursor, Windsurf,
...)

Release Notes:

- agent: Use standardised format for configuring MCP Servers
2025-06-30 08:05:52 +00:00
Danilo Leal
c3d0230f89 docs: Adjust heading sizes (#33628)
Just fine-tuning some heading sizes that were off, particularly h4s and
h5s.

Release Notes:

- N/A
2025-06-29 20:49:28 -03:00
Piotr Osiewicz
bc5927d5af debugger: Fix spec violation with threads request being issued before debug session is initialized (#33627)
Follow-up to #32852. This time we'll check if the debug session is
initialized before querying threads.

Release Notes:

- Fix Zed's debugger issuing threads request before it is allowed to do
so per DAP specification.
2025-06-29 23:38:16 +00:00
Piotr Osiewicz
d2cf995e27 debugger: Tweak layout of debug landing page in vertical dock position (#33625)
Release Notes:

- Reorganized layout of a debug panel without any sessions for a
vertical dock position.
- Moved parent directories of source breakpoints into a tooltip.
2025-06-30 00:48:14 +02:00
Michael Sloan
86161aa427 Use refs to deduplicate settings JSON schema (~1.7mb to ~0.26mb) (#33618)
Release Notes:

- N/A
2025-06-29 18:33:05 +00:00
Peter Tripp
a602b4b305 Improve R documentation (#33594)
Release Notes:

- N/A
2025-06-29 12:21:10 -04:00
Kirill Bulatov
047d515abf Rework color indicators visual representation (#33605)
Use a div-based rendering code instead of using a text

Closes https://github.com/zed-industries/zed/discussions/33507

Before:
<img width="410" alt="before_dark"
src="https://github.com/user-attachments/assets/66ad63ae-7836-4dc7-8176-a2ff5a38bcd4"
/>
After:
<img width="407" alt="after_dark"
src="https://github.com/user-attachments/assets/0b627da8-461b-4f19-b236-4a69bf5952a0"
/>


Before:
<img width="409" alt="before_light"
src="https://github.com/user-attachments/assets/ebcfabec-fcda-4b63-aee6-c702888f0db4"
/>
After:
<img width="410" alt="after_light"
src="https://github.com/user-attachments/assets/c0da42a1-d6b3-4e08-a56c-9966c07e442d"
/>

The border is not that contrast as in VSCode examples in the issue, but
I'm supposed to use the right thing in

1e11de48ee/crates/editor/src/display_map/inlay_map.rs (L357)

based on 


41583fb066/crates/theme/src/styles/colors.rs (L16-L17)

Another oddity is that the border starts to shrink on `cmd-=`
(`zed::IncreaseBufferFontSize`):

<img width="1244" alt="image"
src="https://github.com/user-attachments/assets/f424edc0-ca0c-4b02-96d4-6da7bf70449a"
/>

but that needs a different part of code to be adjusted hence skipped.

Tailwind CSS example:

<img width="1108" alt="image"
src="https://github.com/user-attachments/assets/10ada4dc-ea8c-46d3-b285-d895bbd6a619"
/>


Release Notes:

- Reworked color indicators visual representation
2025-06-29 09:43:56 +00:00
Piotr Osiewicz
e5bcd720e1 debugger: Add UI for tweaking breakpoint properties directly from breakpoint list (#33097)
Release Notes:

- debugger: Breakpoint properties (log/hit condition/condition) can now
be set directly from breakpoint list.
2025-06-28 23:41:44 +02:00
Kirill Bulatov
41583fb066 Fix document colors issues with other inlays and multi buffers (#33598)
Closes https://github.com/zed-industries/zed/issues/33575

* Fixes inlay colors spoiled after document color displayed
* Optimizes the query pattern for large multi buffers

Release Notes:

- Fixed document colors issues with other inlays and multi buffers
2025-06-28 21:10:49 +00:00
Cole Miller
521a223681 Add editor::Rewrap binding to Emacs keymaps (#33588)
`M-q` is `fill-paragraph` which is like `editor::Rewrap`.

Release Notes:

- emacs: Bound `alt-q` to `editor::Rewrap` (like `M-q` or `M-x
fill-paragraph`)
2025-06-28 15:35:59 -04:00
Conrad Irwin
c8c6468f9c vim: Non-interactive shell (#33568)
Closes #33144

Release Notes:

- vim: Run r! in a non-interactive shell
2025-06-28 10:23:57 -06:00
Umesh Yadav
3f4098e87b open_ai: Make OpenAI error message generic (#33383)
Context: In this PR: https://github.com/zed-industries/zed/pull/33362,
we started to use underlying open_ai crate for making api calls for
vercel as well. Now whenever we get the error we get something like the
below. Where on part of the error mentions OpenAI but the rest of the
error returns the actual error from provider. This PR tries to make the
error generic for now so that people don't get confused seeing OpenAI in
their v0 integration.

```
Error interacting with language model
Failed to connect to OpenAI API: 403 Forbidden {"success":false,"error":"Premium or Team plan required to access the v0 API: https://v0.dev/chat/settings/billing"}
```

Release Notes:

- N/A
2025-06-28 14:38:27 +02:00
alphaArgon
1d684c8890 Add shadow back for blurred/transparent window on macOS (#27403)
Closes #15383
Closes #10993

`NSVisualEffectView` is an official API for implementing blur effects
and, by traversing the layers, we **can remove the background color**
that comes with the view. This avoids using private APIs and aligns
better with macOS’s native design.

Currently, `GPUIView` serves as the content view of the window. To add
the blurred view, `GPUIView` is downgraded to a subview of the content
view, placed at the same level as the blurred view.

Release Notes:

- Fixed the missing shadow for blurred-background windows on macOS.

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
2025-06-28 09:50:54 +03:00
Rift
97c5c5a6e7 vim: Respect count for paragraphs (#33489)
Closes #32462 

Release Notes:

- vim: Paragraph objects now support counts (`d2ap`, `v2ap`, etc.)

---------

Co-authored-by: Rift <no@e.mail>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
2025-06-27 22:05:47 -06:00
5brian
ba4fc1bcfc vim: Add debug panel ex command (#33560)
Added :Debug to open debug panel, also added
[:display](https://neovim.io/doc/user/change.html#%3Adisplay), alias to
:reg

Release Notes:

- N/A
2025-06-27 21:32:40 -06:00
Smit Barmase
bbf16bda75 editor: Improve rewrap to respect indent and prefix boundaries (#33566)
1. Fixes bug where this would not rewrap:

```rs
// This is the first long comment block to be wrapped.
fn my_func(a: u32);
// This is the second long comment block to be wrapped.
```
2. Comment prefix boundaries (Notice now they don't merge between
different comment prefix):

Initial text:
```rs
// A regular long long comment to be wrapped.
// A second regular long comment to be wrapped.
/// A documentation long comment to be wrapped.
```
Upon rewrap:
```rs
// A regular long long comment to be
// wrapped. A second regular long
// comment to be wrapped.
/// A documentation long comment to be
/// wrapped.
```
3. Indent boundaries (Notice now they don't merge between different
indentation):

Initial text:
```rs
fn foo() {
      // This is a long comment at the base indent.
      // This is a long comment at the base indent.
                 // This is a long comment at the next indent.
                 // This is a long comment at the next indent.
      // This is a long comment at the base indent.
}
```
Upon rewrap:
```rs
fn foo() {
      // This is a long comment at the base
      // indent. This is a long comment at the
      // base indent.
                 // This is a long comment at the 
                 // next indent. This is a long 
                 // comment at the next indent.
      // This is a long comment at the base
      // indent.
}
```

Release Notes:

- Fixed an issue where rewrap would not work with selection when two
comment blocks are separated with line of code.
- Improved rewrap to respect changes in indentation or comment prefix
(e.g. `//` vs `///`) as boundaries so that it doesn't merge them into
one mangled text.
2025-06-28 05:38:18 +05:30
ddoemonn
c56b8904cc Prevent branch name overflow in git panel selection (#33529)
Closes #33527

Release Notes:

- Fixed long branch names overflowing to multiple lines in git panel
branch selector

---------

Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-06-27 20:50:53 -03:00
Artem Loenko
695118d110 agent: Show provider icon in model selectors (#30595)
I often switch between models, and I believe many people do. Currently,
it is difficult to determine which provider offers the selected model
because the same models are available from different providers. I
propose a simple change to the selector so that users can distinguish
between providers from the model they have chosen.

As a side note, I would actually prefer to have a text label with the
provider’s name next to the model name in the selector. However, I
understand that this is too opinionated and takes up too much space.

| Before | After |
| ------ | ------ |
|
![before_inline_assist](https://github.com/user-attachments/assets/35617ba5-e8d4-4dab-a997-f7286f73f2bf)
|
![after_inline_assist](https://github.com/user-attachments/assets/c37c81b4-73e4-49e2-955d-b8543b2855ad)
|
|
![before_text_thread](https://github.com/user-attachments/assets/af90303b-12d6-402c-90a5-8b36cd97396e)
|
![after_text_thread](https://github.com/user-attachments/assets/bca5b423-f12b-4eaf-a82e-424d09b7f447)
|
|
![before_thread](https://github.com/user-attachments/assets/0946775f-1d52-437b-a217-9708ee2e789a)
|
![after_thread](https://github.com/user-attachments/assets/f5e53968-9020-446f-9d5e-653ae9fdea3e)
|

Release Notes:

- The model selector has been improved with a provider icon, making it
easier to distinguish between providers.

---------

Co-authored-by: Danilo Leal <67129314+danilo-leal@users.noreply.github.com>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
2025-06-27 19:33:58 -03:00
Conrad Irwin
a675ca7a1e Remove into SelectionEffects from .change_selections (#33554)
In #32656 I generalized the argument to change selections to allow
controling both the scroll and the nav history (and the completion
trigger).

To avoid conflicting with ongoing debugger cherry-picks I left the
argument as an `impl Into<>`, but I think it's clearer to make callers
specify what they want here.

I converted a lot of `None` arguments to `SelectionEffects::no_scroll()`
to be exactly compatible; but I think many people used none as an "i
don't care" value in which case Default::default() might be more
appropraite

Closes #ISSUE

Release Notes:

- N/A
2025-06-27 14:31:31 -06:00
Conrad Irwin
6e762d9c05 Revert "Remove into SelectionEffects from .change_selections"
This reverts commit 28380d714d.
2025-06-27 14:06:17 -06:00
Conrad Irwin
28380d714d Remove into SelectionEffects from .change_selections
In #32656 I generalized the argument to change selections to allow
controling both the scroll and the nav history (and the completion
trigger).

To avoid conflicting with ongoing debugger cherry-picks I left the
argument as an `impl Into<>`, but I think it's clearer to make callers
specify what they want here.

I converted a lot of `None` arguments to `SelectionEffects::no_scroll()`
to be exactly compatible; but I think many people used none as an "i
don't care" value in which case Default::default() might be more
appropraite
2025-06-27 14:03:45 -06:00
Alejandro Fernández Gómez
f338c46bf7 Fix line indices when using a selection in the context (#33549)
Closes #33152.

The label for a file selection context had an off-by-one error on line
indices. This PR adjusts that.

Before:

<img width="1072" alt="Screenshot 2025-06-27 at 20 55 28"
src="https://github.com/user-attachments/assets/da0be503-056b-442b-9a79-38cf504d8a44"
/>

After:

<img width="1090" alt="Screenshot 2025-06-27 at 20 49 35"
src="https://github.com/user-attachments/assets/f98df57a-8f07-4ea5-a06b-a4b6fb8c2e4e"
/>


Release Notes:

- Fixed a off-by-one error on the line indices when using a selection as
context for the agent,
2025-06-27 13:41:17 -06:00
Umesh Yadav
5fbb7b0d40 copilot: Only set Copilot-Vision-Request header for vision requests (#33552)
Closes #31951

The fix is copied and translated from copilot chat actual implementation
code:
ad7cbcae9a/src/platform/openai/node/fetch.ts (L493C1-L495C3)

Release Notes:

- Fix copilot failing due to missing `Copilot-Vision-Request` from
request.
2025-06-27 21:37:26 +02:00
Cole Miller
f12b0dddf4 Touch up extension DAP schemas fix (#33548)
Updates #33546 

Release Notes:

- N/A

Co-authored-by: Piotr <piotr@zed.dev>
2025-06-27 15:34:21 -04:00
Conrad Irwin
14bb10d783 Don't panic on vintage files (#33543)
Release Notes:

- remoting: Fix a crash on the remote side when encountering files from
before 1970.
2025-06-27 13:15:50 -06:00
Cole Miller
c9ce4aec91 Fix debug adapters from extensions not being picked up (#33546)
Copy the debug adapter schemas so that they're available to the
extension host, like we do for other extension assets.

Release Notes:

- N/A
2025-06-27 14:31:58 -04:00
Kirill Bulatov
01dfb6fa82 Respect server capabilities on queries (#33538)
Closes https://github.com/zed-industries/zed/issues/33522

Turns out a bunch of Zed requests were not checking their capabilities
correctly, due to odd copy-paste and due to default that assumed that
the capabilities are met.

Adjust the code, which includes the document colors, add the test on the
colors case.

Release Notes:

- Fixed excessive document colors requests for unrelated files
2025-06-27 16:31:40 +00:00
5brian
f9987a1141 vim: Grep in visual line (#33414)
From
https://github.com/zed-industries/zed/pull/10831#issuecomment-2078523272

> I agree with not prefilling the search bar with a multiline query.

Not sure if it's a bug that a one-line visual line selection does not
get pre filled, this PR corrects the query to use the visual line
selection instead of the 'normal' selection

Release Notes:

- N/A
2025-06-27 10:18:26 -06:00
Ben Kunkle
7432e947bc Add element_selection_background highlight to theme (#32388)
Closes #32354

The issue is that we render selections over the text in the agent panel,
but under the text in editor, so themes that have no alpha for the
selection background color (defaults to 0xff) will just occlude the
selected region. Making the selection render under the text in markdown
would be a significant (and complicated) refactor, as selections can
cross element boundaries (i.e. spanning code block and a header after
the code block).

The solution is to add a new highlight to themes
`element_selection_background` that defaults to the local players
selection background with an alpha of 0.25 (roughly equal to 0x3D which
is the alpha we use for selection backgrounds in default themes) if the
alpha of the local players selection is 1.0. The idea here is to give
theme authors more control over how the selections look outside of
editor, as in the agent panel specifically, the background color is
different, so while an alpha of 0.25 looks acceptable, a different color
would likely be better.

CC: @iamnbutler. Would appreciate your thoughts on this. 

> Note: Before and after using Everforest theme

| Before | After | 
|-------| -----|
| <img width="618" alt="Screenshot 2025-06-09 at 5 23 10 PM"
src="https://github.com/user-attachments/assets/41c7aa02-5b3f-45c6-981c-646ab9e2a1f3"
/> | <img width="618" alt="Screenshot 2025-06-09 at 5 25 03 PM"
src="https://github.com/user-attachments/assets/dfb13ffc-1559-4f01-98f1-a7aea68079b7"
/> |

Clearly, the selection in the after doesn't look _that_ great, but it is
better than the before, and this PR makes the color of the selection
configurable by the theme so that this theme author could make it a
lighter color for better contrast.




Release Notes:

- agent panel: Fixed an issue with some themes where selections inside
the agent panel would occlude the selected text completely

Co-authored-by: Antonio <me@as-cii.com>
2025-06-27 15:46:04 +00:00
Conrad Irwin
157199b65b Replace newlines in search bar (#33504)
Release Notes:

- search: Pasted newlines are now rendered as "\n" (with an underline),
instead of line-wrapping. This should make it much clearer what you're
searching for.
 
<img width="675" alt="Screenshot 2025-06-27 at 00 34 52"
src="https://github.com/user-attachments/assets/67275bc6-bec1-463f-b351-6b9ed0a6df81"
/>
2025-06-27 09:39:38 -06:00
Conrad Irwin
d74f3f4ea6 Fix crash in git checkout (#33499)
Closes #33438

Release Notes:

- git: Use git cli to perform checkouts (to avoid a crash seen in
libgit2)
2025-06-27 09:16:15 -06:00
Smit Barmase
9e2023bffc editor: Fix editor tests from changing on format on save (#33532)
Use placeholder to prevent format-on-save from removing whitespace in
editor tests, which leads to unnecessary git diff and failing tests.

cc: https://github.com/zed-industries/zed/pull/32340

Release Notes:

- N/A
2025-06-27 20:14:01 +05:30
Umesh Yadav
3ab4ad6de8 language_models: Use JsonSchemaSubset for Gemini models in OpenRouter (#33477)
Closes #33466

Release Notes:

- N/A
2025-06-27 16:36:16 +02:00
Peter Tripp
e3ce0618a3 collab: Lookup avatars by GitHub ID instead of username (#33523)
Closes: https://github.com/zed-industries/zed/issues/19207

This will correctly show Avatars for recently renamed/deleted users and
for enterprise users where the username avatar url triggers a redirect
to an auth prompt. Also saves a request (302 redirect) per avatar.

Tested locally and avatars loaded as expected.

Release Notes:

- N/A
2025-06-27 09:40:50 -04:00
Kirill Bulatov
865dd4c5fc Rework LSP tool keyboard story (#33525)
https://github.com/user-attachments/assets/81da68fe-bbc5-4b23-8182-923c752a8bd2

* Removes all extra elements: headers, buttons, to simplify the menu
navigation approach and save space.
Implements the keyboard navigation and panel toggling.

* Keeps the status icon and the server name, and their ordering approach
(current buffer/other) in the menu.
The status icon can still be hovered, but that is not yet possible to
trigger from the keyboard: future ideas would be make a similar side
display instead of hover, as Zeta menu does:


![image](https://github.com/user-attachments/assets/c844bc39-00ed-4fe3-96d5-1c9d323a21cc)

* Allows to start (if all are stopped) and stop (if some are not
stopped) all servers at once now with the button at the bottom

Release Notes:

- N/A
2025-06-27 16:25:56 +03:00
Umesh Yadav
2178f66af6 agent_ui: Rename MaxModeTooltip to BurnModeTooltip (#33521)
Closes #ISSUE

Release Notes:

- N/A
2025-06-27 13:56:46 +02:00
ddoemonn
338a7395a7 Fix blend alpha colors with editor background in inline preview (#33513)
Closes #33505

## Before

<img width="434" alt="Screenshot 2025-06-27 at 12 22 57"
src="https://github.com/user-attachments/assets/ac215a39-b3fe-4c9e-bd7d-0d7568d5fd1f"
/>

## After

<img width="441" alt="Screenshot 2025-06-27 at 12 22 47"
src="https://github.com/user-attachments/assets/28218ed6-c1aa-4d3f-a268-def2fa9f0340"
/>

Release Notes:

- Fixed inline color previews not correctly blending alpha/transparency
values with the editor background
2025-06-27 12:37:05 +03:00
Finn Evers
4c2415b338 editor: Use em_advance everywhere for horizontal scroll position computations (#33514)
Closes #33472

This PR fixes some regressions that were introduced in
https://github.com/zed-industries/zed/pull/32558, which updated the
editor scrolling to use `em_advance` instead of `em_width` for the
horizontal scroll position calculation.
However, not all occurrences were updated, which caused issues with wrap
guides and some small stuttering with horizontal autoscroll whilst
typing/navigating with the keyboard.

Release Notes:

- Fixed an issue where horizontal autoscrolling would stutter and indent
guides would drift when scrolling horizontally.
2025-06-27 09:32:50 +00:00
Ron Harel
e6bc1308af Add SVG preview (#32694)
Closes #10454

Implements SVG file preview capability similar to the existing markdown
preview.
- Adds `svg_preview` crate with preview view and live reloading upon
file save.
- Integrates SVG preview button in quick action bar.
- File preview shortcuts (`ctrl/cmd+k v` and `ctrl/cmd+shift+v`) are
extension-aware.

Release Notes:

- Added SVG file preview, accessible via the quick action bar button or
keyboard shortcuts (`ctrl/cmd+k v` and `ctrl/cmd+shift+v`) when editing
SVG files.
2025-06-27 09:08:05 +00:00
Ben Brandt
6c46e1129d Cleanup remaining references to max mode (#33509)
Release Notes:

- N/A
2025-06-27 08:32:13 +00:00
fantacell
fbb5628ec6 Reset selection goal after helix motion (#33184)
Closes #33060

Motions like `NextWordStart` don't reset the selection goal in vim mode
`helix_normal` unlike in `normal` which can lead to the cursor jumping
back to the previous horizontal position after going up or down.

Release Notes:

- N/A
2025-06-26 22:32:35 -06:00
Conrad Irwin
8c9116daa5 Fix panic in ctrl-g (#33474)
Release Notes:

- vim: Fixed a crash with ctrl-g
2025-06-26 21:26:58 -06:00
Conrad Irwin
20a3e613b8 vim: Better jump list support (#33495)
Closes #23527
Closes #30183
Closes some Discord chats

Release Notes:

- vim: Motions now push to the jump list using the same logic as vim
(i.e.
`G`/`g g`/`g d` always do, but `j`/`k` always don't). Most non-vim
actions
(including clicking with the mouse) continue to push to the jump list
only
  when they move the cursor by 10 or more lines.
2025-06-26 21:25:07 -06:00
Ben Kunkle
ba1c05abf2 keymap: Add ability to update user keymaps (#33487)
Closes #ISSUE

The ability to update user keybindings in their keymap is required for
#32436. This PR adds the ability to do so, reusing much of the existing
infrastructure for updating settings JSON files.

However, the existing JSON update functionality was intended to work
only with objects, therefore, this PR simply wraps the object updating
code with non-general keymap-specific array updating logic, that only
works for top-level arrays and can only append or update entries in said
top-level arrays. This limited API is reflected in the limited
operations that the new `update_keymap` method on `KeymapFile` can take
as arguments.

Additionally, this PR pulls out the existing JSON updating code into its
own module (where array updating code has been added) and adds a
significant number of tests (hence the high line count in the diff)

Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-06-26 21:52:26 -04:00
Danilo Leal
2823771c06 Add design improvements to the LSP popover (#33485)
Not the ideal design just yet as that will probably require a different
approach altogether, but am pushing here just some reasonably small UI
adjustments that will make this feel slightly nicer!

Release Notes:

- N/A
2025-06-26 22:27:21 +00:00
Cole Miller
343f155ab9 Update docs for Swift debugging (#33483)
Release Notes:

- N/A *or* Added/Fixed/Improved ...
2025-06-26 21:25:03 +00:00
Julia Ryan
2dece13d83 nix: Update to access new rust toolchain version (#33476)
Needed due to #33439

Release Notes:

- N/A
2025-06-26 20:31:24 +00:00
Piotr Osiewicz
985dcf7523 chore: Bump Rust version to 1.88 (#33439)
Goodies in this version:
- if-let chains 🎉
- Better compiler perf for Zed
(https://github.com/rust-lang/rust/pull/138522)

For more, see: https://releases.rs/docs/1.88.0/

Release Notes:

- N/A

---------

Co-authored-by: Junkui Zhang <364772080@qq.com>
2025-06-26 20:54:19 +02:00
Conrad Irwin
b079871428 Fix subtraction with overflow (#33471)
Release Notes:

- N/A
2025-06-26 12:38:54 -06:00
fantacell
4983b01c89 helix: Change word motions (#33408)
When starting on the newline character at the end of a line the helix
word motions select that character, unlike in helix itself. This makes
it easy to accidentaly join two lines together.
Also, word motions that go backwards should stop at the start of a line.
I added that.

Release Notes:

- helix: Fix edge-cases with word motions and newlines
2025-06-26 12:25:47 -06:00
Cole Miller
35863c4302 debugger: Fix treatment of node-terminal scenarios (#33432)
- Normalize `node-terminal` to `pwa-node` before sending to DAP
- Split `command` into `program` and `args`
- Run in external console

Release Notes:

- debugger: Fixed debugging JavaScript tasks that used `"type":
"node-terminal"`.
2025-06-26 14:02:09 -04:00
Kirill Bulatov
a0bd25f218 Feature gate the LSP button (#33463)
Follow-up of https://github.com/zed-industries/zed/pull/32490

The tool still looks like designed by professional developers, and still
may change its UX based on the internal feedback.

Release Notes:

- N/A
2025-06-26 15:41:42 +00:00
Agus Zubiaga
8a1e795746 agent: Move ActiveThread and MessageEditor into ActiveView (#33462)
`ActiveThread` and `MessageEditor` only make sense when `active_view` is
`Thread`, so we moved them in there. This will make it easier to work on
new agent threads.

Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
Co-authored-by: Smit Barmase <heysmitbarmase@gmail.com>
2025-06-26 15:36:23 +00:00
Peter Tripp
f4818b648e linux: Add agent::ToggleBurnMode shortcut (super-ctrl-b) (#33458)
Follow-up to: 
- https://github.com/zed-industries/zed/pull/33452
- https://github.com/zed-industries/zed/pull/33190
- https://github.com/zed-industries/zed/pull/31630

Release Notes:

- N/A
2025-06-26 15:07:46 +00:00
Peter Tripp
7031ed8b87 ci: Fix duplicated/failed eval jobs (#33453)
I think this should fix the CI issues with Eval jobs:

1. Duplicated workflows because `synchronize` / `opened` were triggering
distinct runs. This caused failed job entries because the duplicated
workflows had a shared concurrency group and so one would pre-empt the
other.

3. Removes the no-op job, introduced as an attempted workaround in
   https://github.com/zed-industries/zed/pull/29420.

These should correctly show as "Skipped" now:

| Before | After |
| - | - |
| <img width="359" alt="Screenshot 2025-06-26 at 9 57 04"
src="https://github.com/user-attachments/assets/6ddd4f46-27c7-4d82-98ba-0f1166fc55e7"
/> | <img width="355" alt="Screenshot 2025-06-26 at 10 09 54"
src="https://github.com/user-attachments/assets/5faade2c-f17c-447a-9af9-6396f9e53016"
/> |

Release Notes:

- N/A
2025-06-26 11:01:16 -04:00
Richard Feldman
6073d2c93c Automatically retry when API is Overloaded or 500s (#33275)
<img width="484" alt="Screenshot 2025-06-25 at 2 26 16 PM"
src="https://github.com/user-attachments/assets/340f15d7-b115-4895-bae8-b12a915bfda1"
/>

<img width="460" alt="Screenshot 2025-06-25 at 2 26 08 PM"
src="https://github.com/user-attachments/assets/6e587a38-d542-405f-809f-402e87520538"
/>

Now we:
* Automatically retry up to 3 times on upstream Overloaded or 500 errors
(currently for Anthropic only; will add others in future PRs)
* Also automatically retry on rate limit errors (using the provided
duration to wait, if we were given one)
* Give you a notification if you don't have Zed open and we stopped the
thread because of an error

Still todo in future PRs:
* Update collab to report Overloaded and 500 errors differently if
collab itself is passing through an upstream error vs not (currently we
report these as "Zed's API is overloaded" when actually it's the
upstream one!)
* Updating providers other than Anthropic to categorize their errors so
that they benefit from this
* Expanding graceful error handling/retry to other things besides
Overloaded and 500 errors (e.g. connection reset)

Release Notes:

- Automatically retry in Agent Panel instead of erroring out when an
upstream AI API is overloaded or 500s
- Show a notification when an Agent thread errors out and Zed is not the
active window
2025-06-26 10:53:33 -04:00
Danilo Leal
00499aadd4 Add back default keybindings to Burn Mode and branch picker toggles (#33452)
Follow up to https://github.com/zed-industries/zed/pull/33190, as they
were removed because of conflict with VS Code's usage of those bindings
to toggle the right dock. `cmd-ctrl-b` seems like a safe alternative.
Note that this PR is macOS only, though. I couldn't find yet any good
options for Linux as they were all mostly conflicting with something
else.

Release Notes:

- N/A
2025-06-26 11:35:02 -03:00
Peter Tripp
d1eb69c6cd ci: Improve check_docs skipping (#33455)
Follow-up to: https://github.com/zed-industries/zed/pull/33398

Logic there was incomplete. Caused [this
failure](https://github.com/zed-industries/zed/actions/runs/15904169712/job/44854558276).

Release Notes:

- N/A
2025-06-26 14:34:20 +00:00
Marshall Bowers
40cbfb7eb2 docs: Add note about extension submodules needing to use HTTPS URLS (#33454)
This PR adds a note to the extension publishing docs about extension
submodules needing to use HTTPS URLs.

Release Notes:

- N/A
2025-06-26 14:18:56 +00:00
Peter Tripp
5d0f02d356 Add cmd-alt-b (workspace::ToggleRightDock) on macOS (#33450)
Release Notes:

- N/A
2025-06-26 13:54:21 +00:00
Renze Post
ca8e213151 Suggest reST extension for .rst files (#33413)
Suggest the reST extension when opening a .rst file for the first time.

Release Notes:

- N/A
2025-06-26 08:59:04 -04:00
Michael Sloan
90c893747c gpui: Prevent the same action name from being registered multiple times (#33359)
Also removes duplicate `editor::RevertFile` and `vim::HelixDelete`
actions

Release Notes:

- N/A
2025-06-26 06:24:14 +00:00
Smit Barmase
d09c7eb317 language: Add context-aware decrease indent for Python (#33370)
Closes #33238, follow-up to
https://github.com/zed-industries/zed/pull/29625.

Changes:

- Removed `significant_indentation`, which was the way to introduce
indentation scoping in languages like Python. However, it turned out to
be unnecessarily complicated to define and maintain.
- Introduced `decrease_indent_patterns`, which takes a `pattern` keyword
to automatically outdent and `valid_after` keywords to treat as valid
code points to snap to. The outdent happens to the most recent
`valid_after` keyword that also has less or equal indentation than the
currently typed keyword.

Fixes:

1. In Python, typing `except`, `finally`, `else`, and so on now
automatically indents intelligently based on the context in which it
appears. For instance:

```py
try:
    if a == 1:
        try:
             b = 2
             ^  # <-- typing "except:" here would indent it to inner try block
```

but,

```py
try:
    if a == 1:
        try:
             b = 2
    ^  # <-- typing "except:" here would indent it to outer try block
```

2. Fixes comments not maintaining indent.

Release Notes:

- Improved auto outdent for Python while typing keywords like `except`,
`else`, `finally`, etc.
- Fixed the issue where comments in Python would not maintain their
indentation.
2025-06-26 11:11:03 +05:30
Smit Barmase
1753432406 Fix tree sitter python try statement to accept missing else/except/finally (#33431)
We have fork now:
218fcbf3fd

Release Notes:

- N/A
2025-06-26 09:48:44 +05:30
Cole Miller
d9218b10ea Bump livekit-rust-sdks for candidate webrtc-sys build fix (#33387)
Incorporates https://github.com/zed-industries/livekit-rust-sdks/pull/5

Don't merge yet, waiting until after new releases are cut in case of
unexpected breakage.

Release Notes:

- N/A
2025-06-25 21:00:33 -04:00
Michael Sloan
dfdeb1bf51 linux: Don't insert characters if modifiers other than shift are held (#33424)
Closes #32219 #29666

Release Notes:

- Linux: Now skips insertion of characters when modifiers are held. Before, characters were inserted if there's no match in the keymap.
2025-06-25 17:11:59 -06:00
Max Brunsfeld
b9f81c7ce7 Restore missing initialization of text thread actions (#33422)
Fixes a regression introduced in
https://github.com/zed-industries/zed/pull/33289

Release Notes:

- Fixed a bug where some text thread actions were accidentally removed.
2025-06-25 22:48:40 +00:00
Michael Sloan
b1450b6d71 Remove git_panel::GenerateCommitMessage in favor of git::GenerateCommitMessage (#33421)
`git_panel::GenerateCommitMessage` has no handler,
`git::GenerateCommitMessage` should be preferred. Could add a
`#[action(deprecated_aliases = ["git_panel::GenerateCommitMessage"])]`,
but decided not to because that action didn't work. So instead uses of
it will show up as keymap errors.

Closes #32667

Release Notes:

- N/A
2025-06-25 22:29:30 +00:00
David Barsky
1af9f98c1d lsp-log: Avoid trimming leading space in language server logs (#33418)
Not sure what the full intention/right fix for this is, but
https://github.com/zed-industries/zed/pull/32659 re-introduced trimming
of leading spaces. rust-analyzer has [a custom tracing
formatter](317542c1e4/crates/rust-analyzer/src/tracing/hprof.rs)
that is _super_ useful for profiling what the heck rust-analyzer is
doing. It makes prodigious use of whitespace to delineate to create a
tree-shaped structure. This change reintroduces the leading whitespace.

I made a previous change similar to this that removed a `stderr:` in
https://github.com/zed-industries/zed/pull/27213/. If this is a
direction y'all are happy to go with, I'd be happy to add a test for
this!

<details>
<summary>A screenshot of the before</summary>

<img width="1624" alt="Screenshot 2025-06-25 at 2 12 45 PM"
src="https://github.com/user-attachments/assets/a714d973-9377-41ca-8087-3b0e82b41620"
/>

</details>

<details>
<summary>A screenshot of the after</summary>

<img width="1136" alt="Screenshot 2025-06-25 at 2 40 07 PM"
src="https://github.com/user-attachments/assets/b798ca13-11fc-4f97-9602-55e782068a5a"
/>

</details>

cc: @mgsloan.

Release Notes:

- Fixed the removal of leading whitespace in a language server's stderr
logs.
2025-06-25 16:24:51 -06:00
864 changed files with 65740 additions and 20412 deletions

View File

@@ -19,6 +19,8 @@ rustflags = [
"windows_slim_errors", # This cfg will reduce the size of `windows::core::Error` from 16 bytes to 4 bytes
"-C",
"target-feature=+crt-static", # This fixes the linking issue when compiling livekit on Windows
"-C",
"link-arg=-fuse-ld=lld",
]
[env]

View File

@@ -23,6 +23,8 @@ workspace-members = [
]
third-party = [
{ name = "reqwest", version = "0.11.27" },
# build of remote_server should not include scap / its x11 dependency
{ name = "scap", git = "https://github.com/zed-industries/scap", rev = "808aa5c45b41e8f44729d02e38fd00a2fe2722e7" },
]
[final-excludes]
@@ -33,7 +35,6 @@ workspace-members = [
"zed_emmet",
"zed_glsl",
"zed_html",
"perplexity",
"zed_proto",
"zed_ruff",
"slash_commands_example",

30
.github/actionlint.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
# Configuration related to self-hosted runner.
self-hosted-runner:
# Labels of self-hosted runner in array of strings.
labels:
# GitHub-hosted Runners
- github-8vcpu-ubuntu-2404
- github-16vcpu-ubuntu-2404
- windows-2025-16
- windows-2025-32
- windows-2025-64
# Buildjet Ubuntu 20.04 - AMD x86_64
- buildjet-2vcpu-ubuntu-2004
- buildjet-4vcpu-ubuntu-2004
- buildjet-8vcpu-ubuntu-2004
- buildjet-16vcpu-ubuntu-2004
- buildjet-32vcpu-ubuntu-2004
# Buildjet Ubuntu 22.04 - AMD x86_64
- buildjet-2vcpu-ubuntu-2204
- buildjet-4vcpu-ubuntu-2204
- buildjet-8vcpu-ubuntu-2204
- buildjet-16vcpu-ubuntu-2204
- buildjet-32vcpu-ubuntu-2204
# Buildjet Ubuntu 22.04 - Graviton aarch64
- buildjet-8vcpu-ubuntu-2204-arm
- buildjet-16vcpu-ubuntu-2204-arm
- buildjet-32vcpu-ubuntu-2204-arm
- buildjet-64vcpu-ubuntu-2204-arm
# Self Hosted Runners
- self-mini-macos
- self-32vcpu-windows-2022

View File

@@ -28,7 +28,7 @@ jobs:
run: |
set -eux
channel=$(cat crates/zed/RELEASE_CHANNEL)
channel="$(cat crates/zed/RELEASE_CHANNEL)"
tag_suffix=""
case $channel in
@@ -43,9 +43,9 @@ jobs:
;;
esac
which cargo-set-version > /dev/null || cargo install cargo-edit
output=$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')
output="$(cargo set-version -p zed --bump patch 2>&1 | sed 's/.* //')"
export GIT_COMMITTER_NAME="Zed Bot"
export GIT_COMMITTER_EMAIL="hi@zed.dev"
git commit -am "Bump to $output for @$GITHUB_ACTOR" --author "Zed Bot <hi@zed.dev>"
git tag v${output}${tag_suffix}
git push origin HEAD v${output}${tag_suffix}
git tag "v${output}${tag_suffix}"
git push origin HEAD "v${output}${tag_suffix}"

View File

@@ -21,6 +21,9 @@ env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
jobs:
job_spec:
@@ -30,6 +33,8 @@ jobs:
run_tests: ${{ steps.filter.outputs.run_tests }}
run_license: ${{ steps.filter.outputs.run_license }}
run_docs: ${{ steps.filter.outputs.run_docs }}
run_nix: ${{ steps.filter.outputs.run_nix }}
run_actionlint: ${{ steps.filter.outputs.run_actionlint }}
runs-on:
- ubuntu-latest
steps:
@@ -43,32 +48,40 @@ jobs:
run: |
if [ -z "$GITHUB_BASE_REF" ]; then
echo "Not in a PR context (i.e., push to main/stable/preview)"
COMPARE_REV=$(git rev-parse HEAD~1)
COMPARE_REV="$(git rev-parse HEAD~1)"
else
echo "In a PR context comparing to pull_request.base.ref"
git fetch origin "$GITHUB_BASE_REF" --depth=350
COMPARE_REV=$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD)
COMPARE_REV="$(git merge-base "origin/${GITHUB_BASE_REF}" HEAD)"
fi
# Specify anything which should skip full CI in this regex:
CHANGED_FILES="$(git diff --name-only "$COMPARE_REV" ${{ github.sha }})"
# Specify anything which should potentially skip full test suite in this regex:
# - docs/
# - script/update_top_ranking_issues/
# - .github/ISSUE_TEMPLATE/
# - .github/workflows/ (except .github/workflows/ci.yml)
SKIP_REGEX='^(docs/|\.github/(ISSUE_TEMPLATE|workflows/(?!ci)))'
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -vP "$SKIP_REGEX") ]]; then
echo "run_tests=true" >> $GITHUB_OUTPUT
else
echo "run_tests=false" >> $GITHUB_OUTPUT
fi
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^docs/') ]]; then
echo "run_docs=true" >> $GITHUB_OUTPUT
else
echo "run_docs=false" >> $GITHUB_OUTPUT
fi
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^Cargo.lock') ]]; then
echo "run_license=true" >> $GITHUB_OUTPUT
else
echo "run_license=false" >> $GITHUB_OUTPUT
fi
SKIP_REGEX='^(docs/|script/update_top_ranking_issues/|\.github/(ISSUE_TEMPLATE|workflows/(?!ci)))'
echo "$CHANGED_FILES" | grep -qvP "$SKIP_REGEX" && \
echo "run_tests=true" >> "$GITHUB_OUTPUT" || \
echo "run_tests=false" >> "$GITHUB_OUTPUT"
echo "$CHANGED_FILES" | grep -qP '^docs/' && \
echo "run_docs=true" >> "$GITHUB_OUTPUT" || \
echo "run_docs=false" >> "$GITHUB_OUTPUT"
echo "$CHANGED_FILES" | grep -qP '^\.github/(workflows/|actions/|actionlint.yml)' && \
echo "run_actionlint=true" >> "$GITHUB_OUTPUT" || \
echo "run_actionlint=false" >> "$GITHUB_OUTPUT"
echo "$CHANGED_FILES" | grep -qP '^(Cargo.lock|script/.*licenses)' && \
echo "run_license=true" >> "$GITHUB_OUTPUT" || \
echo "run_license=false" >> "$GITHUB_OUTPUT"
echo "$CHANGED_FILES" | grep -qP '^(nix/|flake\.|Cargo\.|rust-toolchain.toml|\.cargo/config.toml)' && \
echo "run_nix=true" >> "$GITHUB_OUTPUT" || \
echo "run_nix=false" >> "$GITHUB_OUTPUT"
migration_checks:
name: Check Postgres and Protobuf migrations, mergability
@@ -78,8 +91,7 @@ jobs:
needs.job_spec.outputs.run_tests == 'true'
timeout-minutes: 60
runs-on:
- self-hosted
- macOS
- self-mini-macos
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -101,11 +113,11 @@ jobs:
run: |
if [ -z "$GITHUB_BASE_REF" ];
then
echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> $GITHUB_ENV
echo "BUF_BASE_BRANCH=$(git merge-base origin/main HEAD)" >> "$GITHUB_ENV"
else
git checkout -B temp
git merge -q origin/$GITHUB_BASE_REF -m "merge main into temp"
echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> $GITHUB_ENV
git merge -q "origin/$GITHUB_BASE_REF" -m "merge main into temp"
echo "BUF_BASE_BRANCH=$GITHUB_BASE_REF" >> "$GITHUB_ENV"
fi
- uses: bufbuild/buf-setup-action@v1
@@ -129,7 +141,7 @@ jobs:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install cargo-hakari
uses: clechasseur/rs-cargo@8435b10f6e71c2e3d4d3b7573003a8ce4bfc6386 # v2
with:
@@ -167,7 +179,7 @@ jobs:
- name: Prettier Check on /docs
working-directory: ./docs
run: |
pnpm dlx prettier@${PRETTIER_VERSION} . --check || {
pnpm dlx "prettier@${PRETTIER_VERSION}" . --check || {
echo "To fix, run from the root of the Zed repo:"
echo " cd docs && pnpm dlx prettier@${PRETTIER_VERSION} . --write && cd .."
false
@@ -177,7 +189,7 @@ jobs:
- name: Prettier Check on default.json
run: |
pnpm dlx prettier@${PRETTIER_VERSION} assets/settings/default.json --check || {
pnpm dlx "prettier@${PRETTIER_VERSION}" assets/settings/default.json --check || {
echo "To fix, run from the root of the Zed repo:"
echo " pnpm dlx prettier@${PRETTIER_VERSION} assets/settings/default.json --write"
false
@@ -223,6 +235,20 @@ jobs:
- name: Build docs
uses: ./.github/actions/build_docs
actionlint:
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries' && needs.job_spec.outputs.run_actionlint == 'true'
needs: [job_spec]
steps:
- uses: actions/checkout@v4
- name: Download actionlint
id: get_actionlint
run: bash <(curl https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
shell: bash
- name: Check workflow files
run: ${{ steps.get_actionlint.outputs.executable }} -color
shell: bash
macos_tests:
timeout-minutes: 60
name: (macOS) Run Clippy and tests
@@ -231,8 +257,7 @@ jobs:
github.repository_owner == 'zed-industries' &&
needs.job_spec.outputs.run_tests == 'true'
runs-on:
- self-hosted
- macOS
- self-mini-macos
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -301,7 +326,7 @@ jobs:
- buildjet-16vcpu-ubuntu-2204
steps:
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -353,7 +378,7 @@ jobs:
- buildjet-8vcpu-ubuntu-2204
steps:
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -383,7 +408,7 @@ jobs:
windows_tests:
timeout-minutes: 60
name: (Windows) Run Tests
name: (Windows) Run Clippy and tests
needs: [job_spec]
if: |
github.repository_owner == 'zed-industries' &&
@@ -404,11 +429,10 @@ jobs:
with:
clean: false
- name: Setup Cargo and Rustup
- name: Configure CI
run: |
mkdir -p ${{ env.CARGO_HOME }} -ErrorAction Ignore
cp ./.cargo/ci-config.toml ${{ env.CARGO_HOME }}/config.toml
.\script\install-rustup.ps1
New-Item -ItemType Directory -Path "./../.cargo" -Force
Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml"
- name: cargo clippy
run: |
@@ -423,18 +447,9 @@ jobs:
- name: Limit target directory size
run: ./script/clear-target-dir-if-larger-than.ps1 250
# - name: Check dev drive space
# working-directory: ${{ env.ZED_WORKSPACE }}
# # `setup-dev-driver.ps1` creates a 100GB drive, with CI taking up ~45GB of the drive.
# run: ./script/exit-ci-if-dev-drive-is-full.ps1 95
# Since the Windows runners are stateful, so we need to remove the config file to prevent potential bug.
- name: Clean CI config file
if: always()
run: |
if (Test-Path "${{ env.CARGO_HOME }}/config.toml") {
Remove-Item -Path "${{ env.CARGO_HOME }}/config.toml" -Force
}
run: Remove-Item -Recurse -Path "./../.cargo" -Force -ErrorAction SilentlyContinue
tests_pass:
name: Tests Pass
@@ -443,6 +458,7 @@ jobs:
- job_spec
- style
- check_docs
- actionlint
- migration_checks
# run_tests: If adding required tests, add them here and to script below.
- workspace_hack
@@ -460,7 +476,14 @@ jobs:
RET_CODE=0
# Always check style
[[ "${{ needs.style.result }}" != 'success' ]] && { RET_CODE=1; echo "style tests failed"; }
[[ "${{ needs.check_docs.result }}" != 'success' ]] && { RET_CODE=1; echo "docs checks failed"; }
if [[ "${{ needs.job_spec.outputs.run_docs }}" == "true" ]]; then
[[ "${{ needs.check_docs.result }}" != 'success' ]] && { RET_CODE=1; echo "docs checks failed"; }
fi
if [[ "${{ needs.job_spec.outputs.run_actionlint }}" == "true" ]]; then
[[ "${{ needs.actionlint.result }}" != 'success' ]] && { RET_CODE=1; echo "actionlint checks failed"; }
fi
# Only check test jobs if they were supposed to run
if [[ "${{ needs.job_spec.outputs.run_tests }}" == "true" ]]; then
@@ -481,8 +504,7 @@ jobs:
timeout-minutes: 120
name: Create a macOS bundle
runs-on:
- self-hosted
- bundle
- self-mini-macos
if: |
startsWith(github.ref, 'refs/tags/v')
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
@@ -493,9 +515,6 @@ jobs:
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps:
- name: Install Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
@@ -578,10 +597,6 @@ jobs:
startsWith(github.ref, 'refs/tags/v')
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
needs: [linux_tests]
env:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -635,10 +650,6 @@ jobs:
startsWith(github.ref, 'refs/tags/v')
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
needs: [linux_tests]
env:
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -687,20 +698,18 @@ jobs:
timeout-minutes: 60
runs-on: github-8vcpu-ubuntu-2404
if: |
false && (
startsWith(github.ref, 'refs/tags/v')
|| contains(github.event.pull_request.labels.*.name, 'run-bundling')
)
needs: [linux_tests]
name: Build Zed on FreeBSD
# env:
# MYTOKEN : ${{ secrets.MYTOKEN }}
# MYTOKEN2: "value2"
steps:
- uses: actions/checkout@v4
- name: Build FreeBSD remote-server
id: freebsd-build
uses: vmactions/freebsd-vm@c3ae29a132c8ef1924775414107a97cac042aad5 # v1.2.0
with:
# envs: "MYTOKEN MYTOKEN2"
usesh: true
release: 13.5
copyback: true
@@ -744,24 +753,77 @@ jobs:
nix-build:
name: Build with Nix
uses: ./.github/workflows/nix.yml
if: github.repository_owner == 'zed-industries' && contains(github.event.pull_request.labels.*.name, 'run-nix')
needs: [job_spec]
if: github.repository_owner == 'zed-industries' &&
(contains(github.event.pull_request.labels.*.name, 'run-nix') ||
needs.job_spec.outputs.run_nix == 'true')
secrets: inherit
with:
flake-output: debug
# excludes the final package to only cache dependencies
cachix-filter: "-zed-editor-[0-9.]*-nightly"
bundle-windows-x64:
timeout-minutes: 120
name: Create a Windows installer
runs-on: [self-hosted, Windows, X64]
if: false && (startsWith(github.ref, 'refs/tags/v') || contains(github.event.pull_request.labels.*.name, 'run-bundling'))
needs: [windows_tests]
env:
AZURE_TENANT_ID: ${{ secrets.AZURE_SIGNING_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_SIGNING_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_SIGNING_CLIENT_SECRET }}
ACCOUNT_NAME: ${{ vars.AZURE_SIGNING_ACCOUNT_NAME }}
CERT_PROFILE_NAME: ${{ vars.AZURE_SIGNING_CERT_PROFILE_NAME }}
ENDPOINT: ${{ vars.AZURE_SIGNING_ENDPOINT }}
FILE_DIGEST: SHA256
TIMESTAMP_DIGEST: SHA256
TIMESTAMP_SERVER: "http://timestamp.acs.microsoft.com"
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
clean: false
- name: Determine version and release channel
working-directory: ${{ env.ZED_WORKSPACE }}
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
run: |
# This exports RELEASE_CHANNEL into env (GITHUB_ENV)
script/determine-release-channel.ps1
- name: Build Zed installer
working-directory: ${{ env.ZED_WORKSPACE }}
run: script/bundle-windows.ps1
- name: Upload installer (x86_64) to Workflow - zed (run-bundling)
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: contains(github.event.pull_request.labels.*.name, 'run-bundling')
with:
name: ZedEditorUserSetup-x64-${{ github.event.pull_request.head.sha || github.sha }}.exe
path: ${{ env.SETUP_PATH }}
- name: Upload Artifacts to release
uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v1
# Re-enable when we are ready to publish windows preview releases
if: ${{ !(contains(github.event.pull_request.labels.*.name, 'run-bundling')) && env.RELEASE_CHANNEL == 'preview' }} # upload only preview
with:
draft: true
prerelease: ${{ env.RELEASE_CHANNEL == 'preview' }}
files: ${{ env.SETUP_PATH }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
auto-release-preview:
name: Auto release preview
if: |
startsWith(github.ref, 'refs/tags/v')
&& endsWith(github.ref, '-pre') && !endsWith(github.ref, '.0-pre')
needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64, freebsd]
needs: [bundle-mac, bundle-linux-x86_x64, bundle-linux-aarch64, bundle-windows-x64]
runs-on:
- self-hosted
- bundle
- self-mini-macos
steps:
- name: gh release
run: gh release edit $GITHUB_REF_NAME --draft=false
run: gh release edit "$GITHUB_REF_NAME" --draft=false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -18,7 +18,7 @@ jobs:
URL="https://zed.dev/releases/stable/latest"
fi
echo "URL=$URL" >> $GITHUB_OUTPUT
echo "URL=$URL" >> "$GITHUB_OUTPUT"
- name: Get content
uses: 2428392/gh-truncate-string-action@b3ff790d21cf42af3ca7579146eedb93c8fb0757 # v1.4.1
id: get-content
@@ -50,9 +50,9 @@ jobs:
PREVIEW_TAG="${VERSION}-pre"
if git rev-parse "$PREVIEW_TAG" > /dev/null 2>&1; then
echo "was_promoted_from_preview=true" >> $GITHUB_OUTPUT
echo "was_promoted_from_preview=true" >> "$GITHUB_OUTPUT"
else
echo "was_promoted_from_preview=false" >> $GITHUB_OUTPUT
echo "was_promoted_from_preview=false" >> "$GITHUB_OUTPUT"
fi
- name: Send release notes email

View File

@@ -79,12 +79,12 @@ jobs:
- name: Build docker image
run: |
docker build -f Dockerfile-collab \
--build-arg GITHUB_SHA=$GITHUB_SHA \
--tag registry.digitalocean.com/zed/collab:$GITHUB_SHA \
--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}
run: docker push "registry.digitalocean.com/zed/collab:${GITHUB_SHA}"
- name: Prune Docker system
run: docker system prune --filter 'until=72h' -f
@@ -131,7 +131,8 @@ jobs:
source script/lib/deploy-helpers.sh
export_vars_for_environment $ZED_KUBE_NAMESPACE
export ZED_DO_CERTIFICATE_ID=$(doctl compute certificate list --format ID --no-header)
ZED_DO_CERTIFICATE_ID="$(doctl compute certificate list --format ID --no-header)"
export ZED_DO_CERTIFICATE_ID
export ZED_IMAGE_ID="registry.digitalocean.com/zed/collab:${GITHUB_SHA}"
export ZED_SERVICE_NAME=collab

View File

@@ -7,7 +7,7 @@ on:
pull_request:
branches:
- "**"
types: [opened, synchronize, reopened, labeled]
types: [synchronize, reopened, labeled]
workflow_dispatch:
@@ -25,16 +25,6 @@ env:
ZED_EVAL_TELEMETRY: 1
jobs:
# This is a no-op job that we run to prevent GitHub from marking the workflow
# as failed for PRs that don't have the `run-eval` label.
noop:
name: No-op
runs-on: ubuntu-latest
if: github.repository_owner == 'zed-industries'
steps:
- name: No-op
run: echo "Nothing to do"
run_eval:
timeout-minutes: 60
name: Run Agent Eval
@@ -45,7 +35,7 @@ jobs:
- buildjet-16vcpu-ubuntu-2204
steps:
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

View File

@@ -43,8 +43,8 @@ jobs:
- name: Set path
if: ${{ ! matrix.system.install_nix }}
run: |
echo "/nix/var/nix/profiles/default/bin" >> $GITHUB_PATH
echo "/Users/administrator/.nix-profile/bin" >> $GITHUB_PATH
echo "/nix/var/nix/profiles/default/bin" >> "$GITHUB_PATH"
echo "/Users/administrator/.nix-profile/bin" >> "$GITHUB_PATH"
- uses: cachix/install-nix-action@02a151ada4993995686f9ed4f1be7cfbb229e56f # v31
if: ${{ matrix.system.install_nix }}
@@ -56,11 +56,13 @@ jobs:
name: zed
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
pushFilter: "${{ inputs.cachix-filter }}"
cachixArgs: '-v'
cachixArgs: "-v"
- run: nix build .#${{ inputs.flake-output }} -L --accept-flake-config
- name: Limit /nix/store to 50GB on macs
if: ${{ ! matrix.system.install_nix }}
run: |
[ $(du -sm /nix/store | cut -f1) -gt 50000 ] && nix-collect-garbage -d || :
if [ "$(du -sm /nix/store | cut -f1)" -gt 50000 ]; then
nix-collect-garbage -d || true
fi

View File

@@ -12,6 +12,9 @@ env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: 1
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
jobs:
style:
@@ -51,13 +54,38 @@ jobs:
- name: Run tests
uses: ./.github/actions/run_tests
windows-tests:
timeout-minutes: 60
name: Run tests on Windows
if: github.repository_owner == 'zed-industries'
runs-on: [self-hosted, Windows, X64]
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
clean: false
- name: Configure CI
run: |
New-Item -ItemType Directory -Path "./../.cargo" -Force
Copy-Item -Path "./.cargo/ci-config.toml" -Destination "./../.cargo/config.toml"
- name: Run tests
uses: ./.github/actions/run_tests_windows
- name: Limit target directory size
run: ./script/clear-target-dir-if-larger-than.ps1 1024
- name: Clean CI config file
if: always()
run: Remove-Item -Recurse -Path "./../.cargo" -Force -ErrorAction SilentlyContinue
bundle-mac:
timeout-minutes: 60
name: Create a macOS bundle
if: github.repository_owner == 'zed-industries'
runs-on:
- self-hosted
- bundle
- self-mini-macos
needs: tests
env:
MACOS_CERTIFICATE: ${{ secrets.MACOS_CERTIFICATE }}
@@ -65,9 +93,6 @@ jobs:
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
APPLE_NOTARIZATION_ISSUER_ID: ${{ secrets.APPLE_NOTARIZATION_ISSUER_ID }}
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Install Node
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
@@ -99,10 +124,6 @@ jobs:
runs-on:
- buildjet-16vcpu-ubuntu-2004
needs: tests
env:
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -110,7 +131,7 @@ jobs:
clean: false
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Install Linux dependencies
run: ./script/linux && ./script/install-mold 2.34.0
@@ -138,10 +159,6 @@ jobs:
runs-on:
- buildjet-16vcpu-ubuntu-2204-arm
needs: tests
env:
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
ZED_CLIENT_CHECKSUM_SEED: ${{ secrets.ZED_CLIENT_CHECKSUM_SEED }}
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
@@ -169,12 +186,9 @@ jobs:
freebsd:
timeout-minutes: 60
if: github.repository_owner == 'zed-industries'
if: false && github.repository_owner == 'zed-industries'
runs-on: github-8vcpu-ubuntu-2404
needs: tests
env:
DIGITALOCEAN_SPACES_ACCESS_KEY: ${{ secrets.DIGITALOCEAN_SPACES_ACCESS_KEY }}
DIGITALOCEAN_SPACES_SECRET_KEY: ${{ secrets.DIGITALOCEAN_SPACES_SECRET_KEY }}
name: Build Zed on FreeBSD
# env:
# MYTOKEN : ${{ secrets.MYTOKEN }}
@@ -213,10 +227,49 @@ jobs:
bundle-nix:
name: Build and cache Nix package
if: false
needs: tests
secrets: inherit
uses: ./.github/workflows/nix.yml
bundle-windows-x64:
timeout-minutes: 60
name: Create a Windows installer
if: github.repository_owner == 'zed-industries'
runs-on: [self-hosted, Windows, X64]
needs: windows-tests
env:
AZURE_TENANT_ID: ${{ secrets.AZURE_SIGNING_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_SIGNING_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_SIGNING_CLIENT_SECRET }}
ACCOUNT_NAME: ${{ vars.AZURE_SIGNING_ACCOUNT_NAME }}
CERT_PROFILE_NAME: ${{ vars.AZURE_SIGNING_CERT_PROFILE_NAME }}
ENDPOINT: ${{ vars.AZURE_SIGNING_ENDPOINT }}
FILE_DIGEST: SHA256
TIMESTAMP_DIGEST: SHA256
TIMESTAMP_SERVER: "http://timestamp.acs.microsoft.com"
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
clean: false
- name: Set release channel to nightly
working-directory: ${{ env.ZED_WORKSPACE }}
run: |
$ErrorActionPreference = "Stop"
$version = git rev-parse --short HEAD
Write-Host "Publishing version: $version on release channel nightly"
"nightly" | Set-Content -Path "crates/zed/RELEASE_CHANNEL"
- name: Build Zed installer
working-directory: ${{ env.ZED_WORKSPACE }}
run: script/bundle-windows.ps1
- name: Upload Zed Nightly
working-directory: ${{ env.ZED_WORKSPACE }}
run: script/upload-nightly.ps1 windows
update-nightly-tag:
name: Update nightly tag
if: github.repository_owner == 'zed-industries'
@@ -225,6 +278,7 @@ jobs:
- bundle-mac
- bundle-linux-x86
- bundle-linux-arm
- bundle-windows-x64
steps:
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

View File

@@ -26,7 +26,7 @@ jobs:
- buildjet-16vcpu-ubuntu-2204
steps:
- name: Add Rust to the PATH
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH
run: echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
- name: Checkout repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

View File

@@ -5,9 +5,7 @@
"build": {
"label": "Build Zed",
"command": "cargo",
"args": [
"build"
]
"args": ["build"]
}
},
{
@@ -16,9 +14,7 @@
"build": {
"label": "Build Zed",
"command": "cargo",
"args": [
"build"
]
"args": ["build"]
}
},
}
]

View File

@@ -40,7 +40,7 @@
},
"file_types": {
"Dockerfile": ["Dockerfile*[!dockerignore]"],
"JSONC": ["assets/**/*.json", "renovate.json"],
"JSONC": ["**/assets/**/*.json", "renovate.json"],
"Git Ignore": ["dockerignore"]
},
"hard_tabs": false,

477
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,9 +2,12 @@
resolver = "2"
members = [
"crates/activity_indicator",
"crates/acp_thread",
"crates/agent_ui",
"crates/agent",
"crates/agent_settings",
"crates/ai_onboarding",
"crates/agent_servers",
"crates/anthropic",
"crates/askpass",
"crates/assets",
@@ -45,6 +48,7 @@ members = [
"crates/diagnostics",
"crates/docs_preprocessor",
"crates/editor",
"crates/explorer_command_injector",
"crates/eval",
"crates/extension",
"crates/extension_api",
@@ -95,12 +99,16 @@ members = [
"crates/markdown_preview",
"crates/media",
"crates/menu",
"crates/svg_preview",
"crates/migrator",
"crates/mistral",
"crates/multi_buffer",
"crates/nc",
"crates/net",
"crates/node_runtime",
"crates/notifications",
"crates/ollama",
"crates/onboarding",
"crates/open_ai",
"crates/open_router",
"crates/outline",
@@ -174,6 +182,7 @@ members = [
"crates/welcome",
"crates/workspace",
"crates/worktree",
"crates/x_ai",
"crates/zed",
"crates/zed_actions",
"crates/zeta",
@@ -187,7 +196,6 @@ members = [
"extensions/emmet",
"extensions/glsl",
"extensions/html",
"extensions/perplexity",
"extensions/proto",
"extensions/ruff",
"extensions/slash-commands-example",
@@ -214,11 +222,14 @@ edition = "2024"
# Workspace member crates
#
activity_indicator = { path = "crates/activity_indicator" }
acp_thread = { path = "crates/acp_thread" }
agent = { path = "crates/agent" }
activity_indicator = { path = "crates/activity_indicator" }
agent_ui = { path = "crates/agent_ui" }
agent_settings = { path = "crates/agent_settings" }
agent_servers = { path = "crates/agent_servers" }
ai = { path = "crates/ai" }
ai_onboarding = { path = "crates/ai_onboarding" }
anthropic = { path = "crates/anthropic" }
askpass = { path = "crates/askpass" }
assets = { path = "crates/assets" }
@@ -304,14 +315,18 @@ lmstudio = { path = "crates/lmstudio" }
lsp = { path = "crates/lsp" }
markdown = { path = "crates/markdown" }
markdown_preview = { path = "crates/markdown_preview" }
svg_preview = { path = "crates/svg_preview" }
media = { path = "crates/media" }
menu = { path = "crates/menu" }
migrator = { path = "crates/migrator" }
mistral = { path = "crates/mistral" }
multi_buffer = { path = "crates/multi_buffer" }
nc = { path = "crates/nc" }
net = { path = "crates/net" }
node_runtime = { path = "crates/node_runtime" }
notifications = { path = "crates/notifications" }
ollama = { path = "crates/ollama" }
onboarding = { path = "crates/onboarding" }
open_ai = { path = "crates/open_ai" }
open_router = { path = "crates/open_router", features = ["schemars"] }
outline = { path = "crates/outline" }
@@ -386,6 +401,7 @@ web_search_providers = { path = "crates/web_search_providers" }
welcome = { path = "crates/welcome" }
workspace = { path = "crates/workspace" }
worktree = { path = "crates/worktree" }
x_ai = { path = "crates/x_ai" }
zed = { path = "crates/zed" }
zed_actions = { path = "crates/zed_actions" }
zeta = { path = "crates/zeta" }
@@ -396,6 +412,7 @@ zlog_settings = { path = "crates/zlog_settings" }
# External crates
#
agentic-coding-protocol = "0.0.10"
aho-corasick = "1.1"
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", branch = "add-hush-login-flag" }
any_vec = "0.14"
@@ -442,12 +459,12 @@ core-video = { version = "0.4.3", features = ["metal"] }
cpal = "0.16"
criterion = { version = "0.5", features = ["html_reports"] }
ctor = "0.4.0"
dap-types = { git = "https://github.com/zed-industries/dap-types", rev = "b40956a7f4d1939da67429d941389ee306a3a308" }
dap-types = { git = "https://github.com/zed-industries/dap-types", rev = "7f39295b441614ca9dbf44293e53c32f666897f9" }
dashmap = "6.0"
derive_more = "0.99.17"
dirs = "4.0"
documented = "0.9.1"
dotenv = "0.15.0"
dotenvy = "0.15.0"
ec4rs = "1.1"
emojis = "0.6.1"
env_logger = "0.11"
@@ -465,6 +482,7 @@ heed = { version = "0.21.0", features = ["read-txn-no-tls"] }
hex = "0.4.3"
html5ever = "0.27.0"
http = "1.1"
http-body = "1.0"
hyper = "0.14"
ignore = "0.4.22"
image = "0.25.1"
@@ -483,7 +501,7 @@ libc = "0.2"
libsqlite3-sys = { version = "0.30.1", features = ["bundled"] }
linkify = "0.10.0"
log = { version = "0.4.16", features = ["kv_unstable_serde", "serde"] }
lsp-types = { git = "https://github.com/zed-industries/lsp-types", rev = "c9c189f1c5dd53c624a419ce35bc77ad6a908d18" }
lsp-types = { git = "https://github.com/zed-industries/lsp-types", rev = "39f629bdd03d59abd786ed9fc27e8bca02c0c0ec" }
markup5ever_rcdom = "0.3.0"
metal = "0.29"
moka = { version = "0.12.10", features = ["sync"] }
@@ -498,6 +516,7 @@ ordered-float = "2.1.1"
palette = { version = "0.7.5", default-features = false, features = ["std"] }
parking_lot = "0.12.1"
partial-json-fixer = "0.5.3"
parse_int = "0.9"
pathdiff = "0.2"
pet = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" }
pet-conda = { git = "https://github.com/microsoft/python-environment-tools.git", rev = "845945b830297a50de0e24020b980a65e4820559" }
@@ -537,9 +556,10 @@ rustc-demangle = "0.1.23"
rustc-hash = "2.1.0"
rustls = { version = "0.23.26" }
rustls-platform-verifier = "0.5.0"
scap = { git = "https://github.com/zed-industries/scap", rev = "08f0a01417505cc0990b9931a37e5120db92e0d0", default-features = false }
schemars = { version = "0.8", features = ["impl_json_schema", "indexmap2"] }
scap = { git = "https://github.com/zed-industries/scap", rev = "808aa5c45b41e8f44729d02e38fd00a2fe2722e7", default-features = false }
schemars = { version = "1.0", features = ["indexmap2"] }
semver = "1.0"
sentry = { version = "0.41", default-features = false, features = ["reqwest", "rustls"] }
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
serde_json = { version = "1.0", features = ["preserve_order", "raw_value"] }
@@ -595,7 +615,7 @@ tree-sitter-html = "0.23"
tree-sitter-jsdoc = "0.23"
tree-sitter-json = "0.24"
tree-sitter-md = { git = "https://github.com/tree-sitter-grammars/tree-sitter-markdown", rev = "9a23c1a96c0513d8fc6520972beedd419a973539" }
tree-sitter-python = "0.23"
tree-sitter-python = { git = "https://github.com/zed-industries/tree-sitter-python", rev = "218fcbf3fda3d029225f3dec005cb497d111b35e" }
tree-sitter-regex = "0.24"
tree-sitter-ruby = "0.23"
tree-sitter-rust = "0.24"
@@ -622,8 +642,10 @@ wasmtime = { version = "29", default-features = false, features = [
] }
wasmtime-wasi = "29"
which = "6.0.0"
windows-core = "0.61"
wit-component = "0.221"
workspace-hack = "0.1.0"
zed_llm_client = "0.8.4"
zed_llm_client = "= 0.8.6"
zstd = "0.11"
[workspace.dependencies.async-stripe]
@@ -658,6 +680,7 @@ features = [
"Win32_Graphics_Gdi",
"Win32_Graphics_Imaging",
"Win32_Graphics_Imaging_D2D",
"Win32_Networking_WinSock",
"Win32_Security",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",
@@ -688,6 +711,7 @@ features = [
[patch.crates-io]
notify = { git = "https://github.com/zed-industries/notify.git", rev = "bbb9ea5ae52b253e095737847e367c30653a2e96" }
notify-types = { git = "https://github.com/zed-industries/notify.git", rev = "bbb9ea5ae52b253e095737847e367c30653a2e96" }
windows-capture = { git = "https://github.com/zed-industries/windows-capture.git", rev = "f0d6c1b6691db75461b732f6d5ff56eed002eeb9" }
# Makes the workspace hack crate refer to the local one, but only when you're building locally
workspace-hack = { path = "tooling/workspace-hack" }

View File

@@ -1,6 +1,6 @@
# syntax = docker/dockerfile:1.2
FROM rust:1.87-bookworm as builder
FROM rust:1.88-bookworm as builder
WORKDIR app
COPY . .

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.35443 9.97775L6.71495 8.65418L6.75443 8.53883L6.71495 8.47508H6.59948L6.20456 8.45081L4.8557 8.41436L3.68608 8.36579L2.55291 8.30507L2.26734 8.24438L2 7.89224L2.02734 7.71617L2.26734 7.55528L2.61063 7.58564L3.37013 7.63724L4.50937 7.71617L5.3357 7.76474L6.56 7.89224H6.75443L6.78176 7.81331L6.71495 7.76474L6.66329 7.71617L5.48456 6.91778L4.20861 6.07388L3.54025 5.58815L3.17873 5.34227L2.99646 5.11157L2.91747 4.60764L3.24557 4.24639L3.68608 4.27675L3.79848 4.30711L4.24506 4.65014L5.19899 5.38781L6.44456 6.30458L6.62684 6.45635L6.69974 6.40475L6.70886 6.36833L6.62684 6.23171L5.94938 5.00834L5.22632 3.76372L4.9043 3.24766L4.81924 2.93802C4.78886 2.81053 4.7676 2.70427 4.7676 2.57374L5.14127 2.06678L5.34785 2L5.84609 2.06678L6.0557 2.24893L6.36557 2.95624L6.86684 4.07033L7.64456 5.58512L7.87241 6.0344L7.99391 6.45029L8.03948 6.57779H8.11847V6.50492L8.18228 5.6519L8.30075 4.6046L8.41619 3.25677L8.4557 2.87731L8.64404 2.42196L9.01772 2.17607L9.30938 2.31571L9.54938 2.65874L9.51596 2.88034L9.37316 3.80622L9.09368 5.25728L8.9114 6.22868H9.01772L9.13925 6.10727L9.6314 5.45459L10.4577 4.42246L10.8223 4.01265L11.2476 3.56033L11.521 3.3448H12.0375L12.4172 3.90944L12.2471 4.49228L11.7154 5.1662L11.275 5.73692L10.643 6.58691L10.2481 7.26689L10.2846 7.32152L10.3787 7.31243L11.8066 7.00886L12.5782 6.86921L13.4987 6.71135L13.915 6.90563L13.9605 7.10297L13.7965 7.50671L12.8122 7.74956L11.6577 7.98026L9.93824 8.38706L9.91697 8.40224L9.94127 8.43257L10.716 8.50544L11.0471 8.52365H11.8582L13.3681 8.63597L13.763 8.89703L14 9.21578L13.9605 9.45863L13.3529 9.76829L12.5327 9.57398L10.6187 9.11864L9.96254 8.95472H9.8714V9.00935L10.4182 9.54365L11.4208 10.4483L12.6754 11.614L12.7393 11.9023L12.5782 12.13L12.4081 12.1057L11.3053 11.277L10.88 10.9036L9.91697 10.0931H9.85316V10.1781L10.075 10.5029L11.2476 12.2636L11.3083 12.804L11.2233 12.98L10.9195 13.0863L10.5853 13.0255L9.89873 12.0632L9.19088 10.9795L8.61974 10.0081L8.54987 10.0476L8.21267 13.6752L8.05469 13.8604L7.69013 14L7.38632 13.7693L7.22531 13.3959L7.38632 12.6582L7.58075 11.6959L7.73873 10.9309L7.88153 9.98078L7.96658 9.66506L7.96052 9.64382L7.89062 9.65291L7.17368 10.6365L6.08303 12.1088L5.22026 13.0316L5.01368 13.1136L4.65519 12.9284L4.68861 12.5975L4.88911 12.303L6.08303 10.7852L6.80303 9.84416L7.26785 9.30077L7.26482 9.22187H7.23746L4.06582 11.2801L3.50076 11.3529L3.25772 11.1252L3.2881 10.7518L3.40354 10.6304L4.35747 9.97469L4.35443 9.97775Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.44 12.27C7.81333 13.1217 8 14.0317 8 15C8 14.0317 8.18083 13.1217 8.5425 12.27C8.91583 11.4183 9.4175 10.6775 10.0475 10.0475C10.6775 9.4175 11.4183 8.92167 12.27 8.56C13.1217 8.18667 14.0317 8 15 8C14.0317 8 13.1217 7.81917 12.27 7.4575C11.4411 7.1001 10.6871 6.5895 10.0475 5.9525C9.4105 5.31293 8.8999 4.55891 8.5425 3.73C8.18083 2.87833 8 1.96833 8 1C8 1.96833 7.81333 2.87833 7.44 3.73C7.07833 4.58167 6.5825 5.3225 5.9525 5.9525C5.31293 6.5895 4.55891 7.1001 3.73 7.4575C2.87833 7.81917 1.96833 8 1 8C1.96833 8 2.87833 8.18667 3.73 8.56C4.58167 8.92167 5.3225 9.4175 5.9525 10.0475C6.5825 10.6775 7.07833 11.4183 7.44 12.27Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 762 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.25669 0.999943C8.27509 0.993825 9.24655 1.42125 9.9227 2.17279C11.4427 1.85079 12.9991 2.53518 13.7733 3.86518C14.159 4.5149 14.3171 5.26409 14.2372 5.99994H13.2967C13.3789 5.42185 13.265 4.8321 12.9686 4.32514C12.2353 3.06961 10.6088 2.63919 9.33676 3.36322L6.48032 4.98822C6.46926 4.99697 6.46284 5.01135 6.46372 5.02533V6.38568L9.91294 4.42084C10.0565 4.33818 10.2336 4.33823 10.3768 4.42084L13.1502 5.99994H11.2948L9.88364 5.19623C9.87034 5.19054 9.85459 5.19128 9.84262 5.19916L8.64926 5.87983L8.8602 5.99994H7.99985C6.89539 6.00004 5.99988 6.89547 5.99985 7.99994V9.34955L3.90219 8.15522C3.75815 8.07431 3.66897 7.92228 3.66977 7.75873V4.53803C3.66977 4.50828 3.67172 4.4654 3.67172 4.44135C3.08836 4.65262 2.59832 5.0599 2.28794 5.59174C1.55635 6.84647 1.99122 8.44936 3.26059 9.17475L5.99985 10.7363V11.6162C5.87564 11.6568 5.73827 11.6456 5.6229 11.579L2.7977 9.96869C2.77156 9.95382 2.73449 9.9311 2.71372 9.91889C2.60687 10.5231 2.7194 11.1466 3.0311 11.6777C3.6435 12.7209 4.87159 13.1902 5.99985 12.9023V13.8398C4.50443 14.1233 2.98758 13.4424 2.22641 12.1347C1.71174 11.2677 1.60096 10.2237 1.9227 9.27045C0.880739 8.13295 0.703328 6.46023 1.48325 5.13373C1.98739 4.26024 2.84863 3.64401 3.84653 3.44233C4.3245 1.9837 5.70306 0.996447 7.25669 0.999943ZM7.25766 1.91498C5.78932 1.9143 4.59839 3.08914 4.59751 4.53803V7.79193C4.59926 7.80578 4.60735 7.81796 4.61997 7.82416L5.8143 8.50483L5.81626 4.57611C5.81537 4.41216 5.90431 4.2606 6.04868 4.17963L8.87387 2.56928C8.89868 2.55441 8.93612 2.53379 8.95786 2.5224C8.48035 2.13046 7.8788 1.91498 7.25766 1.91498Z" fill="black"/>
<path d="M13.5 6C14.6046 6 15.5 6.89543 15.5 8V13.5C15.5 14.6046 14.6046 15.5 13.5 15.5H8C6.89543 15.5 6 14.6046 6 13.5V8C6 6.89543 6.89543 6 8 6H13.5ZM10.8916 8.02539C10.0563 8.02539 9.33453 8.27982 8.81934 8.76562C8.30213 9.25335 8.02547 9.94371 8.02539 10.748C8.02539 11.557 8.29852 12.2492 8.81543 12.7373C9.33013 13.2232 10.0521 13.4746 10.8916 13.4746C11.9865 13.4745 12.8545 13.1022 13.3076 12.3525C13.3894 12.2176 13.4521 12.0693 13.4521 11.8857C13.4521 11.4795 13.0933 11.2773 12.7842 11.2773C12.6604 11.2774 12.5292 11.3025 12.4072 11.3779C12.2862 11.4529 12.2058 11.5586 12.1494 11.666L12.1475 11.6689C11.9677 12.0213 11.5535 12.246 10.8955 12.2461C10.4219 12.2461 10.0667 12.0932 9.83008 11.8506C9.59255 11.607 9.44141 11.2389 9.44141 10.748C9.44148 10.264 9.59319 9.89628 9.83203 9.65137C10.0702 9.40725 10.4255 9.25391 10.8916 9.25391C11.4912 9.25399 11.9415 9.50614 12.1289 9.8916V9.89062C12.1888 10.0157 12.276 10.1311 12.4023 10.2129C12.5303 10.2956 12.6724 10.3271 12.8115 10.3271C12.9661 10.3271 13.1303 10.2857 13.2627 10.1758C13.4018 10.0603 13.4746 9.89383 13.4746 9.71582C13.4746 9.61857 13.4542 9.52036 13.4199 9.42773L13.3818 9.33691C12.9749 8.49175 11.9927 8.02548 10.8916 8.02539ZM10.3203 8.97852L10.1494 9.03516C10.2095 9.01178 10.2716 8.99089 10.3359 8.97363C10.3307 8.97505 10.3256 8.97706 10.3203 8.97852ZM10.4814 8.94141C10.4969 8.9385 10.5126 8.93616 10.5283 8.93359C10.5126 8.93617 10.4969 8.9385 10.4814 8.94141ZM10.6709 8.91504C10.6819 8.91399 10.693 8.913 10.7041 8.91211C10.693 8.913 10.6819 8.91399 10.6709 8.91504Z" fill="black" fill-opacity="0.95"/>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -1,5 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill="currentColor" stroke="currentColor">
<g clip-path="url(#clip0_205_3)">
<g>
<path d="M0.094 7.78c0.469 0 2.281 -0.405 3.219 -0.936s0.938 -0.531 2.875 -1.906c2.453 -1.741 4.188 -1.158 7.031 -1.158" stroke-width="2.8125" />
<path d="m15.969 3.797 -4.805 2.774V1.023z" />
<path d="M0 7.781c0.469 0 2.281 0.405 3.219 0.936s0.938 0.531 2.875 1.906C8.547 12.364 10.281 11.781 13.125 11.781" stroke-width="2.8125" />

Before

Width:  |  Height:  |  Size: 575 B

After

Width:  |  Height:  |  Size: 545 B

3
assets/icons/ai_x_ai.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="m12.414 5.47.27 9.641h2.157l.27-13.15zM15.11.889h-3.293L6.651 7.613l1.647 2.142zM.889 15.11H4.18l1.647-2.142-1.647-2.143zm0-9.641 7.409 9.641h3.292L4.181 5.47z" fill="#000"/>
</svg>

After

Width:  |  Height:  |  Size: 289 B

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-arrow-down10-icon lucide-arrow-down-1-0"><path d="m3 16 4 4 4-4"/><path d="M7 20V4"/><path d="M17 10V4h-2"/><path d="M15 10h4"/><rect x="15" y="14" width="4" height="6" ry="2"/></svg>

After

Width:  |  Height:  |  Size: 386 B

View File

@@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.98749 1.67322C7.08029 1.71878 7.15543 1.79374 7.20121 1.88643C7.24699 1.97912 7.26084 2.08434 7.24061 2.18572L6.72812 4.75007H9.28122C9.37107 4.75006 9.45903 4.77588 9.53463 4.82445C9.61022 4.87302 9.67027 4.94229 9.70761 5.02402C9.74495 5.10574 9.75801 5.19648 9.74524 5.28542C9.73247 5.37437 9.69441 5.45776 9.63559 5.52569L5.57313 10.2131C5.50536 10.2912 5.41366 10.3447 5.31233 10.3653C5.211 10.3858 5.10571 10.3723 5.01285 10.3268C4.92 10.2813 4.8448 10.2064 4.79896 10.1137C4.75311 10.021 4.7392 9.9158 4.75939 9.81439L5.27188 7.25004H2.71878C2.62893 7.25005 2.54097 7.22423 2.46537 7.17566C2.38978 7.12709 2.32973 7.05782 2.29239 6.97609C2.25505 6.89437 2.24199 6.80363 2.25476 6.71469C2.26753 6.62574 2.30559 6.54235 2.36441 6.47443L6.42687 1.78697C6.49466 1.70879 6.58641 1.65524 6.68782 1.63467C6.78923 1.61409 6.89459 1.62765 6.98749 1.67322Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-clipboard"><rect width="8" height="4" x="8" y="2" rx="1" ry="1"/><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/></svg>

Before

Width:  |  Height:  |  Size: 358 B

View File

@@ -1 +1,12 @@
<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-bug"><path d="m8 2 1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.49219 2.29071L6.41455 3.1933" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.61816 3.1933L10.508 2.29071" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.7042 5.89221V5.15749C5.69033 4.85975 5.73943 4.56239 5.84856 4.28336C5.95768 4.00434 6.12456 3.74943 6.33913 3.53402C6.55369 3.31862 6.81149 3.14718 7.09697 3.03005C7.38245 2.91292 7.68969 2.85254 8.00014 2.85254C8.3106 2.85254 8.61784 2.91292 8.90332 3.03005C9.18879 3.14718 9.44659 3.31862 9.66116 3.53402C9.87572 3.74943 10.0426 4.00434 10.1517 4.28336C10.2609 4.56239 10.31 4.85975 10.2961 5.15749V5.89221" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.00006 13.0426C6.13263 13.0426 4.60474 11.6005 4.60474 9.83792V8.23558C4.60474 7.66895 4.84322 7.12554 5.26772 6.72487C5.69221 6.32421 6.26796 6.09912 6.86829 6.09912H9.13184C9.73217 6.09912 10.3079 6.32421 10.7324 6.72487C11.1569 7.12554 11.3954 7.66895 11.3954 8.23558V9.83792C11.3954 11.6005 9.86749 13.0426 8.00006 13.0426Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.60452 6.25196C3.51235 6.13878 2.60693 5.17677 2.60693 3.9884" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.60462 8.81659H2.34106" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M2.4541 13.3186C2.4541 12.1302 3.41611 11.1116 4.60448 11.0551" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.0761 3.9884C13.0761 5.17677 12.1706 6.13878 11.0955 6.25196" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.6591 8.81659H11.3955" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.3955 11.0551C12.5839 11.1116 13.5459 12.1302 13.5459 13.3186" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 615 B

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -1 +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-search-code"><path d="m13 13.5 2-2.5-2-2.5"/><path d="m21 21-4.3-4.3"/><path d="M9 8.5 7 11l2 2.5"/><circle cx="11" cy="11" r="8"/></svg>
<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-equal-icon lucide-equal"><line x1="5" x2="19" y1="9" y2="9"/><line x1="5" x2="19" y1="15" y2="15"/></svg>

Before

Width:  |  Height:  |  Size: 340 B

After

Width:  |  Height:  |  Size: 308 B

View File

@@ -1,5 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.0001 1.33334H4.00008C3.64646 1.33334 3.30732 1.47382 3.05727 1.72387C2.80722 1.97392 2.66675 2.31305 2.66675 2.66668V13.3333C2.66675 13.687 2.80722 14.0261 3.05727 14.2762C3.30732 14.5262 3.64646 14.6667 4.00008 14.6667H12.0001C12.3537 14.6667 12.6928 14.5262 12.9429 14.2762C13.1929 14.0261 13.3334 13.687 13.3334 13.3333V4.66668L10.0001 1.33334Z" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.66659 6.5L6.33325 9.83333" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.33325 6.5L9.66659 9.83333" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 804 B

View File

@@ -1,5 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.03125 3V3.03125M3.03125 3.03125V9M3.03125 3.03125C3.03125 5 6 5 6 5M3.03125 9C3.03125 11 6 11 6 11M3.03125 9V12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="8" y="2.5" width="6" height="5" rx="1.5" fill="black"/>
<rect x="8" y="8.46875" width="6" height="5.0625" rx="1.5" fill="black"/>
<path d="M3 3V3.03125M3 3.03125V9M3 3.03125C3 5 5.96875 5 5.96875 5M3 9C3 11 5.96875 11 5.96875 11M3 9V12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="8" y="3" width="5.5" height="4" rx="1.5" fill="black"/>
<rect x="8" y="9" width="5.5" height="4" rx="1.5" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 423 B

View File

@@ -1,6 +1,7 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 3.25C4.02614 3.25 4.25 3.02614 4.25 2.75C4.25 2.47386 4.02614 2.25 3.75 2.25C3.47386 2.25 3.25 2.47386 3.25 2.75C3.25 3.02614 3.47386 3.25 3.75 3.25ZM3.75 4.25C4.57843 4.25 5.25 3.57843 5.25 2.75C5.25 1.92157 4.57843 1.25 3.75 1.25C2.92157 1.25 2.25 1.92157 2.25 2.75C2.25 3.57843 2.92157 4.25 3.75 4.25Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.25 3.25C8.52614 3.25 8.75 3.02614 8.75 2.75C8.75 2.47386 8.52614 2.25 8.25 2.25C7.97386 2.25 7.75 2.47386 7.75 2.75C7.75 3.02614 7.97386 3.25 8.25 3.25ZM8.25 4.25C9.07843 4.25 9.75 3.57843 9.75 2.75C9.75 1.92157 9.07843 1.25 8.25 1.25C7.42157 1.25 6.75 1.92157 6.75 2.75C6.75 3.57843 7.42157 4.25 8.25 4.25Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 9.75C4.02614 9.75 4.25 9.52614 4.25 9.25C4.25 8.97386 4.02614 8.75 3.75 8.75C3.47386 8.75 3.25 8.97386 3.25 9.25C3.25 9.52614 3.47386 9.75 3.75 9.75ZM3.75 10.75C4.57843 10.75 5.25 10.0784 5.25 9.25C5.25 8.42157 4.57843 7.75 3.75 7.75C2.92157 7.75 2.25 8.42157 2.25 9.25C2.25 10.0784 2.92157 10.75 3.75 10.75Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.25 3.75H4.25V5.59609C4.67823 5.35824 5.24991 5.25 6 5.25H7.25017C7.5262 5.25 7.75 5.02625 7.75 4.75V3.75H8.75V4.75C8.75 5.57832 8.07871 6.25 7.25017 6.25H6C5.14559 6.25 4.77639 6.41132 4.59684 6.56615C4.42571 6.71373 4.33877 6.92604 4.25 7.30651V8.25H3.25V3.75Z" fill="black"/>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="5" cy="12" r="1.25" stroke="black" stroke-width="1.5"/>
<path d="M5 11V5" stroke="black" stroke-width="1.5"/>
<path d="M5 10C5 10 5.5 8 7 8C7.73103 8 8.69957 8 9.50049 8C10.3289 8 11 7.32843 11 6.5V5" stroke="black" stroke-width="1.5"/>
<circle cx="5" cy="4" r="1.25" stroke="black" stroke-width="1.5"/>
<circle cx="11" cy="4" r="1.25" stroke="black" stroke-width="1.5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 487 B

View File

@@ -1 +1,7 @@
<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-list-tree"><path d="M21 12h-8"/><path d="M21 6H8"/><path d="M21 18h-8"/><path d="M3 6v4c0 1.1.9 2 2 2h3"/><path d="M3 10v6c0 1.1.9 2 2 2h3"/></svg>
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.5 8H9.5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 4L6.5 4" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.5 12H9.5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 3.5V6.33333C3 7.25 3.72 8 4.6 8H7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 6V10.5C3 11.325 3.72 12 4.6 12H7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 680 B

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-location-edit-icon lucide-location-edit"><path d="M17.97 9.304A8 8 0 0 0 2 10c0 4.69 4.887 9.562 7.022 11.468"/><path d="M21.378 16.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"/><circle cx="10" cy="10" r="3"/></svg>

After

Width:  |  Height:  |  Size: 491 B

View File

@@ -0,0 +1,12 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6 3L7 4" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 4L10 3" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.002 6V5.51658C5.98992 5.32067 6.03266 5.12502 6.12762 4.94143C6.22259 4.75784 6.36781 4.59012 6.55453 4.44839C6.74125 4.30666 6.9656 4.19386 7.21403 4.1168C7.46246 4.03973 7.72983 4 8 4C8.27017 4 8.53754 4.03973 8.78597 4.1168C9.0344 4.19386 9.25875 4.30666 9.44547 4.44839C9.63219 4.59012 9.77741 4.75784 9.87238 4.94143C9.96734 5.12502 10.0101 5.32067 9.998 5.51658V6" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8 13C6.35 13 5 11.5462 5 9.76923V8.15385C5 7.58261 5.21071 7.03477 5.58579 6.63085C5.96086 6.22692 6.46957 6 7 6H9C9.53043 6 10.0391 6.22692 10.4142 6.63085C10.7893 7.03477 11 7.58261 11 8.15385V9.76923C11 11.5462 9.65 13 8 13Z" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 6.16663C3.90652 6.06663 3 5.21663 3 4.16663" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 9H3" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 13C3 11.95 3.89474 11.05 5 11" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 4C13 5.05 12.0857 5.9 11 6" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 9H11" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 11C12.1053 11.05 13 11.95 13 13" stroke="black" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.84265 10.7778C4.39206 11.6001 5.17295 12.241 6.08658 12.6194C7.00021 12.9978 8.00555 13.0969 8.97545 12.9039C9.94535 12.711 10.8363 12.2348 11.5355 11.5355C12.2348 10.8363 12.711 9.94535 12.9039 8.97545C13.0969 8.00555 12.9978 7.00021 12.6194 6.08658C12.241 5.17295 11.6001 4.39206 10.7778 3.84265C9.9556 3.29324 8.9889 3 8 3C6.60219 3.00526 5.26054 3.55068 4.25556 4.52222L3 5.77778" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 3V6H6" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 685 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 5L11 11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 409 B

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 4H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.66667 8H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4.66667 12H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.00016 12C8.41993 12.5597 9.00515 12.9731 9.67294 13.1817C10.3407 13.3903 11.0572 13.3835 11.7209 13.1623C12.3846 12.941 12.9619 12.5166 13.371 11.949C13.78 11.3815 14.0002 10.6996 14.0002 10C14.0002 9.20435 13.6841 8.44129 13.1215 7.87868C12.5589 7.31607 11.7958 7 11.0002 7C10.1135 7 9.30683 7.36 8.72683 7.94L7.3335 9.33333" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.3335 6.66669V9.33335H10.0002" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 964 B

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.33333 8H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.6667 5H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 11H2" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 7V11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 9H10" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 620 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.31254 12.549C7.3841 13.0987 8.61676 13.2476 9.78839 12.9688C10.96 12.6901 11.9936 12.0021 12.7028 11.0287C13.412 10.0554 13.7503 8.8607 13.6566 7.66002C13.5629 6.45934 13.0435 5.33159 12.1919 4.48C11.3403 3.62841 10.2126 3.10898 9.01188 3.01531C7.8112 2.92164 6.61655 3.2599 5.64319 3.96912C4.66984 4.67834 3.9818 5.71188 3.70306 6.88351C3.42432 8.05514 3.5732 9.2878 4.12289 10.3594L3 13.6719L6.31254 12.549Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 609 B

View File

@@ -0,0 +1,3 @@
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 4L10 7L5 10V4Z" fill="black" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 227 B

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-scroll-text-icon lucide-scroll-text"><path d="M15 12h-5"/><path d="M15 8h-5"/><path d="M19 17V5a2 2 0 0 0-2-2H4"/><path d="M8 21h12a2 2 0 0 0 2-2v-1a1 1 0 0 0-1-1H11a1 1 0 0 0-1 1v1a2 2 0 1 1-4 0V5a2 2 0 1 0-4 0v2a1 1 0 0 0 1 1h3"/></svg>

After

Width:  |  Height:  |  Size: 441 B

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-split-icon lucide-split"><path d="M16 3h5v5"/><path d="M8 3H3v5"/><path d="M12 22v-8.3a4 4 0 0 0-1.172-2.872L3 3"/><path d="m15 9 6-6"/></svg>

After

Width:  |  Height:  |  Size: 345 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8889 3H4.11111C3.49746 3 3 3.49746 3 4.11111V11.8889C3 12.5025 3.49746 13 4.11111 13H11.8889C12.5025 13 13 12.5025 13 11.8889V4.11111C13 3.49746 12.5025 3 11.8889 3Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.37939 10.3243H10.3794" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.64966 9.32837L7.64966 7.32837L5.64966 5.32837" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 659 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 13C10.7614 13 13 10.7614 13 8C13 5.23858 10.7614 3 8 3C5.23858 3 3 5.23858 3 8C3 10.7614 5.23858 13 8 13Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 8L7.33333 9L10 7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 3C7.66045 3 8.33955 3 9 3" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 4C11.3949 4.26602 11.7345 4.60558 12 5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 7C13 7.66045 13 8.33955 13 9" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 11C11.734 11.3949 11.3944 11.7345 11 12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 13C8.33954 13 7.66046 13 7 13" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 12C4.6051 11.734 4.26554 11.3944 4 11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 9C3 8.33955 3 7.66045 3 7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 5C4.26602 4.6051 4.60558 4.26554 5 4" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,11 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7 3C7.66045 3 8.33955 3 9 3" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11 4C11.3949 4.26602 11.7345 4.60558 12 5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13 7C13 7.66045 13 8.33955 13 9" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 11C11.734 11.3949 11.3944 11.7345 11 12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 13C8.33954 13 7.66046 13 7 13" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 12C4.6051 11.734 4.26554 11.3944 4 11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 9C3 8.33955 3 7.66045 3 7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 5C4.26602 4.6051 4.60558 4.26554 5 4" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.00016 8.66665C8.36835 8.66665 8.66683 8.36817 8.66683 7.99998C8.66683 7.63179 8.36835 7.33331 8.00016 7.33331C7.63197 7.33331 7.3335 7.63179 7.3335 7.99998C7.3335 8.36817 7.63197 8.66665 8.00016 8.66665Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.4174 10.2159C10.5454 9.58974 10.4174 9.57261 11.3762 8.46959C11.9337 7.82822 12.335 7.09214 12.335 6.27818C12.335 5.28184 11.9309 4.32631 11.2118 3.62179C10.4926 2.91728 9.5171 2.52148 8.50001 2.52148C7.48291 2.52148 6.50748 2.91728 5.78828 3.62179C5.06909 4.32631 4.66504 5.28184 4.66504 6.27818C4.66504 6.9043 4.79288 7.65565 5.62379 8.46959C6.58253 9.59098 6.45474 9.58974 6.58257 10.2159M10.4174 10.2159L10.4174 12.2989C10.4174 12.9504 9.87836 13.4786 9.21329 13.4786H7.78674C7.12167 13.4786 6.58253 12.9504 6.58253 12.2989L6.58257 10.2159M10.4174 10.2159H8.50001H6.58257" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 776 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.5 2.5H6.5C6.22386 2.5 6 2.83579 6 3.25V4.75C6 5.16421 6.22386 5.5 6.5 5.5H9.5C9.77614 5.5 10 5.16421 10 4.75V3.25C10 2.83579 9.77614 2.5 9.5 2.5Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 3.5H11C11.2652 3.5 11.5196 3.61706 11.7071 3.82544C11.8946 4.03381 12 4.31643 12 4.61111V12.3889C12 12.6836 11.8946 12.9662 11.7071 13.1746C11.5196 13.3829 11.2652 13.5 11 13.5H5C4.73478 13.5 4.48043 13.3829 4.29289 13.1746C4.10536 12.9662 4 12.6836 4 12.3889V4.61111C4 4.31643 4.10536 4.03381 4.29289 3.82544C4.48043 3.61706 4.73478 3.5 5 3.5H6" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 788 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.50002 2.5H5C4.73478 2.5 4.48043 2.6159 4.29289 2.82219C4.10535 3.02848 4 3.30826 4 3.6V12.3999C4 12.6917 4.10535 12.9715 4.29289 13.1778C4.48043 13.3841 4.73478 13.5 5 13.5H11C11.2652 13.5 11.5195 13.3841 11.7071 13.1778C11.8946 12.9715 12 12.6917 12 12.3999V5.25L9.50002 2.5Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9.3427 6.82379L6.65698 9.5095" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.65698 6.82379L9.3427 9.5095" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 724 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13.7244 11.5299L9.01711 3.2922C8.91447 3.11109 8.76562 2.96045 8.58576 2.85564C8.4059 2.75084 8.20145 2.69562 7.99328 2.69562C7.7851 2.69562 7.58066 2.75084 7.40079 2.85564C7.22093 2.96045 7.07209 3.11109 6.96945 3.2922L2.26218 11.5299C2.15844 11.7096 2.10404 11.9135 2.1045 12.121C2.10495 12.3285 2.16026 12.5321 2.2648 12.7113C2.36934 12.8905 2.5194 13.0389 2.69978 13.1415C2.88015 13.244 3.08443 13.297 3.2919 13.2951H12.7064C12.9129 13.2949 13.1157 13.2404 13.2944 13.137C13.4731 13.0336 13.6215 12.8851 13.7247 12.7062C13.8278 12.5273 13.8821 12.3245 13.882 12.118C13.882 11.9115 13.8276 11.7087 13.7244 11.5299Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99927 6.23425V8.58788" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.99927 10.9415H8.00492" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.4 12.5C12.6917 12.5 12.9715 12.3884 13.1778 12.1899C13.3841 11.9913 13.5 11.722 13.5 11.4412V6.14706C13.5 5.86624 13.3841 5.59693 13.1778 5.39836C12.9715 5.19979 12.6917 5.08824 12.4 5.08824H8.055C7.87103 5.08997 7.68955 5.04726 7.52717 4.96402C7.36478 4.88078 7.22668 4.75967 7.1255 4.61176L6.68 3.97647C6.57984 3.83007 6.44349 3.7099 6.28317 3.62674C6.12286 3.54358 5.94361 3.50003 5.7615 3.5H3.6C3.30826 3.5 3.02847 3.61155 2.82218 3.81012C2.61589 4.00869 2.5 4.27801 2.5 4.55882V11.4412C2.5 11.722 2.61589 11.9913 2.82218 12.1899C3.02847 12.3884 3.30826 12.5 3.6 12.5H12.4Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 778 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9 8.5L4.94864 12.6222C4.71647 12.8544 4.40157 12.9848 4.07323 12.9848C3.74488 12.9848 3.42999 12.8544 3.19781 12.6222C2.96564 12.39 2.83521 12.0751 2.83521 11.7468C2.83521 11.4185 2.96564 11.1036 3.19781 10.8714L7.5 6.5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.8352 9.98474L13.8352 6.98474" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.8352 7.42495L11.7634 6.4298C11.5533 6.23484 11.4353 5.97039 11.4352 5.69462V5.08526L10.1696 3.91022C9.54495 3.33059 8.69961 3.00261 7.81649 2.99722L5.83521 2.98474L6.35041 3.41108C6.71634 3.71233 7.00935 4.08216 7.21013 4.4962C7.4109 4.91024 7.51488 5.35909 7.51521 5.81316L7.5 6.5L9 8.5L9.5 8C9.5 8 9.87337 7.79457 10.0834 7.98959L11.1552 8.98474" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 988 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.5 12C6.65203 12.304 6.87068 12.5565 7.13399 12.7321C7.39729 12.9076 7.69597 13 8 13C8.30403 13 8.60271 12.9076 8.86601 12.7321C9.12932 12.5565 9.34797 12.304 9.5 12" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3.63088 9.21874C3.56556 9.28556 3.52246 9.36865 3.50681 9.45791C3.49116 9.54718 3.50364 9.63876 3.54273 9.72152C3.58183 9.80429 3.64585 9.87467 3.72701 9.92409C3.80817 9.97352 3.90298 9.99987 3.99989 9.99994H12.0001C12.097 9.99997 12.1918 9.97372 12.273 9.92439C12.3542 9.87505 12.4183 9.80476 12.4575 9.72205C12.4967 9.63934 12.5093 9.54778 12.4938 9.45851C12.4783 9.36924 12.4353 9.2861 12.3701 9.21921C11.705 8.57941 11 7.89947 11 5.79994C11 5.05733 10.684 4.34514 10.1213 3.82004C9.55872 3.29494 8.79564 2.99994 7.99997 2.99994C7.20431 2.99994 6.44123 3.29494 5.87861 3.82004C5.31599 4.34514 4.99991 5.05733 4.99991 5.79994C4.99991 7.89947 4.2944 8.57941 3.63088 9.21874Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.5871 5.40582C12.8514 5.14152 13 4.78304 13 4.40922C13 4.03541 12.8516 3.67688 12.5873 3.41252C12.323 3.14816 11.9645 2.99962 11.5907 2.99957C11.2169 2.99953 10.8584 3.14798 10.594 3.41227L3.92098 10.0869C3.80488 10.2027 3.71903 10.3452 3.67097 10.5019L3.01047 12.678C2.99754 12.7212 2.99657 12.7672 3.00764 12.8109C3.01872 12.8547 3.04143 12.8946 3.07337 12.9265C3.1053 12.9584 3.14528 12.981 3.18905 12.992C3.23282 13.003 3.27875 13.002 3.32197 12.989L5.49849 12.329C5.65508 12.2813 5.79758 12.196 5.91349 12.0805L12.5871 5.40582Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M9 5L11 7" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 835 B

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3 5.66667V4.33333C3 3.97971 3.14048 3.64057 3.39052 3.39052C3.64057 3.14048 3.97971 3 4.33333 3H5.66667" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10.3333 3H11.6666C12.0202 3 12.3593 3.14048 12.6094 3.39052C12.8594 3.64057 12.9999 3.97971 12.9999 4.33333V5.66667" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.9999 10.3333V11.6666C12.9999 12.0203 12.8594 12.3594 12.6094 12.6095C12.3593 12.8595 12.0202 13 11.6666 13H10.3333" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.66667 13H4.33333C3.97971 13 3.64057 12.8595 3.39052 12.6095C3.14048 12.3594 3 12.0203 3 11.6666V10.3333" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5.5 8H10.5" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4.57132 13.7143C5.20251 13.7143 5.71418 13.2026 5.71418 12.5714C5.71418 11.9403 5.20251 11.4286 4.57132 11.4286C3.94014 11.4286 3.42847 11.9403 3.42847 12.5714C3.42847 13.2026 3.94014 13.7143 4.57132 13.7143Z" fill="black"/>
<path d="M10.2856 2.85712V5.71426M10.2856 5.71426V8.5714M10.2856 5.71426H13.1428M10.2856 5.71426H7.42847M10.2856 5.71426L12.1904 3.80949M10.2856 5.71426L8.38084 7.61906M10.2856 5.71426L12.1904 7.61906M10.2856 5.71426L8.38084 3.80949" stroke="black" stroke-width="1.5" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 631 B

View File

@@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M13 13L11 11" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.5 12C9.98528 12 12 9.98528 12 7.5C12 5.01472 9.98528 3 7.5 3C5.01472 3 3 5.01472 3 7.5C3 9.98528 5.01472 12 7.5 12Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.99487 8.44023L7.32821 7.10689L5.99487 5.77356" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.33838 10.2264H10.005" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M11.8889 3H4.11111C3.49746 3 3 3.49746 3 4.11111V11.8889C3 12.5025 3.49746 13 4.11111 13H11.8889C12.5025 13 13 12.5025 13 11.8889V4.11111C13 3.49746 12.5025 3 11.8889 3Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 625 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.99993 13.4804C11.0267 13.4804 13.4803 11.0267 13.4803 7.99999C13.4803 4.97325 11.0267 2.51959 7.99993 2.51959C4.97319 2.51959 2.51953 4.97325 2.51953 7.99999C2.51953 11.0267 4.97319 13.4804 7.99993 13.4804Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8 3C6.71611 4.34807 6 6.13836 6 7.99999C6 9.86163 6.71611 11.6519 8 13C9.28387 11.6519 10 9.86163 10 7.99999C10 6.13836 9.28387 4.34807 8 3Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3.24121 7.04827C4.52425 8.27022 6.22817 8.95178 7.99999 8.95178C9.77182 8.95178 11.4757 8.27022 12.7588 7.04827" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 847 B

View File

@@ -1,3 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.9 8.00002C7.44656 8.00002 8.7 6.74637 8.7 5.20002C8.7 3.65368 7.44656 2.40002 5.9 2.40002C4.35344 2.40002 3.1 3.65368 3.1 5.20002C3.1 6.74637 4.35344 8.00002 5.9 8.00002ZM7.00906 9.05002H4.79094C2.69684 9.05002 1 10.7475 1 12.841C1 13.261 1.3395 13.6 1.75819 13.6H10.0409C10.4609 13.6 10.8 13.261 10.8 12.841C10.8 10.7475 9.1025 9.05002 7.00906 9.05002ZM11.4803 9.40002H9.86484C10.87 10.2247 11.5 11.4585 11.5 12.841C11.5 13.121 11.4169 13.3791 11.2812 13.6H14.3C14.6872 13.6 15 13.285 15 12.8803C15 10.9663 13.4338 9.40002 11.4803 9.40002ZM10.45 8.00002C11.8041 8.00002 12.9 6.90409 12.9 5.55002C12.9 4.19596 11.8041 3.10002 10.45 3.10002C9.90072 3.10002 9.39913 3.28716 8.9905 3.59243C9.2425 4.07631 9.4 4.61815 9.4 5.20002C9.4 5.97702 9.13903 6.69059 8.70897 7.27181C9.15281 7.72002 9.7675 8.00002 10.45 8.00002Z" fill="white"/>
<path d="M6.79118 8.27005C8.27568 8.27005 9.4791 7.06663 9.4791 5.58214C9.4791 4.09765 8.27568 2.89423 6.79118 2.89423C5.30669 2.89423 4.10327 4.09765 4.10327 5.58214C4.10327 7.06663 5.30669 8.27005 6.79118 8.27005Z" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6.79112 8.60443C4.19441 8.60443 2.08936 10.7095 2.08936 13.3062H11.4929C11.4929 10.7095 9.38784 8.60443 6.79112 8.60443Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14.6984 12.9263C14.6984 10.8893 13.4895 8.99736 12.2806 8.09067C12.6779 7.79254 12.9957 7.40104 13.2057 6.95083C13.4157 6.50062 13.5115 6.00558 13.4846 5.50952C13.4577 5.01346 13.309 4.53168 13.0515 4.10681C12.7941 3.68194 12.4358 3.3271 12.0085 3.07367" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 947 B

After

Width:  |  Height:  |  Size: 999 B

View File

@@ -1,5 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 2L6.72534 5.87534C6.6601 6.07367 6.5492 6.25392 6.40155 6.40155C6.25392 6.5492 6.07367 6.6601 5.87534 6.72534L2 8L5.87534 9.27466C6.07367 9.3399 6.25392 9.4508 6.40155 9.59845C6.5492 9.74608 6.6601 9.92633 6.72534 10.1247L8 14L9.27466 10.1247C9.3399 9.92633 9.4508 9.74608 9.59845 9.59845C9.74608 9.4508 9.92633 9.3399 10.1247 9.27466L14 8L10.1247 6.72534C9.92633 6.6601 9.74608 6.5492 9.59845 6.40155C9.4508 6.25392 9.3399 6.07367 9.27466 5.87534L8 2Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8 2.93652L6.9243 6.20697C6.86924 6.37435 6.77565 6.52646 6.65105 6.65105C6.52646 6.77565 6.37435 6.86924 6.20697 6.9243L2.93652 8L6.20697 9.0757C6.37435 9.13076 6.52646 9.22435 6.65105 9.34895C6.77565 9.47354 6.86924 9.62565 6.9243 9.79306L8 13.0635L9.0757 9.79306C9.13076 9.62565 9.22435 9.47354 9.34895 9.34895C9.47354 9.22435 9.62565 9.13076 9.79306 9.0757L13.0635 8L9.79306 6.9243C9.62565 6.86924 9.47354 6.77565 9.34895 6.65105C9.22435 6.52646 9.13076 6.37435 9.0757 6.20697L8 2.93652Z" fill="black" fill-opacity="0.15" stroke="black" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3.33334 2V4.66666M2 3.33334H4.66666" stroke="black" stroke-opacity="0.75" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12.6665 11.3333V14M11.3333 12.6666H13.9999" stroke="black" stroke-opacity="0.75" stroke-width="1.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 998 B

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -34,7 +34,7 @@
"ctrl-q": "zed::Quit",
"f4": "debugger::Start",
"shift-f5": "debugger::Stop",
"ctrl-shift-f5": "debugger::Restart",
"ctrl-shift-f5": "debugger::RerunSession",
"f6": "debugger::Pause",
"f7": "debugger::StepOver",
"ctrl-f11": "debugger::StepInto",
@@ -244,6 +244,7 @@
"ctrl-alt-e": "agent::RemoveAllContext",
"ctrl-shift-e": "project_panel::ToggleFocus",
"ctrl-shift-enter": "agent::ContinueThread",
"super-ctrl-b": "agent::ToggleBurnMode",
"alt-enter": "agent::ContinueWithBurnMode"
}
},
@@ -268,7 +269,15 @@
}
},
{
"context": "MessageEditor > Editor",
"context": "AgentPanel && external_agent_thread",
"use_key_equivalents": true,
"bindings": {
"ctrl-n": "agent::NewExternalAgentThread",
"ctrl-alt-t": "agent::NewThread"
}
},
{
"context": "MessageEditor && !Picker > Editor && !use_modifier_to_send",
"bindings": {
"enter": "agent::Chat",
"ctrl-enter": "agent::ChatWithFollow",
@@ -278,6 +287,17 @@
"ctrl-shift-n": "agent::RejectAll"
}
},
{
"context": "MessageEditor && !Picker > Editor && use_modifier_to_send",
"bindings": {
"ctrl-enter": "agent::Chat",
"enter": "editor::Newline",
"ctrl-i": "agent::ToggleProfileSelector",
"shift-ctrl-r": "agent::OpenAgentDiff",
"ctrl-shift-y": "agent::KeepAll",
"ctrl-shift-n": "agent::RejectAll"
}
},
{
"context": "EditMessageEditor > Editor",
"bindings": {
@@ -305,6 +325,16 @@
"enter": "agent::AcceptSuggestedContext"
}
},
{
"context": "AcpThread > Editor",
"use_key_equivalents": true,
"bindings": {
"enter": "agent::Chat",
"up": "agent::PreviousHistoryMessage",
"down": "agent::NextHistoryMessage",
"shift-ctrl-r": "agent::OpenAgentDiff"
}
},
{
"context": "ThreadHistory",
"bindings": {
@@ -400,7 +430,7 @@
"ctrl-shift-pagedown": "pane::SwapItemRight",
"ctrl-f4": ["pane::CloseActiveItem", { "close_pinned": false }],
"ctrl-w": ["pane::CloseActiveItem", { "close_pinned": false }],
"alt-ctrl-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
"alt-ctrl-t": ["pane::CloseOtherItems", { "close_pinned": false }],
"alt-ctrl-shift-w": "workspace::CloseInactiveTabsAndPanes",
"ctrl-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
"ctrl-k t": ["pane::CloseItemsToTheRight", { "close_pinned": false }],
@@ -453,11 +483,10 @@
"ctrl-k ctrl-d": ["editor::SelectNext", { "replace_newest": true }], // editor.action.moveSelectionToNextFindMatch / find_under_expand_skip
"ctrl-k ctrl-shift-d": ["editor::SelectPrevious", { "replace_newest": true }], // editor.action.moveSelectionToPreviousFindMatch
"ctrl-k ctrl-i": "editor::Hover",
"ctrl-k ctrl-b": "editor::BlameHover",
"ctrl-/": ["editor::ToggleComments", { "advance_downwards": false }],
"ctrl-u": "editor::UndoSelection",
"ctrl-shift-u": "editor::RedoSelection",
"f8": "editor::GoToDiagnostic",
"shift-f8": "editor::GoToPreviousDiagnostic",
"f8": ["editor::GoToDiagnostic", { "severity": { "min": "hint", "max": "error" } }],
"shift-f8": ["editor::GoToPreviousDiagnostic", { "severity": { "min": "hint", "max": "error" } }],
"f2": "editor::Rename",
"f12": "editor::GoToDefinition",
"alt-f12": "editor::GoToDefinitionSplit",
@@ -490,13 +519,27 @@
"ctrl-k r": "editor::RevealInFileManager",
"ctrl-k p": "editor::CopyPath",
"ctrl-\\": "pane::SplitRight",
"ctrl-k v": "markdown::OpenPreviewToTheSide",
"ctrl-shift-v": "markdown::OpenPreview",
"ctrl-alt-shift-c": "editor::DisplayCursorNames",
"alt-.": "editor::GoToHunk",
"alt-,": "editor::GoToPreviousHunk"
}
},
{
"context": "Editor && extension == md",
"use_key_equivalents": true,
"bindings": {
"ctrl-k v": "markdown::OpenPreviewToTheSide",
"ctrl-shift-v": "markdown::OpenPreview"
}
},
{
"context": "Editor && extension == svg",
"use_key_equivalents": true,
"bindings": {
"ctrl-k v": "svg::OpenPreviewToTheSide",
"ctrl-shift-v": "svg::OpenPreview"
}
},
{
"context": "Editor && mode == full",
"bindings": {
@@ -542,11 +585,18 @@
"ctrl-b": "workspace::ToggleLeftDock",
"ctrl-j": "workspace::ToggleBottomDock",
"ctrl-alt-y": "workspace::CloseAllDocks",
"ctrl-alt-0": "workspace::ResetActiveDockSize",
// For 0px parameter, uses UI font size value.
"ctrl-alt--": ["workspace::DecreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-=": ["workspace::IncreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-)": "workspace::ResetOpenDocksSize",
"ctrl-alt-_": ["workspace::DecreaseOpenDocksSize", { "px": 0 }],
"ctrl-alt-+": ["workspace::IncreaseOpenDocksSize", { "px": 0 }],
"shift-find": "pane::DeploySearch",
"ctrl-shift-f": "pane::DeploySearch",
"ctrl-shift-h": ["pane::DeploySearch", { "replace_enabled": true }],
"ctrl-shift-t": "pane::ReopenClosedItem",
"ctrl-k ctrl-s": "zed::OpenKeymap",
"ctrl-k ctrl-s": "zed::OpenKeymapEditor",
"ctrl-k ctrl-t": "theme_selector::Toggle",
"ctrl-t": "project_symbols::Toggle",
"ctrl-p": "file_finder::Toggle",
@@ -583,7 +633,9 @@
// "foo-bar": ["task::Spawn", { "task_name": "MyTask", "reveal_target": "dock" }]
// or by tag:
// "foo-bar": ["task::Spawn", { "task_tag": "MyTag" }],
"f5": "debugger::RerunLastSession"
"f5": "debugger::Rerun",
"ctrl-f4": "workspace::CloseActiveDock",
"ctrl-w": "workspace::CloseActiveDock"
}
},
{
@@ -610,6 +662,8 @@
{
"context": "Editor",
"bindings": {
"ctrl-u": "editor::UndoSelection",
"ctrl-shift-u": "editor::RedoSelection",
"ctrl-shift-j": "editor::JoinLines",
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
"ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",
@@ -686,6 +740,13 @@
"pagedown": "editor::ContextMenuLast"
}
},
{
"context": "Editor && showing_signature_help && !showing_completions",
"bindings": {
"up": "editor::SignatureHelpPrevious",
"down": "editor::SignatureHelpNext"
}
},
// Custom bindings
{
"bindings": {
@@ -807,6 +868,7 @@
"alt-shift-y": "git::UnstageFile",
"ctrl-alt-y": "git::ToggleStaged",
"space": "git::ToggleStaged",
"shift-space": "git::StageRange",
"tab": "git_panel::FocusEditor",
"shift-tab": "git_panel::FocusEditor",
"escape": "git_panel::ToggleFocus",
@@ -867,7 +929,7 @@
}
},
{
"context": "GitPanel > Editor",
"context": "CommitEditor > Editor",
"bindings": {
"escape": "git_panel::FocusChanges",
"tab": "git_panel::FocusChanges",
@@ -904,16 +966,23 @@
"context": "BreakpointList",
"bindings": {
"space": "debugger::ToggleEnableBreakpoint",
"backspace": "debugger::UnsetBreakpoint"
"backspace": "debugger::UnsetBreakpoint",
"left": "debugger::PreviousBreakpointProperty",
"right": "debugger::NextBreakpointProperty"
}
},
{
"context": "CollabPanel && not_editing",
"bindings": {
"ctrl-backspace": "collab_panel::Remove",
"space": "menu::Confirm",
"ctrl-up": "collab_panel::MoveChannelUp",
"ctrl-down": "collab_panel::MoveChannelDown"
"space": "menu::Confirm"
}
},
{
"context": "CollabPanel",
"bindings": {
"alt-up": "collab_panel::MoveChannelUp",
"alt-down": "collab_panel::MoveChannelDown"
}
},
{
@@ -947,6 +1016,7 @@
{
"context": "FileFinder || (FileFinder > Picker > Editor)",
"bindings": {
"ctrl-p": "file_finder::Toggle",
"ctrl-shift-a": "file_finder::ToggleSplitMenu",
"ctrl-shift-i": "file_finder::ToggleFilterMenu"
}
@@ -1050,5 +1120,52 @@
"ctrl-tab": "pane::ActivateNextItem",
"ctrl-shift-tab": "pane::ActivatePreviousItem"
}
},
{
"context": "MarkdownPreview",
"bindings": {
"pageup": "markdown::MovePageUp",
"pagedown": "markdown::MovePageDown"
}
},
{
"context": "KeymapEditor",
"use_key_equivalents": true,
"bindings": {
"ctrl-f": "search::FocusSearch",
"alt-find": "keymap_editor::ToggleKeystrokeSearch",
"alt-ctrl-f": "keymap_editor::ToggleKeystrokeSearch",
"alt-c": "keymap_editor::ToggleConflictFilter",
"enter": "keymap_editor::EditBinding",
"alt-enter": "keymap_editor::CreateBinding",
"ctrl-c": "keymap_editor::CopyAction",
"ctrl-shift-c": "keymap_editor::CopyContext",
"ctrl-t": "keymap_editor::ShowMatchingKeybinds"
}
},
{
"context": "KeystrokeInput",
"use_key_equivalents": true,
"bindings": {
"enter": "keystroke_input::StartRecording",
"escape escape escape": "keystroke_input::StopRecording",
"delete": "keystroke_input::ClearKeystrokes"
}
},
{
"context": "KeybindEditorModal",
"use_key_equivalents": true,
"bindings": {
"ctrl-enter": "menu::Confirm",
"escape": "menu::Cancel"
}
},
{
"context": "KeybindEditorModal > Editor",
"use_key_equivalents": true,
"bindings": {
"up": "menu::SelectPrevious",
"down": "menu::SelectNext"
}
}
]

View File

@@ -5,10 +5,10 @@
"bindings": {
"f4": "debugger::Start",
"shift-f5": "debugger::Stop",
"shift-cmd-f5": "debugger::Restart",
"shift-cmd-f5": "debugger::RerunSession",
"f6": "debugger::Pause",
"f7": "debugger::StepOver",
"f11": "debugger::StepInto",
"ctrl-f11": "debugger::StepInto",
"shift-f11": "debugger::StepOut",
"home": "menu::SelectFirst",
"shift-pageup": "menu::SelectFirst",
@@ -283,6 +283,7 @@
"cmd->": "assistant::QuoteSelection",
"cmd-alt-e": "agent::RemoveAllContext",
"cmd-shift-e": "project_panel::ToggleFocus",
"cmd-ctrl-b": "agent::ToggleBurnMode",
"cmd-shift-enter": "agent::ContinueThread",
"alt-enter": "agent::ContinueWithBurnMode"
}
@@ -309,7 +310,15 @@
}
},
{
"context": "MessageEditor > Editor",
"context": "AgentPanel && external_agent_thread",
"use_key_equivalents": true,
"bindings": {
"cmd-n": "agent::NewExternalAgentThread",
"cmd-alt-t": "agent::NewThread"
}
},
{
"context": "MessageEditor && !Picker > Editor && !use_modifier_to_send",
"use_key_equivalents": true,
"bindings": {
"enter": "agent::Chat",
@@ -320,6 +329,18 @@
"cmd-shift-n": "agent::RejectAll"
}
},
{
"context": "MessageEditor && !Picker > Editor && use_modifier_to_send",
"use_key_equivalents": true,
"bindings": {
"cmd-enter": "agent::Chat",
"enter": "editor::Newline",
"cmd-i": "agent::ToggleProfileSelector",
"shift-ctrl-r": "agent::OpenAgentDiff",
"cmd-shift-y": "agent::KeepAll",
"cmd-shift-n": "agent::RejectAll"
}
},
{
"context": "EditMessageEditor > Editor",
"use_key_equivalents": true,
@@ -356,6 +377,16 @@
"ctrl--": "pane::GoBack"
}
},
{
"context": "AcpThread > Editor",
"use_key_equivalents": true,
"bindings": {
"enter": "agent::Chat",
"up": "agent::PreviousHistoryMessage",
"down": "agent::NextHistoryMessage",
"shift-ctrl-r": "agent::OpenAgentDiff"
}
},
{
"context": "ThreadHistory",
"bindings": {
@@ -458,7 +489,7 @@
"ctrl-shift-pageup": "pane::SwapItemLeft",
"ctrl-shift-pagedown": "pane::SwapItemRight",
"cmd-w": ["pane::CloseActiveItem", { "close_pinned": false }],
"alt-cmd-t": ["pane::CloseInactiveItems", { "close_pinned": false }],
"alt-cmd-t": ["pane::CloseOtherItems", { "close_pinned": false }],
"ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes",
"cmd-k e": ["pane::CloseItemsToTheLeft", { "close_pinned": false }],
"cmd-k t": ["pane::CloseItemsToTheRight", { "close_pinned": false }],
@@ -506,11 +537,10 @@
"ctrl-cmd-d": ["editor::SelectPrevious", { "replace_newest": false }], // editor.action.addSelectionToPreviousFindMatch
"cmd-k ctrl-cmd-d": ["editor::SelectPrevious", { "replace_newest": true }], // editor.action.moveSelectionToPreviousFindMatch
"cmd-k cmd-i": "editor::Hover",
"cmd-k cmd-b": "editor::BlameHover",
"cmd-/": ["editor::ToggleComments", { "advance_downwards": false }],
"cmd-u": "editor::UndoSelection",
"cmd-shift-u": "editor::RedoSelection",
"f8": "editor::GoToDiagnostic",
"shift-f8": "editor::GoToPreviousDiagnostic",
"f8": ["editor::GoToDiagnostic", { "severity": { "min": "hint", "max": "error" } }],
"shift-f8": ["editor::GoToPreviousDiagnostic", { "severity": { "min": "hint", "max": "error" } }],
"f2": "editor::Rename",
"f12": "editor::GoToDefinition",
"alt-f12": "editor::GoToDefinitionSplit",
@@ -544,11 +574,25 @@
"cmd-k r": "editor::RevealInFileManager",
"cmd-k p": "editor::CopyPath",
"cmd-\\": "pane::SplitRight",
"cmd-k v": "markdown::OpenPreviewToTheSide",
"cmd-shift-v": "markdown::OpenPreview",
"ctrl-cmd-c": "editor::DisplayCursorNames"
}
},
{
"context": "Editor && extension == md",
"use_key_equivalents": true,
"bindings": {
"cmd-k v": "markdown::OpenPreviewToTheSide",
"cmd-shift-v": "markdown::OpenPreview"
}
},
{
"context": "Editor && extension == svg",
"use_key_equivalents": true,
"bindings": {
"cmd-k v": "svg::OpenPreviewToTheSide",
"cmd-shift-v": "svg::OpenPreview"
}
},
{
"context": "Editor && mode == full",
"use_key_equivalents": true,
@@ -587,6 +631,7 @@
"alt-cmd-o": ["projects::OpenRecent", { "create_new_window": false }],
"ctrl-cmd-o": ["projects::OpenRemote", { "from_existing_connection": false, "create_new_window": false }],
"ctrl-cmd-shift-o": ["projects::OpenRemote", { "from_existing_connection": true, "create_new_window": false }],
"cmd-ctrl-b": "branches::OpenRecent",
"ctrl-~": "workspace::NewTerminal",
"cmd-s": "workspace::Save",
"cmd-k s": "workspace::SaveWithoutFormat",
@@ -604,13 +649,21 @@
"cmd-8": ["workspace::ActivatePane", 7],
"cmd-9": ["workspace::ActivatePane", 8],
"cmd-b": "workspace::ToggleLeftDock",
"cmd-alt-b": "workspace::ToggleRightDock",
"cmd-r": "workspace::ToggleRightDock",
"cmd-j": "workspace::ToggleBottomDock",
"alt-cmd-y": "workspace::CloseAllDocks",
// For 0px parameter, uses UI font size value.
"ctrl-alt-0": "workspace::ResetActiveDockSize",
"ctrl-alt--": ["workspace::DecreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-=": ["workspace::IncreaseActiveDockSize", { "px": 0 }],
"ctrl-alt-)": "workspace::ResetOpenDocksSize",
"ctrl-alt-_": ["workspace::DecreaseOpenDocksSize", { "px": 0 }],
"ctrl-alt-+": ["workspace::IncreaseOpenDocksSize", { "px": 0 }],
"cmd-shift-f": "pane::DeploySearch",
"cmd-shift-h": ["pane::DeploySearch", { "replace_enabled": true }],
"cmd-shift-t": "pane::ReopenClosedItem",
"cmd-k cmd-s": "zed::OpenKeymap",
"cmd-k cmd-s": "zed::OpenKeymapEditor",
"cmd-k cmd-t": "theme_selector::Toggle",
"cmd-t": "project_symbols::Toggle",
"cmd-p": "file_finder::Toggle",
@@ -635,7 +688,8 @@
"cmd-k shift-up": "workspace::SwapPaneUp",
"cmd-k shift-down": "workspace::SwapPaneDown",
"cmd-shift-x": "zed::Extensions",
"f5": "debugger::RerunLastSession"
"f5": "debugger::Rerun",
"cmd-w": "workspace::CloseActiveDock"
}
},
{
@@ -671,6 +725,8 @@
"context": "Editor",
"use_key_equivalents": true,
"bindings": {
"cmd-u": "editor::UndoSelection",
"cmd-shift-u": "editor::RedoSelection",
"ctrl-j": "editor::JoinLines",
"ctrl-alt-backspace": "editor::DeleteToPreviousSubwordStart",
"ctrl-alt-h": "editor::DeleteToPreviousSubwordStart",
@@ -749,6 +805,13 @@
"pagedown": "editor::ContextMenuLast"
}
},
{
"context": "Editor && showing_signature_help && !showing_completions",
"bindings": {
"up": "editor::SignatureHelpPrevious",
"down": "editor::SignatureHelpNext"
}
},
// Custom bindings
{
"use_key_equivalents": true,
@@ -880,6 +943,7 @@
"enter": "menu::Confirm",
"cmd-alt-y": "git::ToggleStaged",
"space": "git::ToggleStaged",
"shift-space": "git::StageRange",
"cmd-y": "git::StageFile",
"cmd-shift-y": "git::UnstageFile",
"alt-down": "git_panel::FocusEditor",
@@ -912,7 +976,7 @@
}
},
{
"context": "GitPanel > Editor",
"context": "CommitEditor > Editor",
"use_key_equivalents": true,
"bindings": {
"enter": "editor::Newline",
@@ -963,7 +1027,9 @@
"context": "BreakpointList",
"bindings": {
"space": "debugger::ToggleEnableBreakpoint",
"backspace": "debugger::UnsetBreakpoint"
"backspace": "debugger::UnsetBreakpoint",
"left": "debugger::PreviousBreakpointProperty",
"right": "debugger::NextBreakpointProperty"
}
},
{
@@ -971,9 +1037,15 @@
"use_key_equivalents": true,
"bindings": {
"ctrl-backspace": "collab_panel::Remove",
"space": "menu::Confirm",
"cmd-up": "collab_panel::MoveChannelUp",
"cmd-down": "collab_panel::MoveChannelDown"
"space": "menu::Confirm"
}
},
{
"context": "CollabPanel",
"use_key_equivalents": true,
"bindings": {
"alt-up": "collab_panel::MoveChannelUp",
"alt-down": "collab_panel::MoveChannelDown"
}
},
{
@@ -1045,13 +1117,16 @@
"ctrl-cmd-space": "terminal::ShowCharacterPalette",
"cmd-c": "terminal::Copy",
"cmd-v": "terminal::Paste",
"cmd-f": "buffer_search::Deploy",
"cmd-a": "editor::SelectAll",
"cmd-k": "terminal::Clear",
"cmd-n": "workspace::NewTerminal",
"ctrl-enter": "assistant::InlineAssist",
"ctrl-_": null, // emacs undo
// Some nice conveniences
"cmd-backspace": ["terminal::SendText", "\u0015"],
"cmd-backspace": ["terminal::SendText", "\u0015"], // ctrl-u: clear line
"alt-delete": ["terminal::SendText", "\u001bd"], // alt-d: delete word forward
"cmd-delete": ["terminal::SendText", "\u000b"], // ctrl-k: delete to end of line
"cmd-right": ["terminal::SendText", "\u0005"],
"cmd-left": ["terminal::SendText", "\u0001"],
// Terminal.app compatibility
@@ -1148,5 +1223,51 @@
"ctrl-tab": "pane::ActivateNextItem",
"ctrl-shift-tab": "pane::ActivatePreviousItem"
}
},
{
"context": "MarkdownPreview",
"bindings": {
"pageup": "markdown::MovePageUp",
"pagedown": "markdown::MovePageDown"
}
},
{
"context": "KeymapEditor",
"use_key_equivalents": true,
"bindings": {
"cmd-f": "search::FocusSearch",
"cmd-alt-f": "keymap_editor::ToggleKeystrokeSearch",
"cmd-alt-c": "keymap_editor::ToggleConflictFilter",
"enter": "keymap_editor::EditBinding",
"alt-enter": "keymap_editor::CreateBinding",
"cmd-c": "keymap_editor::CopyAction",
"cmd-shift-c": "keymap_editor::CopyContext",
"cmd-t": "keymap_editor::ShowMatchingKeybinds"
}
},
{
"context": "KeystrokeInput",
"use_key_equivalents": true,
"bindings": {
"enter": "keystroke_input::StartRecording",
"escape escape escape": "keystroke_input::StopRecording",
"delete": "keystroke_input::ClearKeystrokes"
}
},
{
"context": "KeybindEditorModal",
"use_key_equivalents": true,
"bindings": {
"cmd-enter": "menu::Confirm",
"escape": "menu::Cancel"
}
},
{
"context": "KeybindEditorModal > Editor",
"use_key_equivalents": true,
"bindings": {
"up": "menu::SelectPrevious",
"down": "menu::SelectNext"
}
}
]

View File

@@ -13,9 +13,9 @@
}
},
{
"context": "Editor && vim_mode == insert && !menu",
"context": "Editor && vim_mode == insert",
"bindings": {
// "j k": "vim::SwitchToNormalMode"
// "j k": "vim::NormalBefore"
}
}
]

View File

@@ -59,7 +59,8 @@
"alt->": "editor::MoveToEnd", // end-of-buffer
"ctrl-l": "editor::ScrollCursorCenterTopBottom", // recenter-top-bottom
"ctrl-s": "buffer_search::Deploy", // isearch-forward
"alt-^": "editor::JoinLines" // join-line
"alt-^": "editor::JoinLines", // join-line
"alt-q": "editor::Rewrap" // fill-paragraph
}
},
{
@@ -97,6 +98,13 @@
"ctrl-n": "editor::ContextMenuNext"
}
},
{
"context": "Editor && showing_signature_help && !showing_completions",
"bindings": {
"ctrl-p": "editor::SignatureHelpPrevious",
"ctrl-n": "editor::SignatureHelpNext"
}
},
{
"context": "Workspace",
"bindings": {
@@ -106,7 +114,7 @@
"ctrl-x o": "workspace::ActivateNextPane", // other-window
"ctrl-x k": "pane::CloseActiveItem", // kill-buffer
"ctrl-x 0": "pane::CloseActiveItem", // delete-window
"ctrl-x 1": "pane::CloseInactiveItems", // delete-other-windows
"ctrl-x 1": "pane::CloseOtherItems", // delete-other-windows
"ctrl-x 2": "pane::SplitDown", // split-window-below
"ctrl-x 3": "pane::SplitRight", // split-window-right
"ctrl-x ctrl-f": "file_finder::Toggle", // find-file

View File

@@ -66,22 +66,51 @@
"context": "Editor && mode == full",
"bindings": {
"ctrl-f12": "outline::Toggle",
"alt-7": "outline::Toggle",
"ctrl-r": ["buffer_search::Deploy", { "replace_enabled": true }],
"ctrl-shift-n": "file_finder::Toggle",
"ctrl-g": "go_to_line::Toggle",
"alt-enter": "editor::ToggleCodeActions"
}
},
{
"context": "BufferSearchBar",
"bindings": {
"shift-enter": "search::SelectPreviousMatch"
}
},
{
"context": "BufferSearchBar || ProjectSearchBar",
"bindings": {
"alt-c": "search::ToggleCaseSensitive",
"alt-e": "search::ToggleSelection",
"alt-x": "search::ToggleRegex",
"alt-w": "search::ToggleWholeWord"
}
},
{
"context": "Workspace",
"bindings": {
"ctrl-shift-f12": "workspace::CloseAllDocks",
"ctrl-shift-r": ["pane::DeploySearch", { "replace_enabled": true }],
"alt-shift-f10": "task::Spawn",
"ctrl-e": "file_finder::Toggle",
"ctrl-k": "git_panel::ToggleFocus", // bug: This should also focus commit editor
"ctrl-shift-n": "file_finder::Toggle",
"ctrl-shift-a": "command_palette::Toggle",
"shift shift": "command_palette::Toggle",
"ctrl-alt-shift-n": "project_symbols::Toggle",
"alt-0": "git_panel::ToggleFocus",
"alt-1": "workspace::ToggleLeftDock",
"ctrl-e": "tab_switcher::Toggle",
"alt-6": "diagnostics::Deploy"
"alt-5": "debug_panel::ToggleFocus",
"alt-6": "diagnostics::Deploy",
"alt-7": "outline_panel::ToggleFocus"
}
},
{
"context": "Workspace || Editor",
"bindings": {
"alt-f12": "terminal_panel::ToggleFocus",
"ctrl-shift-k": "git::Push"
}
},
{
@@ -95,10 +124,33 @@
"context": "ProjectPanel",
"bindings": {
"enter": "project_panel::Open",
"ctrl-shift-f": "project_panel::NewSearchInDirectory",
"backspace": ["project_panel::Trash", { "skip_prompt": false }],
"delete": ["project_panel::Trash", { "skip_prompt": false }],
"shift-delete": ["project_panel::Delete", { "skip_prompt": false }],
"shift-f6": "project_panel::Rename"
}
},
{
"context": "Terminal",
"bindings": {
"ctrl-shift-t": "workspace::NewTerminal",
"alt-f12": "workspace::CloseActiveDock",
"alt-left": "pane::ActivatePreviousItem",
"alt-right": "pane::ActivateNextItem",
"ctrl-up": "terminal::ScrollLineUp",
"ctrl-down": "terminal::ScrollLineDown",
"shift-pageup": "terminal::ScrollPageUp",
"shift-pagedown": "terminal::ScrollPageDown"
}
},
{ "context": "GitPanel", "bindings": { "alt-0": "workspace::CloseActiveDock" } },
{ "context": "ProjectPanel", "bindings": { "alt-1": "workspace::CloseActiveDock" } },
{ "context": "DebugPanel", "bindings": { "alt-5": "workspace::CloseActiveDock" } },
{ "context": "Diagnostics > Editor", "bindings": { "alt-6": "pane::CloseActiveItem" } },
{ "context": "OutlinePanel", "bindings": { "alt-7": "workspace::CloseActiveDock" } },
{
"context": "Dock || Workspace || Terminal || OutlinePanel || ProjectPanel || CollabPanel || (Editor && mode == auto_height)",
"bindings": { "escape": "editor::ToggleFocus" }
}
]

View File

@@ -59,7 +59,8 @@
"alt->": "editor::MoveToEnd", // end-of-buffer
"ctrl-l": "editor::ScrollCursorCenterTopBottom", // recenter-top-bottom
"ctrl-s": "buffer_search::Deploy", // isearch-forward
"alt-^": "editor::JoinLines" // join-line
"alt-^": "editor::JoinLines", // join-line
"alt-q": "editor::Rewrap" // fill-paragraph
}
},
{
@@ -97,6 +98,13 @@
"ctrl-n": "editor::ContextMenuNext"
}
},
{
"context": "Editor && showing_signature_help && !showing_completions",
"bindings": {
"ctrl-p": "editor::SignatureHelpPrevious",
"ctrl-n": "editor::SignatureHelpNext"
}
},
{
"context": "Workspace",
"bindings": {
@@ -106,7 +114,7 @@
"ctrl-x o": "workspace::ActivateNextPane", // other-window
"ctrl-x k": "pane::CloseActiveItem", // kill-buffer
"ctrl-x 0": "pane::CloseActiveItem", // delete-window
"ctrl-x 1": "pane::CloseInactiveItems", // delete-other-windows
"ctrl-x 1": "pane::CloseOtherItems", // delete-other-windows
"ctrl-x 2": "pane::SplitDown", // split-window-below
"ctrl-x 3": "pane::SplitRight", // split-window-right
"ctrl-x ctrl-f": "file_finder::Toggle", // find-file

View File

@@ -3,6 +3,7 @@
"bindings": {
"cmd-{": "pane::ActivatePreviousItem",
"cmd-}": "pane::ActivateNextItem",
"cmd-0": "git_panel::ToggleFocus", // overrides `cmd-0` zoom reset
"ctrl-f2": "debugger::Stop",
"f6": "debugger::Pause",
"f7": "debugger::StepInto",
@@ -63,28 +64,55 @@
"context": "Editor && mode == full",
"bindings": {
"cmd-f12": "outline::Toggle",
"cmd-7": "outline::Toggle",
"cmd-r": ["buffer_search::Deploy", { "replace_enabled": true }],
"cmd-shift-o": "file_finder::Toggle",
"cmd-l": "go_to_line::Toggle",
"alt-enter": "editor::ToggleCodeActions"
}
},
{
"context": "BufferSearchBar > Editor",
"context": "BufferSearchBar",
"bindings": {
"shift-enter": "search::SelectPreviousMatch"
}
},
{
"context": "BufferSearchBar || ProjectSearchBar",
"bindings": {
"alt-c": "search::ToggleCaseSensitive",
"alt-e": "search::ToggleSelection",
"alt-x": "search::ToggleRegex",
"alt-w": "search::ToggleWholeWord",
"ctrl-alt-c": "search::ToggleCaseSensitive",
"ctrl-alt-e": "search::ToggleSelection",
"ctrl-alt-w": "search::ToggleWholeWord",
"ctrl-alt-x": "search::ToggleRegex"
}
},
{
"context": "Workspace",
"bindings": {
"cmd-shift-f12": "workspace::CloseAllDocks",
"cmd-shift-r": ["pane::DeploySearch", { "replace_enabled": true }],
"ctrl-alt-r": "task::Spawn",
"cmd-e": "file_finder::Toggle",
"cmd-k": "git_panel::ToggleFocus", // bug: This should also focus commit editor
"cmd-shift-o": "file_finder::Toggle",
"cmd-shift-a": "command_palette::Toggle",
"shift shift": "command_palette::Toggle",
"cmd-alt-o": "project_symbols::Toggle", // JetBrains: Go to Symbol
"cmd-o": "project_symbols::Toggle", // JetBrains: Go to Class
"cmd-1": "workspace::ToggleLeftDock",
"cmd-6": "diagnostics::Deploy"
"cmd-1": "project_panel::ToggleFocus",
"cmd-5": "debug_panel::ToggleFocus",
"cmd-6": "diagnostics::Deploy",
"cmd-7": "outline_panel::ToggleFocus"
}
},
{
"context": "Workspace || Editor",
"bindings": {
"alt-f12": "terminal_panel::ToggleFocus",
"cmd-shift-k": "git::Push"
}
},
{
@@ -98,11 +126,31 @@
"context": "ProjectPanel",
"bindings": {
"enter": "project_panel::Open",
"cmd-shift-f": "project_panel::NewSearchInDirectory",
"cmd-backspace": ["project_panel::Trash", { "skip_prompt": false }],
"backspace": ["project_panel::Trash", { "skip_prompt": false }],
"delete": ["project_panel::Trash", { "skip_prompt": false }],
"shift-delete": ["project_panel::Delete", { "skip_prompt": false }],
"shift-f6": "project_panel::Rename"
}
},
{
"context": "Terminal",
"bindings": {
"cmd-t": "workspace::NewTerminal",
"alt-f12": "workspace::CloseActiveDock",
"cmd-up": "terminal::ScrollLineUp",
"cmd-down": "terminal::ScrollLineDown",
"shift-pageup": "terminal::ScrollPageUp",
"shift-pagedown": "terminal::ScrollPageDown"
}
},
{ "context": "GitPanel", "bindings": { "cmd-0": "workspace::CloseActiveDock" } },
{ "context": "DebugPanel", "bindings": { "cmd-5": "workspace::CloseActiveDock" } },
{ "context": "Diagnostics > Editor", "bindings": { "cmd-6": "pane::CloseActiveItem" } },
{ "context": "OutlinePanel", "bindings": { "cmd-7": "workspace::CloseActiveDock" } },
{
"context": "Dock || Workspace || Terminal || OutlinePanel || ProjectPanel || CollabPanel || (Editor && mode == auto_height)",
"bindings": { "escape": "editor::ToggleFocus" }
}
]

View File

@@ -6,7 +6,7 @@
}
},
{
"context": "Editor",
"context": "Editor && mode == full",
"bindings": {
"cmd-l": "go_to_line::Toggle",
"ctrl-shift-d": "editor::DuplicateLineDown",
@@ -15,7 +15,12 @@
"cmd-enter": "editor::NewlineBelow",
"cmd-alt-enter": "editor::NewlineAbove",
"cmd-shift-l": "editor::SelectLine",
"cmd-shift-t": "outline::Toggle",
"cmd-shift-t": "outline::Toggle"
}
},
{
"context": "Editor",
"bindings": {
"alt-backspace": "editor::DeleteToPreviousWordStart",
"alt-shift-backspace": "editor::DeleteToNextWordEnd",
"alt-delete": "editor::DeleteToNextWordEnd",
@@ -39,10 +44,6 @@
"ctrl-_": "editor::ConvertToSnakeCase"
}
},
{
"context": "Editor && mode == full",
"bindings": {}
},
{
"context": "BufferSearchBar",
"bindings": {

View File

@@ -124,6 +124,7 @@
"g r a": "editor::ToggleCodeActions",
"g g": "vim::StartOfDocument",
"g h": "editor::Hover",
"g B": "editor::BlameHover",
"g t": "pane::ActivateNextItem",
"g shift-t": "pane::ActivatePreviousItem",
"g d": "editor::GoToDefinition",
@@ -189,6 +190,8 @@
"z shift-r": "editor::UnfoldAll",
"z l": "vim::ColumnRight",
"z h": "vim::ColumnLeft",
"z shift-l": "vim::HalfPageRight",
"z shift-h": "vim::HalfPageLeft",
"shift-z shift-q": ["pane::CloseActiveItem", { "save_intent": "skip" }],
"shift-z shift-z": ["pane::CloseActiveItem", { "save_intent": "save_all" }],
// Count support
@@ -210,43 +213,26 @@
"ctrl-w space": "editor::OpenExcerptsSplit",
"ctrl-w g space": "editor::OpenExcerptsSplit",
"ctrl-6": "pane::AlternateFile",
"ctrl-^": "pane::AlternateFile"
"ctrl-^": "pane::AlternateFile",
".": "vim::Repeat"
}
},
{
"context": "vim_mode == normal",
"bindings": {
"ctrl-[": "editor::Cancel",
"escape": "editor::Cancel",
":": "command_palette::Toggle",
".": "vim::Repeat",
"c": "vim::PushChange",
"shift-c": "vim::ChangeToEndOfLine",
"d": "vim::PushDelete",
"delete": "vim::DeleteRight",
"shift-d": "vim::DeleteToEndOfLine",
"shift-j": "vim::JoinLines",
"g shift-j": "vim::JoinLinesNoWhitespace",
"y": "vim::PushYank",
"shift-y": "vim::YankLine",
"i": "vim::InsertBefore",
"shift-i": "vim::InsertFirstNonWhitespace",
"a": "vim::InsertAfter",
"shift-a": "vim::InsertEndOfLine",
"x": "vim::DeleteRight",
"shift-x": "vim::DeleteLeft",
"o": "vim::InsertLineBelow",
"shift-o": "vim::InsertLineAbove",
"~": "vim::ChangeCase",
"ctrl-a": "vim::Increment",
"ctrl-x": "vim::Decrement",
"p": "vim::Paste",
"shift-p": ["vim::Paste", { "before": true }],
"u": "vim::Undo",
"ctrl-r": "vim::Redo",
"r": "vim::PushReplace",
"s": "vim::Substitute",
"shift-s": "vim::SubstituteLine",
">": "vim::PushIndent",
"<": "vim::PushOutdent",
"=": "vim::PushAutoIndent",
@@ -256,11 +242,8 @@
"g ~": "vim::PushOppositeCase",
"g ?": "vim::PushRot13",
// "g ?": "vim::PushRot47",
"\"": "vim::PushRegister",
"g w": "vim::PushRewrap",
"g q": "vim::PushRewrap",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePreviousItem",
"insert": "vim::InsertBefore",
// tree-sitter related commands
"[ x": "vim::SelectLargerSyntaxNode",
@@ -327,6 +310,7 @@
"g shift-r": ["vim::Paste", { "preserve_clipboard": true }],
"g c": "vim::ToggleComments",
"g q": "vim::Rewrap",
"g w": "vim::Rewrap",
"g ?": "vim::ConvertToRot13",
// "g ?": "vim::ConvertToRot47",
"\"": "vim::PushRegister",
@@ -363,18 +347,11 @@
}
},
{
"context": "vim_mode == helix_normal && !menu",
"context": "(vim_mode == normal || vim_mode == helix_normal) && !menu",
"bindings": {
"escape": "editor::Cancel",
"ctrl-[": "editor::Cancel",
":": "command_palette::Toggle",
"left": "vim::WrappingLeft",
"right": "vim::WrappingRight",
"h": "vim::WrappingLeft",
"l": "vim::WrappingRight",
"shift-d": "vim::DeleteToEndOfLine",
"shift-j": "vim::JoinLines",
"y": "editor::Copy",
"shift-y": "vim::YankLine",
"i": "vim::InsertBefore",
"shift-i": "vim::InsertFirstNonWhitespace",
@@ -388,27 +365,41 @@
"p": "vim::Paste",
"shift-p": ["vim::Paste", { "before": true }],
"u": "vim::Undo",
"shift-u": "vim::UndoLastLine",
"r": "vim::PushReplace",
"s": "vim::Substitute",
"shift-s": "vim::SubstituteLine",
"\"": "vim::PushRegister",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePreviousItem"
}
},
{
"context": "vim_mode == helix_normal && !menu",
"bindings": {
"ctrl-[": "editor::Cancel",
";": "vim::HelixCollapseSelection",
":": "command_palette::Toggle",
"left": "vim::WrappingLeft",
"right": "vim::WrappingRight",
"h": "vim::WrappingLeft",
"l": "vim::WrappingRight",
"y": "editor::Copy",
"alt-;": "vim::OtherEnd",
"ctrl-r": "vim::Redo",
"f": ["vim::PushFindForward", { "before": false, "multiline": true }],
"t": ["vim::PushFindForward", { "before": true, "multiline": true }],
"shift-f": ["vim::PushFindBackward", { "after": false, "multiline": true }],
"shift-t": ["vim::PushFindBackward", { "after": true, "multiline": true }],
"r": "vim::PushReplace",
"s": "vim::Substitute",
"shift-s": "vim::SubstituteLine",
">": "vim::Indent",
"<": "vim::Outdent",
"=": "vim::AutoIndent",
"g u": "vim::PushLowercase",
"g shift-u": "vim::PushUppercase",
"g ~": "vim::PushOppositeCase",
"\"": "vim::PushRegister",
"g q": "vim::PushRewrap",
"g w": "vim::PushRewrap",
"ctrl-pagedown": "pane::ActivateNextItem",
"ctrl-pageup": "pane::ActivatePreviousItem",
"insert": "vim::InsertBefore",
".": "vim::Repeat",
"alt-.": "vim::RepeatFind",
// tree-sitter related commands
"[ x": "editor::SelectLargerSyntaxNode",
@@ -428,7 +419,6 @@
"g h": "vim::StartOfLine",
"g s": "vim::FirstNonWhitespace", // "g s" default behavior is "space s"
"g e": "vim::EndOfDocument",
"g y": "editor::GoToTypeDefinition",
"g r": "editor::FindAllReferences", // zed specific
"g t": "vim::WindowTop",
"g c": "vim::WindowMiddle",
@@ -477,6 +467,13 @@
"ctrl-n": "editor::ShowWordCompletions"
}
},
{
"context": "(vim_mode == insert || vim_mode == normal) && showing_signature_help && !showing_completions",
"bindings": {
"ctrl-p": "editor::SignatureHelpPrevious",
"ctrl-n": "editor::SignatureHelpNext"
}
},
{
"context": "vim_mode == replace",
"bindings": {
@@ -728,7 +725,7 @@
}
},
{
"context": "AgentPanel || GitPanel || ProjectPanel || CollabPanel || OutlinePanel || ChatPanel || VimControl || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || DebugPanel",
"context": "VimControl || !Editor && !Terminal",
"bindings": {
// window related commands (ctrl-w X)
"ctrl-w": null,
@@ -786,7 +783,7 @@
}
},
{
"context": "ChangesList || EmptyPane || SharedScreen || MarkdownPreview || KeyContextView || Welcome",
"context": "!Editor && !Terminal",
"bindings": {
":": "command_palette::Toggle",
"g /": "pane::DeploySearch"
@@ -846,9 +843,37 @@
"i": "git_panel::FocusEditor",
"x": "git::ToggleStaged",
"shift-x": "git::StageAll",
"g x": "git::StageRange",
"shift-u": "git::UnstageAll"
}
},
{
"context": "Editor && mode == auto_height && VimControl",
"bindings": {
// TODO: Implement search
"/": null,
"?": null,
"#": null,
"*": null,
"n": null,
"shift-n": null
}
},
{
"context": "Picker > Editor",
"bindings": {
"ctrl-h": "editor::Backspace",
"ctrl-u": "editor::DeleteToBeginningOfLine",
"ctrl-w": "editor::DeleteToPreviousWordStart"
}
},
{
"context": "GitCommit > Editor && VimControl && vim_mode == normal",
"bindings": {
"ctrl-c": "menu::Cancel",
"escape": "menu::Cancel"
}
},
{
"context": "Editor && edit_prediction",
"bindings": {
@@ -860,14 +885,7 @@
{
"context": "MessageEditor > Editor && VimControl",
"bindings": {
"enter": "agent::Chat",
// TODO: Implement search
"/": null,
"?": null,
"#": null,
"*": null,
"n": null,
"shift-n": null
"enter": "agent::Chat"
}
},
{

View File

@@ -84,7 +84,7 @@
"bottom_dock_layout": "contained",
// The direction that you want to split panes horizontally. Defaults to "up"
"pane_split_direction_horizontal": "up",
// The direction that you want to split panes horizontally. Defaults to "left"
// The direction that you want to split panes vertically. Defaults to "left"
"pane_split_direction_vertical": "left",
// Centered layout related settings.
"centered_layout": {
@@ -197,6 +197,8 @@
// "inline"
// 3. Place snippets at the bottom of the completion list:
// "bottom"
// 4. Do not show snippets in the completion list:
// "none"
"snippet_sort_order": "inline",
// How to highlight the current line in the editor.
//
@@ -228,7 +230,12 @@
// Whether to show code action button at start of buffer line.
"inline_code_actions": true,
// Whether to allow drag and drop text selection in buffer.
"drag_and_drop_selection": true,
"drag_and_drop_selection": {
// When true, enables drag and drop text selection in buffer.
"enabled": true,
// The delay in milliseconds that must elapse before drag and drop is allowed. Otherwise, a new text selection is created.
"delay": 300
},
// What to do when go to definition yields no results.
//
// 1. Do nothing: `none`
@@ -357,7 +364,9 @@
// Whether to show user picture in the titlebar.
"show_user_picture": true,
// Whether to show the sign in button in the titlebar.
"show_sign_in": true
"show_sign_in": true,
// Whether to show the menus in the titlebar.
"show_menus": false
},
// Scrollbar related settings
"scrollbar": {
@@ -617,6 +626,8 @@
// 3. Mark files with errors and warnings:
// "all"
"show_diagnostics": "all",
// Whether to stick parent directories at top of the project panel.
"sticky_scroll": true,
// Settings related to indent guides in the project panel.
"indent_guides": {
// When to show indent guides in the project panel.
@@ -680,7 +691,10 @@
// 5. Never show the scrollbar:
// "never"
"show": null
}
},
// Default depth to expand outline items in the current file.
// Set to 0 to collapse all items that have children, 1 or higher to collapse items at that depth or deeper.
"expand_outlines_with_depth": 100
},
"collaboration_panel": {
// Whether to show the collaboration panel button in the status bar.
@@ -746,8 +760,6 @@
"default_width": 380
},
"agent": {
// Version of this setting.
"version": "2",
// Whether the agent is enabled.
"enabled": true,
/// What completion mode to start new threads in, if available. Can be 'normal' or 'burn'.
@@ -810,6 +822,7 @@
"edit_file": true,
"fetch": true,
"list_directory": true,
"project_notifications": false,
"move_path": true,
"now": true,
"find_path": true,
@@ -829,6 +842,7 @@
"diagnostics": true,
"fetch": true,
"list_directory": true,
"project_notifications": false,
"now": true,
"find_path": true,
"read_file": true,
@@ -855,7 +869,15 @@
// its response, or needs user input.
// Default: false
"play_sound_when_agent_done": false
"play_sound_when_agent_done": false,
/// Whether to have edit cards in the agent panel expanded, showing a preview of the full diff.
///
/// Default: true
"expand_edit_card": true,
/// Whether to have terminal cards in the agent panel expanded, showing the whole command output.
///
/// Default: true
"expand_terminal_card": true
},
// The settings for slash commands.
"slash_commands": {
@@ -1057,6 +1079,10 @@
// Send anonymized usage data like what languages you're using Zed with.
"metrics": true
},
// Whether to disable all AI features in Zed.
//
// Default: false
"disable_ai": false,
// Automatically update Zed. This setting may be ignored on Linux if
// installed through a package manager.
"auto_update": true,
@@ -1118,6 +1144,7 @@
"**/.svn",
"**/.hg",
"**/.jj",
"**/.repo",
"**/CVS",
"**/.DS_Store",
"**/Thumbs.db",
@@ -1140,16 +1167,14 @@
// Control whether the git blame information is shown inline,
// in the currently focused line.
"inline_blame": {
"enabled": true
"enabled": true,
// Sets a delay after which the inline blame information is shown.
// Delay is restarted with every cursor movement.
// "delay_ms": 600
//
"delay_ms": 0,
// Whether or not to display the git commit summary on the same line.
// "show_commit_summary": false
//
"show_commit_summary": false,
// The minimum column number to show the inline blame information at
// "min_column": 0
"min_column": 0
},
// How git hunks are displayed visually in the editor.
// This setting can take two values:
@@ -1292,6 +1317,8 @@
// Whether or not selecting text in the terminal will automatically
// copy to the system clipboard.
"copy_on_select": false,
// Whether to keep the text selection after copying it to the clipboard
"keep_selection_on_copy": false,
// Whether to show the terminal button in the status bar
"button": true,
// Any key-value pairs added to this list will be added to the terminal's
@@ -1348,7 +1375,7 @@
// 5. Never show the scrollbar:
// "never"
"show": null
}
},
// Set the terminal's font size. If this option is not included,
// the terminal will default to matching the buffer's font size.
// "font_size": 15,
@@ -1360,11 +1387,26 @@
// This will be merged with the platform's default font fallbacks
// "font_fallbacks": ["FiraCode Nerd Fonts"],
// The weight of the editor font in standard CSS units from 100 to 900.
// "font_weight": 400
"font_weight": 400,
// Sets the maximum number of lines in the terminal's scrollback buffer.
// Default: 10_000, maximum: 100_000 (all bigger values set will be treated as 100_000), 0 disables the scrolling.
// Existing terminals will not pick up this change until they are recreated.
// "max_scroll_history_lines": 10000,
"max_scroll_history_lines": 10000,
// The minimum APCA perceptual contrast between foreground and background colors.
// APCA (Accessible Perceptual Contrast Algorithm) is more accurate than WCAG 2.x,
// especially for dark mode. Values range from 0 to 106.
//
// Based on APCA Readability Criterion (ARC) Bronze Simple Mode:
// https://readtech.org/ARC/tests/bronze-simple-mode/
// - 0: No contrast adjustment
// - 45: Minimum for large fluent text (36px+)
// - 60: Minimum for other content text
// - 75: Minimum for body text
// - 90: Preferred for body text
//
// Most terminal themes have APCA values of 40-70.
// A value of 45 preserves colorful themes while ensuring legibility.
"minimum_contrast": 45
},
"code_actions_on_format": {},
// Settings related to running tasks.
@@ -1576,6 +1618,9 @@
"use_on_type_format": false,
"allow_rewrap": "anywhere",
"soft_wrap": "editor_width",
"completions": {
"words": "disabled"
},
"prettier": {
"allowed": true
}
@@ -1589,6 +1634,9 @@
}
},
"Plain Text": {
"completions": {
"words": "disabled"
},
"allow_rewrap": "anywhere"
},
"Python": {
@@ -1632,6 +1680,10 @@
"allowed": true
}
},
"SystemVerilog": {
"format_on_save": "off",
"use_on_type_format": false
},
"Vue.js": {
"language_servers": ["vue-language-server", "..."],
"prettier": {
@@ -1656,7 +1708,6 @@
// Different settings for specific language models.
"language_models": {
"anthropic": {
"version": "1",
"api_url": "https://api.anthropic.com"
},
"google": {
@@ -1666,9 +1717,9 @@
"api_url": "http://localhost:11434"
},
"openai": {
"version": "1",
"api_url": "https://api.openai.com/v1"
},
"openai_compatible": {},
"open_router": {
"api_url": "https://openrouter.ai/api/v1"
},
@@ -1784,7 +1835,8 @@
// `socks5h`. `http` will be used when no scheme is specified.
//
// By default no proxy will be used, or Zed will try get proxy settings from
// environment variables.
// environment variables. If certain hosts should not be proxied,
// set the `no_proxy` environment variable and provide a comma-separated list.
//
// Examples:
// - "proxy": "socks5h://localhost:10808"
@@ -1818,6 +1870,8 @@
"read_ssh_config": true,
// Configures context servers for use by the agent.
"context_servers": {},
// Configures agent servers available in the agent panel.
"agent_servers": {},
"debugger": {
"stepping_granularity": "line",
"save_breakpoints": true,

View File

@@ -3,13 +3,6 @@
// For more documentation on how to configure debug tasks,
// see: https://zed.dev/docs/debugger
[
{
"label": "Debug active PHP file",
"adapter": "PHP",
"program": "$ZED_FILE",
"request": "launch",
"cwd": "$ZED_WORKTREE_ROOT"
},
{
"label": "Debug active Python file",
"adapter": "Debugpy",
@@ -22,13 +15,15 @@
"adapter": "JavaScript",
"program": "$ZED_FILE",
"request": "launch",
"cwd": "$ZED_WORKTREE_ROOT"
"cwd": "$ZED_WORKTREE_ROOT",
"type": "pwa-node"
},
{
"label": "JavaScript debug terminal",
"adapter": "JavaScript",
"request": "launch",
"cwd": "$ZED_WORKTREE_ROOT",
"console": "integratedTerminal"
"console": "integratedTerminal",
"type": "pwa-node"
}
]

View File

@@ -8,7 +8,7 @@
// command palette (cmd-shift-p / ctrl-shift-p)
{
"ui_font_size": 16,
"buffer_font_size": 16,
"buffer_font_size": 15,
"theme": {
"mode": "system",
"light": "One Light",

View File

@@ -59,5 +59,11 @@ services:
depends_on:
- postgres
stripe-mock:
image: stripe/stripe-mock:v0.178.0
ports:
- 12111:12111
- 12112:12112
volumes:
postgres_data:

View File

@@ -0,0 +1,46 @@
[package]
name = "acp_thread"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/acp_thread.rs"
doctest = false
[features]
test-support = ["gpui/test-support", "project/test-support"]
[dependencies]
agentic-coding-protocol.workspace = true
anyhow.workspace = true
assistant_tool.workspace = true
buffer_diff.workspace = true
editor.workspace = true
futures.workspace = true
gpui.workspace = true
itertools.workspace = true
language.workspace = true
markdown.workspace = true
project.workspace = true
serde.workspace = true
serde_json.workspace = true
settings.workspace = true
smol.workspace = true
ui.workspace = true
util.workspace = true
workspace-hack.workspace = true
[dev-dependencies]
async-pipe.workspace = true
env_logger.workspace = true
gpui = { workspace = true, "features" = ["test-support"] }
indoc.workspace = true
project = { workspace = true, "features" = ["test-support"] }
tempfile.workspace = true
util.workspace = true
settings.workspace = true

View File

@@ -0,0 +1 @@
../../LICENSE-GPL

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
use agentic_coding_protocol as acp;
use anyhow::Result;
use futures::future::{FutureExt as _, LocalBoxFuture};
pub trait AgentConnection {
fn request_any(
&self,
params: acp::AnyAgentRequest,
) -> LocalBoxFuture<'static, Result<acp::AnyAgentResult>>;
}
impl AgentConnection for acp::AgentConnection {
fn request_any(
&self,
params: acp::AnyAgentRequest,
) -> LocalBoxFuture<'static, Result<acp::AnyAgentResult>> {
let task = self.request_any(params);
async move { Ok(task.await?) }.boxed_local()
}
}

View File

@@ -31,7 +31,13 @@ use workspace::{StatusItemView, Workspace, item::ItemHandle};
const GIT_OPERATION_DELAY: Duration = Duration::from_millis(0);
actions!(activity_indicator, [ShowErrorMessage]);
actions!(
activity_indicator,
[
/// Displays error messages from language servers in the status bar.
ShowErrorMessage
]
);
pub enum Event {
ShowStatus {
@@ -225,7 +231,6 @@ impl ActivityIndicator {
status,
} => {
let create_buffer = project.update(cx, |project, cx| project.create_buffer(cx));
let project = project.clone();
let status = status.clone();
let server_name = server_name.clone();
cx.spawn_in(window, async move |workspace, cx| {
@@ -241,8 +246,7 @@ impl ActivityIndicator {
workspace.update_in(cx, |workspace, window, cx| {
workspace.add_item_to_active_pane(
Box::new(cx.new(|cx| {
let mut editor =
Editor::for_buffer(buffer, Some(project.clone()), window, cx);
let mut editor = Editor::for_buffer(buffer, None, window, cx);
editor.set_read_only(true);
editor
})),
@@ -442,7 +446,7 @@ impl ActivityIndicator {
.into_any_element(),
),
message: format!("Debug: {}", session.read(cx).adapter()),
tooltip_message: Some(session.read(cx).label().to_string()),
tooltip_message: session.read(cx).label().map(|label| label.to_string()),
on_click: None,
});
}

View File

@@ -72,6 +72,7 @@ gpui = { workspace = true, "features" = ["test-support"] }
indoc.workspace = true
language = { workspace = true, "features" = ["test-support"] }
language_model = { workspace = true, "features" = ["test-support"] }
parking_lot.workspace = true
pretty_assertions.workspace = true
project = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use agent_settings::{AgentProfileId, AgentProfileSettings, AgentSettings};
use assistant_tool::{Tool, ToolSource, ToolWorkingSet};
use assistant_tool::{Tool, ToolSource, ToolWorkingSet, UniqueToolName};
use collections::IndexMap;
use convert_case::{Case, Casing};
use fs::Fs;
@@ -72,7 +72,7 @@ impl AgentProfile {
&self.id
}
pub fn enabled_tools(&self, cx: &App) -> Vec<Arc<dyn Tool>> {
pub fn enabled_tools(&self, cx: &App) -> Vec<(UniqueToolName, Arc<dyn Tool>)> {
let Some(settings) = AgentSettings::get_global(cx).profiles.get(&self.id) else {
return Vec::new();
};
@@ -81,7 +81,7 @@ impl AgentProfile {
.read(cx)
.tools(cx)
.into_iter()
.filter(|tool| Self::is_enabled(settings, tool.source(), tool.name()))
.filter(|(_, tool)| Self::is_enabled(settings, tool.source(), tool.name()))
.collect()
}
@@ -96,16 +96,11 @@ impl AgentProfile {
fn is_enabled(settings: &AgentProfileSettings, source: ToolSource, name: String) -> bool {
match source {
ToolSource::Native => *settings.tools.get(name.as_str()).unwrap_or(&false),
ToolSource::ContextServer { id } => {
if settings.enable_all_context_servers {
return true;
}
let Some(preset) = settings.context_servers.get(id.as_ref()) else {
return false;
};
*preset.tools.get(name.as_str()).unwrap_or(&false)
}
ToolSource::ContextServer { id } => settings
.context_servers
.get(id.as_ref())
.and_then(|preset| preset.tools.get(name.as_str()).copied())
.unwrap_or(settings.enable_all_context_servers),
}
}
}
@@ -142,7 +137,7 @@ mod tests {
let mut enabled_tools = cx
.read(|cx| profile.enabled_tools(cx))
.into_iter()
.map(|tool| tool.name())
.map(|(_, tool)| tool.name())
.collect::<Vec<_>>();
enabled_tools.sort();
@@ -179,7 +174,7 @@ mod tests {
let mut enabled_tools = cx
.read(|cx| profile.enabled_tools(cx))
.into_iter()
.map(|tool| tool.name())
.map(|(_, tool)| tool.name())
.collect::<Vec<_>>();
enabled_tools.sort();
@@ -212,7 +207,7 @@ mod tests {
let mut enabled_tools = cx
.read(|cx| profile.enabled_tools(cx))
.into_iter()
.map(|tool| tool.name())
.map(|(_, tool)| tool.name())
.collect::<Vec<_>>();
enabled_tools.sort();
@@ -272,10 +267,10 @@ mod tests {
}
fn default_tool_set(cx: &mut TestAppContext) -> Entity<ToolWorkingSet> {
cx.new(|_| {
cx.new(|cx| {
let mut tool_set = ToolWorkingSet::default();
tool_set.insert(Arc::new(FakeTool::new("enabled_mcp_tool", "mcp")));
tool_set.insert(Arc::new(FakeTool::new("disabled_mcp_tool", "mcp")));
tool_set.insert(Arc::new(FakeTool::new("enabled_mcp_tool", "mcp")), cx);
tool_set.insert(Arc::new(FakeTool::new("disabled_mcp_tool", "mcp")), cx);
tool_set
})
}

View File

@@ -38,7 +38,7 @@ impl Tool for ContextServerTool {
}
fn icon(&self) -> IconName {
IconName::Cog
IconName::ToolHammer
}
fn source(&self) -> ToolSource {

View File

@@ -0,0 +1,3 @@
[The following is an auto-generated notification; do not reply]
These files have changed since the last read:

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@ use crate::{
};
use agent_settings::{AgentProfileId, CompletionMode};
use anyhow::{Context as _, Result, anyhow};
use assistant_tool::{ToolId, ToolWorkingSet};
use assistant_tool::{Tool, ToolId, ToolWorkingSet};
use chrono::{DateTime, Utc};
use collections::HashMap;
use context_server::ContextServerId;
@@ -537,8 +537,8 @@ impl ThreadStore {
}
ContextServerStatus::Stopped | ContextServerStatus::Error(_) => {
if let Some(tool_ids) = self.context_server_tool_ids.remove(server_id) {
tool_working_set.update(cx, |tool_working_set, _| {
tool_working_set.remove(&tool_ids);
tool_working_set.update(cx, |tool_working_set, cx| {
tool_working_set.remove(&tool_ids, cx);
});
}
}
@@ -569,19 +569,17 @@ impl ThreadStore {
.log_err()
{
let tool_ids = tool_working_set
.update(cx, |tool_working_set, _| {
response
.tools
.into_iter()
.map(|tool| {
log::info!("registering context server tool: {:?}", tool.name);
tool_working_set.insert(Arc::new(ContextServerTool::new(
.update(cx, |tool_working_set, cx| {
tool_working_set.extend(
response.tools.into_iter().map(|tool| {
Arc::new(ContextServerTool::new(
context_server_store.clone(),
server.id(),
tool,
)))
})
.collect::<Vec<_>>()
)) as Arc<dyn Tool>
}),
cx,
)
})
.log_err();

View File

@@ -2,6 +2,7 @@ use crate::{
thread::{MessageId, PromptId, ThreadId},
thread_store::SerializedMessage,
};
use agent_settings::CompletionMode;
use anyhow::Result;
use assistant_tool::{
AnyToolCard, Tool, ToolResultContent, ToolResultOutput, ToolUseStatus, ToolWorkingSet,
@@ -11,8 +12,9 @@ use futures::{FutureExt as _, future::Shared};
use gpui::{App, Entity, SharedString, Task, Window};
use icons::IconName;
use language_model::{
ConfiguredModel, LanguageModel, LanguageModelRequest, LanguageModelToolResult,
LanguageModelToolResultContent, LanguageModelToolUse, LanguageModelToolUseId, Role,
ConfiguredModel, LanguageModel, LanguageModelExt, LanguageModelRequest,
LanguageModelToolResult, LanguageModelToolResultContent, LanguageModelToolUse,
LanguageModelToolUseId, Role,
};
use project::Project;
use std::sync::Arc;
@@ -400,6 +402,7 @@ impl ToolUseState {
tool_name: Arc<str>,
output: Result<ToolResultOutput>,
configured_model: Option<&ConfiguredModel>,
completion_mode: CompletionMode,
) -> Option<PendingToolUse> {
let metadata = self.tool_use_metadata_by_id.remove(&tool_use_id);
@@ -426,7 +429,10 @@ impl ToolUseState {
// Protect from overly large output
let tool_output_limit = configured_model
.map(|model| model.model.max_token_count() as usize * BYTES_PER_TOKEN_ESTIMATE)
.map(|model| {
model.model.max_token_count_for_mode(completion_mode.into()) as usize
* BYTES_PER_TOKEN_ESTIMATE
})
.unwrap_or(usize::MAX);
let content = match tool_result {

View File

@@ -0,0 +1,54 @@
[package]
name = "agent_servers"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[features]
test-support = ["acp_thread/test-support", "gpui/test-support", "project/test-support"]
e2e = []
[lints]
workspace = true
[lib]
path = "src/agent_servers.rs"
doctest = false
[dependencies]
acp_thread.workspace = true
agentic-coding-protocol.workspace = true
anyhow.workspace = true
collections.workspace = true
context_server.workspace = true
futures.workspace = true
gpui.workspace = true
itertools.workspace = true
log.workspace = true
paths.workspace = true
project.workspace = true
schemars.workspace = true
serde.workspace = true
serde_json.workspace = true
settings.workspace = true
smol.workspace = true
strum.workspace = true
tempfile.workspace = true
ui.workspace = true
util.workspace = true
uuid.workspace = true
watch.workspace = true
which.workspace = true
workspace-hack.workspace = true
[target.'cfg(unix)'.dependencies]
libc.workspace = true
nix.workspace = true
[dev-dependencies]
env_logger.workspace = true
language.workspace = true
indoc.workspace = true
acp_thread = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }

View File

@@ -0,0 +1 @@
../../LICENSE-GPL

View File

@@ -0,0 +1,165 @@
mod claude;
mod gemini;
mod settings;
mod stdio_agent_server;
#[cfg(test)]
mod e2e_tests;
pub use claude::*;
pub use gemini::*;
pub use settings::*;
pub use stdio_agent_server::*;
use acp_thread::AcpThread;
use anyhow::Result;
use collections::HashMap;
use gpui::{App, AsyncApp, Entity, SharedString, Task};
use project::Project;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::ResultExt as _;
pub fn init(cx: &mut App) {
settings::init(cx);
}
pub trait AgentServer: Send {
fn logo(&self) -> ui::IconName;
fn name(&self) -> &'static str;
fn empty_state_headline(&self) -> &'static str;
fn empty_state_message(&self) -> &'static str;
fn supports_always_allow(&self) -> bool;
fn new_thread(
&self,
root_dir: &Path,
project: &Entity<Project>,
cx: &mut App,
) -> Task<Result<Entity<AcpThread>>>;
}
impl std::fmt::Debug for AgentServerCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let filtered_env = self.env.as_ref().map(|env| {
env.iter()
.map(|(k, v)| {
(
k,
if util::redact::should_redact(k) {
"[REDACTED]"
} else {
v
},
)
})
.collect::<Vec<_>>()
});
f.debug_struct("AgentServerCommand")
.field("path", &self.path)
.field("args", &self.args)
.field("env", &filtered_env)
.finish()
}
}
pub enum AgentServerVersion {
Supported,
Unsupported {
error_message: SharedString,
upgrade_message: SharedString,
upgrade_command: String,
},
}
#[derive(Deserialize, Serialize, Clone, PartialEq, Eq, JsonSchema)]
pub struct AgentServerCommand {
#[serde(rename = "command")]
pub path: PathBuf,
#[serde(default)]
pub args: Vec<String>,
pub env: Option<HashMap<String, String>>,
}
impl AgentServerCommand {
pub(crate) async fn resolve(
path_bin_name: &'static str,
extra_args: &[&'static str],
settings: Option<AgentServerSettings>,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> Option<Self> {
if let Some(agent_settings) = settings {
return Some(Self {
path: agent_settings.command.path,
args: agent_settings
.command
.args
.into_iter()
.chain(extra_args.iter().map(|arg| arg.to_string()))
.collect(),
env: agent_settings.command.env,
});
} else {
find_bin_in_path(path_bin_name, project, cx)
.await
.map(|path| Self {
path,
args: extra_args.iter().map(|arg| arg.to_string()).collect(),
env: None,
})
}
}
}
async fn find_bin_in_path(
bin_name: &'static str,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> Option<PathBuf> {
let (env_task, root_dir) = project
.update(cx, |project, cx| {
let worktree = project.visible_worktrees(cx).next();
match worktree {
Some(worktree) => {
let env_task = project.environment().update(cx, |env, cx| {
env.get_worktree_environment(worktree.clone(), cx)
});
let path = worktree.read(cx).abs_path();
(env_task, path)
}
None => {
let path: Arc<Path> = paths::home_dir().as_path().into();
let env_task = project.environment().update(cx, |env, cx| {
env.get_directory_environment(path.clone(), cx)
});
(env_task, path)
}
}
})
.log_err()?;
cx.background_executor()
.spawn(async move {
let which_result = if cfg!(windows) {
which::which(bin_name)
} else {
let env = env_task.await.unwrap_or_default();
let shell_path = env.get("PATH").cloned();
which::which_in(bin_name, shell_path.as_ref(), root_dir.as_ref())
};
if let Err(which::Error::CannotFindBinaryPath) = which_result {
return None;
}
which_result.log_err()
})
.await
}

View File

@@ -0,0 +1,805 @@
mod mcp_server;
mod tools;
use collections::HashMap;
use project::Project;
use settings::SettingsStore;
use smol::process::Child;
use std::cell::RefCell;
use std::fmt::Display;
use std::path::Path;
use std::pin::pin;
use std::rc::Rc;
use uuid::Uuid;
use agentic_coding_protocol::{
self as acp, AnyAgentRequest, AnyAgentResult, Client, ProtocolVersion,
StreamAssistantMessageChunkParams, ToolCallContent, UpdateToolCallParams,
};
use anyhow::{Result, anyhow};
use futures::channel::oneshot;
use futures::future::LocalBoxFuture;
use futures::{AsyncBufReadExt, AsyncWriteExt, SinkExt};
use futures::{
AsyncRead, AsyncWrite, FutureExt, StreamExt,
channel::mpsc::{self, UnboundedReceiver, UnboundedSender},
io::BufReader,
select_biased,
};
use gpui::{App, AppContext, Entity, Task};
use serde::{Deserialize, Serialize};
use util::ResultExt;
use crate::claude::mcp_server::ClaudeMcpServer;
use crate::claude::tools::ClaudeTool;
use crate::{AgentServer, AgentServerCommand, AllAgentServersSettings};
use acp_thread::{AcpClientDelegate, AcpThread, AgentConnection};
#[derive(Clone)]
pub struct ClaudeCode;
impl AgentServer for ClaudeCode {
fn name(&self) -> &'static str {
"Claude Code"
}
fn empty_state_headline(&self) -> &'static str {
self.name()
}
fn empty_state_message(&self) -> &'static str {
""
}
fn logo(&self) -> ui::IconName {
ui::IconName::AiClaude
}
fn supports_always_allow(&self) -> bool {
false
}
fn new_thread(
&self,
root_dir: &Path,
project: &Entity<Project>,
cx: &mut App,
) -> Task<Result<Entity<AcpThread>>> {
let project = project.clone();
let root_dir = root_dir.to_path_buf();
let title = self.name().into();
cx.spawn(async move |cx| {
let (mut delegate_tx, delegate_rx) = watch::channel(None);
let tool_id_map = Rc::new(RefCell::new(HashMap::default()));
let mcp_server = ClaudeMcpServer::new(delegate_rx, tool_id_map.clone(), cx).await?;
let mut mcp_servers = HashMap::default();
mcp_servers.insert(
mcp_server::SERVER_NAME.to_string(),
mcp_server.server_config()?,
);
let mcp_config = McpConfig { mcp_servers };
let mcp_config_file = tempfile::NamedTempFile::new()?;
let (mcp_config_file, mcp_config_path) = mcp_config_file.into_parts();
let mut mcp_config_file = smol::fs::File::from(mcp_config_file);
mcp_config_file
.write_all(serde_json::to_string(&mcp_config)?.as_bytes())
.await?;
mcp_config_file.flush().await?;
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings.get::<AllAgentServersSettings>(None).claude.clone()
})?;
let Some(command) =
AgentServerCommand::resolve("claude", &[], settings, &project, cx).await
else {
anyhow::bail!("Failed to find claude binary");
};
let (incoming_message_tx, mut incoming_message_rx) = mpsc::unbounded();
let (outgoing_tx, outgoing_rx) = mpsc::unbounded();
let (cancel_tx, mut cancel_rx) = mpsc::unbounded::<oneshot::Sender<Result<()>>>();
let session_id = Uuid::new_v4();
log::trace!("Starting session with id: {}", session_id);
cx.background_spawn(async move {
let mut outgoing_rx = Some(outgoing_rx);
let mut mode = ClaudeSessionMode::Start;
loop {
let mut child =
spawn_claude(&command, mode, session_id, &mcp_config_path, &root_dir)
.await?;
mode = ClaudeSessionMode::Resume;
let pid = child.id();
log::trace!("Spawned (pid: {})", pid);
let mut io_fut = pin!(
ClaudeAgentConnection::handle_io(
outgoing_rx.take().unwrap(),
incoming_message_tx.clone(),
child.stdin.take().unwrap(),
child.stdout.take().unwrap(),
)
.fuse()
);
select_biased! {
done_tx = cancel_rx.next() => {
if let Some(done_tx) = done_tx {
log::trace!("Interrupted (pid: {})", pid);
let result = send_interrupt(pid as i32);
outgoing_rx.replace(io_fut.await?);
done_tx.send(result).log_err();
continue;
}
}
result = io_fut => {
result?;
}
}
log::trace!("Stopped (pid: {})", pid);
break;
}
drop(mcp_config_path);
anyhow::Ok(())
})
.detach();
cx.new(|cx| {
let end_turn_tx = Rc::new(RefCell::new(None));
let delegate = AcpClientDelegate::new(cx.entity().downgrade(), cx.to_async());
delegate_tx.send(Some(delegate.clone())).log_err();
let handler_task = cx.foreground_executor().spawn({
let end_turn_tx = end_turn_tx.clone();
let tool_id_map = tool_id_map.clone();
let delegate = delegate.clone();
async move {
while let Some(message) = incoming_message_rx.next().await {
ClaudeAgentConnection::handle_message(
delegate.clone(),
message,
end_turn_tx.clone(),
tool_id_map.clone(),
)
.await
}
}
});
let mut connection = ClaudeAgentConnection {
delegate,
outgoing_tx,
end_turn_tx,
cancel_tx,
session_id,
_handler_task: handler_task,
_mcp_server: None,
};
connection._mcp_server = Some(mcp_server);
acp_thread::AcpThread::new(connection, title, None, project.clone(), cx)
})
})
}
}
#[cfg(unix)]
fn send_interrupt(pid: libc::pid_t) -> anyhow::Result<()> {
let pid = nix::unistd::Pid::from_raw(pid);
nix::sys::signal::kill(pid, nix::sys::signal::SIGINT)
.map_err(|e| anyhow!("Failed to interrupt process: {}", e))
}
#[cfg(windows)]
fn send_interrupt(_pid: i32) -> anyhow::Result<()> {
panic!("Cancel not implemented on Windows")
}
impl AgentConnection for ClaudeAgentConnection {
/// Send a request to the agent and wait for a response.
fn request_any(
&self,
params: AnyAgentRequest,
) -> LocalBoxFuture<'static, Result<acp::AnyAgentResult>> {
let delegate = self.delegate.clone();
let end_turn_tx = self.end_turn_tx.clone();
let outgoing_tx = self.outgoing_tx.clone();
let mut cancel_tx = self.cancel_tx.clone();
let session_id = self.session_id;
async move {
match params {
// todo: consider sending an empty request so we get the init response?
AnyAgentRequest::InitializeParams(_) => Ok(AnyAgentResult::InitializeResponse(
acp::InitializeResponse {
is_authenticated: true,
protocol_version: ProtocolVersion::latest(),
},
)),
AnyAgentRequest::AuthenticateParams(_) => {
Err(anyhow!("Authentication not supported"))
}
AnyAgentRequest::SendUserMessageParams(message) => {
delegate.clear_completed_plan_entries().await?;
let (tx, rx) = oneshot::channel();
end_turn_tx.borrow_mut().replace(tx);
let mut content = String::new();
for chunk in message.chunks {
match chunk {
agentic_coding_protocol::UserMessageChunk::Text { text } => {
content.push_str(&text)
}
agentic_coding_protocol::UserMessageChunk::Path { path } => {
content.push_str(&format!("@{path:?}"))
}
}
}
outgoing_tx.unbounded_send(SdkMessage::User {
message: Message {
role: Role::User,
content: Content::UntaggedText(content),
id: None,
model: None,
stop_reason: None,
stop_sequence: None,
usage: None,
},
session_id: Some(session_id),
})?;
rx.await??;
Ok(AnyAgentResult::SendUserMessageResponse(
acp::SendUserMessageResponse,
))
}
AnyAgentRequest::CancelSendMessageParams(_) => {
let (done_tx, done_rx) = oneshot::channel();
cancel_tx.send(done_tx).await?;
done_rx.await??;
Ok(AnyAgentResult::CancelSendMessageResponse(
acp::CancelSendMessageResponse,
))
}
}
}
.boxed_local()
}
}
#[derive(Clone, Copy)]
enum ClaudeSessionMode {
Start,
Resume,
}
async fn spawn_claude(
command: &AgentServerCommand,
mode: ClaudeSessionMode,
session_id: Uuid,
mcp_config_path: &Path,
root_dir: &Path,
) -> Result<Child> {
let child = util::command::new_smol_command(&command.path)
.args([
"--input-format",
"stream-json",
"--output-format",
"stream-json",
"--print",
"--verbose",
"--mcp-config",
mcp_config_path.to_string_lossy().as_ref(),
"--permission-prompt-tool",
&format!(
"mcp__{}__{}",
mcp_server::SERVER_NAME,
mcp_server::PERMISSION_TOOL
),
"--allowedTools",
"mcp__zed__Read,mcp__zed__Edit",
"--disallowedTools",
"Read,Edit",
])
.args(match mode {
ClaudeSessionMode::Start => ["--session-id".to_string(), session_id.to_string()],
ClaudeSessionMode::Resume => ["--resume".to_string(), session_id.to_string()],
})
.args(command.args.iter().map(|arg| arg.as_str()))
.current_dir(root_dir)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.kill_on_drop(true)
.spawn()?;
Ok(child)
}
struct ClaudeAgentConnection {
delegate: AcpClientDelegate,
session_id: Uuid,
outgoing_tx: UnboundedSender<SdkMessage>,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<()>>>>>,
cancel_tx: UnboundedSender<oneshot::Sender<Result<()>>>,
_mcp_server: Option<ClaudeMcpServer>,
_handler_task: Task<()>,
}
impl ClaudeAgentConnection {
async fn handle_message(
delegate: AcpClientDelegate,
message: SdkMessage,
end_turn_tx: Rc<RefCell<Option<oneshot::Sender<Result<()>>>>>,
tool_id_map: Rc<RefCell<HashMap<String, acp::ToolCallId>>>,
) {
match message {
SdkMessage::Assistant { message, .. } | SdkMessage::User { message, .. } => {
for chunk in message.content.chunks() {
match chunk {
ContentChunk::Text { text } | ContentChunk::UntaggedText(text) => {
delegate
.stream_assistant_message_chunk(StreamAssistantMessageChunkParams {
chunk: acp::AssistantMessageChunk::Text { text },
})
.await
.log_err();
}
ContentChunk::ToolUse { id, name, input } => {
let claude_tool = ClaudeTool::infer(&name, input);
if let ClaudeTool::TodoWrite(Some(params)) = claude_tool {
delegate
.update_plan(acp::UpdatePlanParams {
entries: params.todos.into_iter().map(Into::into).collect(),
})
.await
.log_err();
} else if let Some(resp) = delegate
.push_tool_call(claude_tool.as_acp())
.await
.log_err()
{
tool_id_map.borrow_mut().insert(id, resp.id);
}
}
ContentChunk::ToolResult {
content,
tool_use_id,
} => {
let id = tool_id_map.borrow_mut().remove(&tool_use_id);
if let Some(id) = id {
let content = content.to_string();
delegate
.update_tool_call(UpdateToolCallParams {
tool_call_id: id,
status: acp::ToolCallStatus::Finished,
// Don't unset existing content
content: (!content.is_empty()).then_some(
ToolCallContent::Markdown {
// For now we only include text content
markdown: content,
},
),
})
.await
.log_err();
}
}
ContentChunk::Image
| ContentChunk::Document
| ContentChunk::Thinking
| ContentChunk::RedactedThinking
| ContentChunk::WebSearchToolResult => {
delegate
.stream_assistant_message_chunk(StreamAssistantMessageChunkParams {
chunk: acp::AssistantMessageChunk::Text {
text: format!("Unsupported content: {:?}", chunk),
},
})
.await
.log_err();
}
}
}
}
SdkMessage::Result {
is_error, subtype, ..
} => {
if let Some(end_turn_tx) = end_turn_tx.borrow_mut().take() {
if is_error {
end_turn_tx.send(Err(anyhow!("Error: {subtype}"))).ok();
} else {
end_turn_tx.send(Ok(())).ok();
}
}
}
SdkMessage::System { .. } => {}
}
}
async fn handle_io(
mut outgoing_rx: UnboundedReceiver<SdkMessage>,
incoming_tx: UnboundedSender<SdkMessage>,
mut outgoing_bytes: impl Unpin + AsyncWrite,
incoming_bytes: impl Unpin + AsyncRead,
) -> Result<UnboundedReceiver<SdkMessage>> {
let mut output_reader = BufReader::new(incoming_bytes);
let mut outgoing_line = Vec::new();
let mut incoming_line = String::new();
loop {
select_biased! {
message = outgoing_rx.next() => {
if let Some(message) = message {
outgoing_line.clear();
serde_json::to_writer(&mut outgoing_line, &message)?;
log::trace!("send: {}", String::from_utf8_lossy(&outgoing_line));
outgoing_line.push(b'\n');
outgoing_bytes.write_all(&outgoing_line).await.ok();
} else {
break;
}
}
bytes_read = output_reader.read_line(&mut incoming_line).fuse() => {
if bytes_read? == 0 {
break
}
log::trace!("recv: {}", &incoming_line);
match serde_json::from_str::<SdkMessage>(&incoming_line) {
Ok(message) => {
incoming_tx.unbounded_send(message).log_err();
}
Err(error) => {
log::error!("failed to parse incoming message: {error}. Raw: {incoming_line}");
}
}
incoming_line.clear();
}
}
}
Ok(outgoing_rx)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Message {
role: Role,
content: Content,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
stop_reason: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
stop_sequence: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
usage: Option<Usage>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
enum Content {
UntaggedText(String),
Chunks(Vec<ContentChunk>),
}
impl Content {
pub fn chunks(self) -> impl Iterator<Item = ContentChunk> {
match self {
Self::Chunks(chunks) => chunks.into_iter(),
Self::UntaggedText(text) => vec![ContentChunk::Text { text: text.clone() }].into_iter(),
}
}
}
impl Display for Content {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Content::UntaggedText(txt) => write!(f, "{}", txt),
Content::Chunks(chunks) => {
for chunk in chunks {
write!(f, "{}", chunk)?;
}
Ok(())
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum ContentChunk {
Text {
text: String,
},
ToolUse {
id: String,
name: String,
input: serde_json::Value,
},
ToolResult {
content: Content,
tool_use_id: String,
},
// TODO
Image,
Document,
Thinking,
RedactedThinking,
WebSearchToolResult,
#[serde(untagged)]
UntaggedText(String),
}
impl Display for ContentChunk {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ContentChunk::Text { text } => write!(f, "{}", text),
ContentChunk::UntaggedText(text) => write!(f, "{}", text),
ContentChunk::ToolResult { content, .. } => write!(f, "{}", content),
ContentChunk::Image
| ContentChunk::Document
| ContentChunk::Thinking
| ContentChunk::RedactedThinking
| ContentChunk::ToolUse { .. }
| ContentChunk::WebSearchToolResult => {
write!(f, "\n{:?}\n", &self)
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Usage {
input_tokens: u32,
cache_creation_input_tokens: u32,
cache_read_input_tokens: u32,
output_tokens: u32,
service_tier: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum Role {
System,
Assistant,
User,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct MessageParam {
role: Role,
content: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
enum SdkMessage {
// An assistant message
Assistant {
message: Message, // from Anthropic SDK
#[serde(skip_serializing_if = "Option::is_none")]
session_id: Option<Uuid>,
},
// A user message
User {
message: Message, // from Anthropic SDK
#[serde(skip_serializing_if = "Option::is_none")]
session_id: Option<Uuid>,
},
// Emitted as the last message in a conversation
Result {
subtype: ResultErrorType,
duration_ms: f64,
duration_api_ms: f64,
is_error: bool,
num_turns: i32,
#[serde(skip_serializing_if = "Option::is_none")]
result: Option<String>,
session_id: String,
total_cost_usd: f64,
},
// Emitted as the first message at the start of a conversation
System {
cwd: String,
session_id: String,
tools: Vec<String>,
model: String,
mcp_servers: Vec<McpServer>,
#[serde(rename = "apiKeySource")]
api_key_source: String,
#[serde(rename = "permissionMode")]
permission_mode: PermissionMode,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum ResultErrorType {
Success,
ErrorMaxTurns,
ErrorDuringExecution,
}
impl Display for ResultErrorType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ResultErrorType::Success => write!(f, "success"),
ResultErrorType::ErrorMaxTurns => write!(f, "error_max_turns"),
ResultErrorType::ErrorDuringExecution => write!(f, "error_during_execution"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
struct McpServer {
name: String,
status: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
enum PermissionMode {
Default,
AcceptEdits,
BypassPermissions,
Plan,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct McpConfig {
mcp_servers: HashMap<String, McpServerConfig>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct McpServerConfig {
command: String,
args: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
env: Option<HashMap<String, String>>,
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use serde_json::json;
crate::common_e2e_tests!(ClaudeCode);
pub fn local_command() -> AgentServerCommand {
AgentServerCommand {
path: "claude".into(),
args: vec![],
env: None,
}
}
#[test]
fn test_deserialize_content_untagged_text() {
let json = json!("Hello, world!");
let content: Content = serde_json::from_value(json).unwrap();
match content {
Content::UntaggedText(text) => assert_eq!(text, "Hello, world!"),
_ => panic!("Expected UntaggedText variant"),
}
}
#[test]
fn test_deserialize_content_chunks() {
let json = json!([
{
"type": "text",
"text": "Hello"
},
{
"type": "tool_use",
"id": "tool_123",
"name": "calculator",
"input": {"operation": "add", "a": 1, "b": 2}
}
]);
let content: Content = serde_json::from_value(json).unwrap();
match content {
Content::Chunks(chunks) => {
assert_eq!(chunks.len(), 2);
match &chunks[0] {
ContentChunk::Text { text } => assert_eq!(text, "Hello"),
_ => panic!("Expected Text chunk"),
}
match &chunks[1] {
ContentChunk::ToolUse { id, name, input } => {
assert_eq!(id, "tool_123");
assert_eq!(name, "calculator");
assert_eq!(input["operation"], "add");
assert_eq!(input["a"], 1);
assert_eq!(input["b"], 2);
}
_ => panic!("Expected ToolUse chunk"),
}
}
_ => panic!("Expected Chunks variant"),
}
}
#[test]
fn test_deserialize_tool_result_untagged_text() {
let json = json!({
"type": "tool_result",
"content": "Result content",
"tool_use_id": "tool_456"
});
let chunk: ContentChunk = serde_json::from_value(json).unwrap();
match chunk {
ContentChunk::ToolResult {
content,
tool_use_id,
} => {
match content {
Content::UntaggedText(text) => assert_eq!(text, "Result content"),
_ => panic!("Expected UntaggedText content"),
}
assert_eq!(tool_use_id, "tool_456");
}
_ => panic!("Expected ToolResult variant"),
}
}
#[test]
fn test_deserialize_tool_result_chunks() {
let json = json!({
"type": "tool_result",
"content": [
{
"type": "text",
"text": "Processing complete"
},
{
"type": "text",
"text": "Result: 42"
}
],
"tool_use_id": "tool_789"
});
let chunk: ContentChunk = serde_json::from_value(json).unwrap();
match chunk {
ContentChunk::ToolResult {
content,
tool_use_id,
} => {
match content {
Content::Chunks(chunks) => {
assert_eq!(chunks.len(), 2);
match &chunks[0] {
ContentChunk::Text { text } => assert_eq!(text, "Processing complete"),
_ => panic!("Expected Text chunk"),
}
match &chunks[1] {
ContentChunk::Text { text } => assert_eq!(text, "Result: 42"),
_ => panic!("Expected Text chunk"),
}
}
_ => panic!("Expected Chunks content"),
}
assert_eq!(tool_use_id, "tool_789");
}
_ => panic!("Expected ToolResult variant"),
}
}
}

View File

@@ -0,0 +1,296 @@
use std::{cell::RefCell, rc::Rc};
use acp_thread::AcpClientDelegate;
use agentic_coding_protocol::{self as acp, Client, ReadTextFileParams, WriteTextFileParams};
use anyhow::{Context, Result};
use collections::HashMap;
use context_server::{
listener::McpServer,
types::{
CallToolParams, CallToolResponse, Implementation, InitializeParams, InitializeResponse,
ListToolsResponse, ProtocolVersion, ServerCapabilities, Tool, ToolAnnotations,
ToolResponseContent, ToolsCapabilities, requests,
},
};
use gpui::{App, AsyncApp, Task};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use util::debug_panic;
use crate::claude::{
McpServerConfig,
tools::{ClaudeTool, EditToolParams, ReadToolParams},
};
pub struct ClaudeMcpServer {
server: McpServer,
}
pub const SERVER_NAME: &str = "zed";
pub const READ_TOOL: &str = "Read";
pub const EDIT_TOOL: &str = "Edit";
pub const PERMISSION_TOOL: &str = "Confirmation";
#[derive(Deserialize, JsonSchema, Debug)]
struct PermissionToolParams {
tool_name: String,
input: serde_json::Value,
tool_use_id: Option<String>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct PermissionToolResponse {
behavior: PermissionToolBehavior,
updated_input: serde_json::Value,
}
#[derive(Serialize)]
#[serde(rename_all = "snake_case")]
enum PermissionToolBehavior {
Allow,
Deny,
}
impl ClaudeMcpServer {
pub async fn new(
delegate: watch::Receiver<Option<AcpClientDelegate>>,
tool_id_map: Rc<RefCell<HashMap<String, acp::ToolCallId>>>,
cx: &AsyncApp,
) -> Result<Self> {
let mut mcp_server = McpServer::new(cx).await?;
mcp_server.handle_request::<requests::Initialize>(Self::handle_initialize);
mcp_server.handle_request::<requests::ListTools>(Self::handle_list_tools);
mcp_server.handle_request::<requests::CallTool>(move |request, cx| {
Self::handle_call_tool(request, delegate.clone(), tool_id_map.clone(), cx)
});
Ok(Self { server: mcp_server })
}
pub fn server_config(&self) -> Result<McpServerConfig> {
let zed_path = std::env::current_exe()
.context("finding current executable path for use in mcp_server")?
.to_string_lossy()
.to_string();
Ok(McpServerConfig {
command: zed_path,
args: vec![
"--nc".into(),
self.server.socket_path().display().to_string(),
],
env: None,
})
}
fn handle_initialize(_: InitializeParams, cx: &App) -> Task<Result<InitializeResponse>> {
cx.foreground_executor().spawn(async move {
Ok(InitializeResponse {
protocol_version: ProtocolVersion("2025-06-18".into()),
capabilities: ServerCapabilities {
experimental: None,
logging: None,
completions: None,
prompts: None,
resources: None,
tools: Some(ToolsCapabilities {
list_changed: Some(false),
}),
},
server_info: Implementation {
name: SERVER_NAME.into(),
version: "0.1.0".into(),
},
meta: None,
})
})
}
fn handle_list_tools(_: (), cx: &App) -> Task<Result<ListToolsResponse>> {
cx.foreground_executor().spawn(async move {
Ok(ListToolsResponse {
tools: vec![
Tool {
name: PERMISSION_TOOL.into(),
input_schema: schemars::schema_for!(PermissionToolParams).into(),
description: None,
annotations: None,
},
Tool {
name: READ_TOOL.into(),
input_schema: schemars::schema_for!(ReadToolParams).into(),
description: Some("Read the contents of a file. In sessions with mcp__zed__Read always use it instead of Read as it contains the most up-to-date contents.".to_string()),
annotations: Some(ToolAnnotations {
title: Some("Read file".to_string()),
read_only_hint: Some(true),
destructive_hint: Some(false),
open_world_hint: Some(false),
// if time passes the contents might change, but it's not going to do anything different
// true or false seem too strong, let's try a none.
idempotent_hint: None,
}),
},
Tool {
name: EDIT_TOOL.into(),
input_schema: schemars::schema_for!(EditToolParams).into(),
description: Some("Edits a file. In sessions with mcp__zed__Edit always use it instead of Edit as it will show the diff to the user better.".to_string()),
annotations: Some(ToolAnnotations {
title: Some("Edit file".to_string()),
read_only_hint: Some(false),
destructive_hint: Some(false),
open_world_hint: Some(false),
idempotent_hint: Some(false),
}),
},
],
next_cursor: None,
meta: None,
})
})
}
fn handle_call_tool(
request: CallToolParams,
mut delegate_watch: watch::Receiver<Option<AcpClientDelegate>>,
tool_id_map: Rc<RefCell<HashMap<String, acp::ToolCallId>>>,
cx: &App,
) -> Task<Result<CallToolResponse>> {
cx.spawn(async move |cx| {
let Some(delegate) = delegate_watch.recv().await? else {
debug_panic!("Sent None delegate");
anyhow::bail!("Server not available");
};
if request.name.as_str() == PERMISSION_TOOL {
let input =
serde_json::from_value(request.arguments.context("Arguments required")?)?;
let result =
Self::handle_permissions_tool_call(input, delegate, tool_id_map, cx).await?;
Ok(CallToolResponse {
content: vec![ToolResponseContent::Text {
text: serde_json::to_string(&result)?,
}],
is_error: None,
meta: None,
})
} else if request.name.as_str() == READ_TOOL {
let input =
serde_json::from_value(request.arguments.context("Arguments required")?)?;
let content = Self::handle_read_tool_call(input, delegate, cx).await?;
Ok(CallToolResponse {
content,
is_error: None,
meta: None,
})
} else if request.name.as_str() == EDIT_TOOL {
let input =
serde_json::from_value(request.arguments.context("Arguments required")?)?;
Self::handle_edit_tool_call(input, delegate, cx).await?;
Ok(CallToolResponse {
content: vec![],
is_error: None,
meta: None,
})
} else {
anyhow::bail!("Unsupported tool");
}
})
}
fn handle_read_tool_call(
params: ReadToolParams,
delegate: AcpClientDelegate,
cx: &AsyncApp,
) -> Task<Result<Vec<ToolResponseContent>>> {
cx.foreground_executor().spawn(async move {
let response = delegate
.read_text_file(ReadTextFileParams {
path: params.abs_path,
line: params.offset,
limit: params.limit,
})
.await?;
Ok(vec![ToolResponseContent::Text {
text: response.content,
}])
})
}
fn handle_edit_tool_call(
params: EditToolParams,
delegate: AcpClientDelegate,
cx: &AsyncApp,
) -> Task<Result<()>> {
cx.foreground_executor().spawn(async move {
let response = delegate
.read_text_file_reusing_snapshot(ReadTextFileParams {
path: params.abs_path.clone(),
line: None,
limit: None,
})
.await?;
let new_content = response.content.replace(&params.old_text, &params.new_text);
if new_content == response.content {
return Err(anyhow::anyhow!("The old_text was not found in the content"));
}
delegate
.write_text_file(WriteTextFileParams {
path: params.abs_path,
content: new_content,
})
.await?;
Ok(())
})
}
fn handle_permissions_tool_call(
params: PermissionToolParams,
delegate: AcpClientDelegate,
tool_id_map: Rc<RefCell<HashMap<String, acp::ToolCallId>>>,
cx: &AsyncApp,
) -> Task<Result<PermissionToolResponse>> {
cx.foreground_executor().spawn(async move {
let claude_tool = ClaudeTool::infer(&params.tool_name, params.input.clone());
let tool_call_id = match params.tool_use_id {
Some(tool_use_id) => tool_id_map
.borrow()
.get(&tool_use_id)
.cloned()
.context("Tool call ID not found")?,
None => delegate.push_tool_call(claude_tool.as_acp()).await?.id,
};
let outcome = delegate
.request_existing_tool_call_confirmation(
tool_call_id,
claude_tool.confirmation(None),
)
.await?;
match outcome {
acp::ToolCallConfirmationOutcome::Allow
| acp::ToolCallConfirmationOutcome::AlwaysAllow
| acp::ToolCallConfirmationOutcome::AlwaysAllowMcpServer
| acp::ToolCallConfirmationOutcome::AlwaysAllowTool => Ok(PermissionToolResponse {
behavior: PermissionToolBehavior::Allow,
updated_input: params.input,
}),
acp::ToolCallConfirmationOutcome::Reject
| acp::ToolCallConfirmationOutcome::Cancel => Ok(PermissionToolResponse {
behavior: PermissionToolBehavior::Deny,
updated_input: params.input,
}),
}
})
}
}

View File

@@ -0,0 +1,783 @@
use std::path::PathBuf;
use agentic_coding_protocol::{self as acp, PushToolCallParams, ToolCallLocation};
use itertools::Itertools;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use util::ResultExt;
pub enum ClaudeTool {
Task(Option<TaskToolParams>),
NotebookRead(Option<NotebookReadToolParams>),
NotebookEdit(Option<NotebookEditToolParams>),
Edit(Option<EditToolParams>),
MultiEdit(Option<MultiEditToolParams>),
ReadFile(Option<ReadToolParams>),
Write(Option<WriteToolParams>),
Ls(Option<LsToolParams>),
Glob(Option<GlobToolParams>),
Grep(Option<GrepToolParams>),
Terminal(Option<BashToolParams>),
WebFetch(Option<WebFetchToolParams>),
WebSearch(Option<WebSearchToolParams>),
TodoWrite(Option<TodoWriteToolParams>),
ExitPlanMode(Option<ExitPlanModeToolParams>),
Other {
name: String,
input: serde_json::Value,
},
}
impl ClaudeTool {
pub fn infer(tool_name: &str, input: serde_json::Value) -> Self {
match tool_name {
// Known tools
"mcp__zed__Read" => Self::ReadFile(serde_json::from_value(input).log_err()),
"mcp__zed__Edit" => Self::Edit(serde_json::from_value(input).log_err()),
"MultiEdit" => Self::MultiEdit(serde_json::from_value(input).log_err()),
"Write" => Self::Write(serde_json::from_value(input).log_err()),
"LS" => Self::Ls(serde_json::from_value(input).log_err()),
"Glob" => Self::Glob(serde_json::from_value(input).log_err()),
"Grep" => Self::Grep(serde_json::from_value(input).log_err()),
"Bash" => Self::Terminal(serde_json::from_value(input).log_err()),
"WebFetch" => Self::WebFetch(serde_json::from_value(input).log_err()),
"WebSearch" => Self::WebSearch(serde_json::from_value(input).log_err()),
"TodoWrite" => Self::TodoWrite(serde_json::from_value(input).log_err()),
"exit_plan_mode" => Self::ExitPlanMode(serde_json::from_value(input).log_err()),
"Task" => Self::Task(serde_json::from_value(input).log_err()),
"NotebookRead" => Self::NotebookRead(serde_json::from_value(input).log_err()),
"NotebookEdit" => Self::NotebookEdit(serde_json::from_value(input).log_err()),
// Inferred from name
_ => {
let tool_name = tool_name.to_lowercase();
if tool_name.contains("edit") || tool_name.contains("write") {
Self::Edit(None)
} else if tool_name.contains("terminal") {
Self::Terminal(None)
} else {
Self::Other {
name: tool_name.to_string(),
input,
}
}
}
}
}
pub fn label(&self) -> String {
match &self {
Self::Task(Some(params)) => params.description.clone(),
Self::Task(None) => "Task".into(),
Self::NotebookRead(Some(params)) => {
format!("Read Notebook {}", params.notebook_path.display())
}
Self::NotebookRead(None) => "Read Notebook".into(),
Self::NotebookEdit(Some(params)) => {
format!("Edit Notebook {}", params.notebook_path.display())
}
Self::NotebookEdit(None) => "Edit Notebook".into(),
Self::Terminal(Some(params)) => format!("`{}`", params.command),
Self::Terminal(None) => "Terminal".into(),
Self::ReadFile(_) => "Read File".into(),
Self::Ls(Some(params)) => {
format!("List Directory {}", params.path.display())
}
Self::Ls(None) => "List Directory".into(),
Self::Edit(Some(params)) => {
format!("Edit {}", params.abs_path.display())
}
Self::Edit(None) => "Edit".into(),
Self::MultiEdit(Some(params)) => {
format!("Multi Edit {}", params.file_path.display())
}
Self::MultiEdit(None) => "Multi Edit".into(),
Self::Write(Some(params)) => {
format!("Write {}", params.file_path.display())
}
Self::Write(None) => "Write".into(),
Self::Glob(Some(params)) => {
format!("Glob `{params}`")
}
Self::Glob(None) => "Glob".into(),
Self::Grep(Some(params)) => format!("`{params}`"),
Self::Grep(None) => "Grep".into(),
Self::WebFetch(Some(params)) => format!("Fetch {}", params.url),
Self::WebFetch(None) => "Fetch".into(),
Self::WebSearch(Some(params)) => format!("Web Search: {}", params),
Self::WebSearch(None) => "Web Search".into(),
Self::TodoWrite(Some(params)) => format!(
"Update TODOs: {}",
params.todos.iter().map(|todo| &todo.content).join(", ")
),
Self::TodoWrite(None) => "Update TODOs".into(),
Self::ExitPlanMode(_) => "Exit Plan Mode".into(),
Self::Other { name, .. } => name.clone(),
}
}
pub fn content(&self) -> Option<acp::ToolCallContent> {
match &self {
Self::Other { input, .. } => Some(acp::ToolCallContent::Markdown {
markdown: format!(
"```json\n{}```",
serde_json::to_string_pretty(&input).unwrap_or("{}".to_string())
),
}),
Self::Task(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.prompt.clone(),
}),
Self::NotebookRead(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.notebook_path.display().to_string(),
}),
Self::NotebookEdit(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.new_source.clone(),
}),
Self::Terminal(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: format!(
"`{}`\n\n{}",
params.command,
params.description.as_deref().unwrap_or_default()
),
}),
Self::ReadFile(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.abs_path.display().to_string(),
}),
Self::Ls(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.path.display().to_string(),
}),
Self::Glob(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.to_string(),
}),
Self::Grep(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: format!("`{params}`"),
}),
Self::WebFetch(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.prompt.clone(),
}),
Self::WebSearch(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.to_string(),
}),
Self::TodoWrite(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params
.todos
.iter()
.map(|todo| {
format!(
"- {} {}: {}",
match todo.status {
TodoStatus::Completed => "",
TodoStatus::InProgress => "🚧",
TodoStatus::Pending => "",
},
todo.priority,
todo.content
)
})
.join("\n"),
}),
Self::ExitPlanMode(Some(params)) => Some(acp::ToolCallContent::Markdown {
markdown: params.plan.clone(),
}),
Self::Edit(Some(params)) => Some(acp::ToolCallContent::Diff {
diff: acp::Diff {
path: params.abs_path.clone(),
old_text: Some(params.old_text.clone()),
new_text: params.new_text.clone(),
},
}),
Self::Write(Some(params)) => Some(acp::ToolCallContent::Diff {
diff: acp::Diff {
path: params.file_path.clone(),
old_text: None,
new_text: params.content.clone(),
},
}),
Self::MultiEdit(Some(params)) => {
// todo: show multiple edits in a multibuffer?
params.edits.first().map(|edit| acp::ToolCallContent::Diff {
diff: acp::Diff {
path: params.file_path.clone(),
old_text: Some(edit.old_string.clone()),
new_text: edit.new_string.clone(),
},
})
}
Self::Task(None)
| Self::NotebookRead(None)
| Self::NotebookEdit(None)
| Self::Terminal(None)
| Self::ReadFile(None)
| Self::Ls(None)
| Self::Glob(None)
| Self::Grep(None)
| Self::WebFetch(None)
| Self::WebSearch(None)
| Self::TodoWrite(None)
| Self::ExitPlanMode(None)
| Self::Edit(None)
| Self::Write(None)
| Self::MultiEdit(None) => None,
}
}
pub fn icon(&self) -> acp::Icon {
match self {
Self::Task(_) => acp::Icon::Hammer,
Self::NotebookRead(_) => acp::Icon::FileSearch,
Self::NotebookEdit(_) => acp::Icon::Pencil,
Self::Edit(_) => acp::Icon::Pencil,
Self::MultiEdit(_) => acp::Icon::Pencil,
Self::Write(_) => acp::Icon::Pencil,
Self::ReadFile(_) => acp::Icon::FileSearch,
Self::Ls(_) => acp::Icon::Folder,
Self::Glob(_) => acp::Icon::FileSearch,
Self::Grep(_) => acp::Icon::Regex,
Self::Terminal(_) => acp::Icon::Terminal,
Self::WebSearch(_) => acp::Icon::Globe,
Self::WebFetch(_) => acp::Icon::Globe,
Self::TodoWrite(_) => acp::Icon::LightBulb,
Self::ExitPlanMode(_) => acp::Icon::Hammer,
Self::Other { .. } => acp::Icon::Hammer,
}
}
pub fn confirmation(&self, description: Option<String>) -> acp::ToolCallConfirmation {
match &self {
Self::Edit(_) | Self::Write(_) | Self::NotebookEdit(_) | Self::MultiEdit(_) => {
acp::ToolCallConfirmation::Edit { description }
}
Self::WebFetch(params) => acp::ToolCallConfirmation::Fetch {
urls: params
.as_ref()
.map(|p| vec![p.url.clone()])
.unwrap_or_default(),
description,
},
Self::Terminal(Some(BashToolParams {
description,
command,
..
})) => acp::ToolCallConfirmation::Execute {
command: command.clone(),
root_command: command.clone(),
description: description.clone(),
},
Self::ExitPlanMode(Some(params)) => acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {}", params.plan)
} else {
params.plan.clone()
},
},
Self::Task(Some(params)) => acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {}", params.description)
} else {
params.description.clone()
},
},
Self::Ls(Some(LsToolParams { path, .. }))
| Self::ReadFile(Some(ReadToolParams { abs_path: path, .. })) => {
let path = path.display();
acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {path}")
} else {
path.to_string()
},
}
}
Self::NotebookRead(Some(NotebookReadToolParams { notebook_path, .. })) => {
let path = notebook_path.display();
acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {path}")
} else {
path.to_string()
},
}
}
Self::Glob(Some(params)) => acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {params}")
} else {
params.to_string()
},
},
Self::Grep(Some(params)) => acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {params}")
} else {
params.to_string()
},
},
Self::WebSearch(Some(params)) => acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {params}")
} else {
params.to_string()
},
},
Self::TodoWrite(Some(params)) => {
let params = params.todos.iter().map(|todo| &todo.content).join(", ");
acp::ToolCallConfirmation::Other {
description: if let Some(description) = description {
format!("{description} {params}")
} else {
params
},
}
}
Self::Terminal(None)
| Self::Task(None)
| Self::NotebookRead(None)
| Self::ExitPlanMode(None)
| Self::Ls(None)
| Self::Glob(None)
| Self::Grep(None)
| Self::ReadFile(None)
| Self::WebSearch(None)
| Self::TodoWrite(None)
| Self::Other { .. } => acp::ToolCallConfirmation::Other {
description: description.unwrap_or("".to_string()),
},
}
}
pub fn locations(&self) -> Vec<acp::ToolCallLocation> {
match &self {
Self::Edit(Some(EditToolParams { abs_path, .. })) => vec![ToolCallLocation {
path: abs_path.clone(),
line: None,
}],
Self::MultiEdit(Some(MultiEditToolParams { file_path, .. })) => {
vec![ToolCallLocation {
path: file_path.clone(),
line: None,
}]
}
Self::Write(Some(WriteToolParams { file_path, .. })) => vec![ToolCallLocation {
path: file_path.clone(),
line: None,
}],
Self::ReadFile(Some(ReadToolParams {
abs_path, offset, ..
})) => vec![ToolCallLocation {
path: abs_path.clone(),
line: *offset,
}],
Self::NotebookRead(Some(NotebookReadToolParams { notebook_path, .. })) => {
vec![ToolCallLocation {
path: notebook_path.clone(),
line: None,
}]
}
Self::NotebookEdit(Some(NotebookEditToolParams { notebook_path, .. })) => {
vec![ToolCallLocation {
path: notebook_path.clone(),
line: None,
}]
}
Self::Glob(Some(GlobToolParams {
path: Some(path), ..
})) => vec![ToolCallLocation {
path: path.clone(),
line: None,
}],
Self::Ls(Some(LsToolParams { path, .. })) => vec![ToolCallLocation {
path: path.clone(),
line: None,
}],
Self::Grep(Some(GrepToolParams {
path: Some(path), ..
})) => vec![ToolCallLocation {
path: PathBuf::from(path),
line: None,
}],
Self::Task(_)
| Self::NotebookRead(None)
| Self::NotebookEdit(None)
| Self::Edit(None)
| Self::MultiEdit(None)
| Self::Write(None)
| Self::ReadFile(None)
| Self::Ls(None)
| Self::Glob(_)
| Self::Grep(_)
| Self::Terminal(_)
| Self::WebFetch(_)
| Self::WebSearch(_)
| Self::TodoWrite(_)
| Self::ExitPlanMode(_)
| Self::Other { .. } => vec![],
}
}
pub fn as_acp(&self) -> PushToolCallParams {
PushToolCallParams {
label: self.label(),
content: self.content(),
icon: self.icon(),
locations: self.locations(),
}
}
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct EditToolParams {
/// The absolute path to the file to read.
pub abs_path: PathBuf,
/// The old text to replace (must be unique in the file)
pub old_text: String,
/// The new text.
pub new_text: String,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct ReadToolParams {
/// The absolute path to the file to read.
pub abs_path: PathBuf,
/// Which line to start reading from. Omit to start from the beginning.
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<u32>,
/// How many lines to read. Omit for the whole file.
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct WriteToolParams {
/// Absolute path for new file
pub file_path: PathBuf,
/// File content
pub content: String,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct BashToolParams {
/// Shell command to execute
pub command: String,
/// 5-10 word description of what command does
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
/// Timeout in ms (max 600000ms/10min, default 120000ms)
#[serde(skip_serializing_if = "Option::is_none")]
pub timeout: Option<u32>,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct GlobToolParams {
/// Glob pattern like **/*.js or src/**/*.ts
pub pattern: String,
/// Directory to search in (omit for current directory)
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<PathBuf>,
}
impl std::fmt::Display for GlobToolParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if let Some(path) = &self.path {
write!(f, "{}", path.display())?;
}
write!(f, "{}", self.pattern)
}
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct LsToolParams {
/// Absolute path to directory
pub path: PathBuf,
/// Array of glob patterns to ignore
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub ignore: Vec<String>,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct GrepToolParams {
/// Regex pattern to search for
pub pattern: String,
/// File/directory to search (defaults to current directory)
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
/// "content" (shows lines), "files_with_matches" (default), "count"
#[serde(skip_serializing_if = "Option::is_none")]
pub output_mode: Option<GrepOutputMode>,
/// Filter files with glob pattern like "*.js"
#[serde(skip_serializing_if = "Option::is_none")]
pub glob: Option<String>,
/// File type filter like "js", "py", "rust"
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub file_type: Option<String>,
/// Case insensitive search
#[serde(rename = "-i", default, skip_serializing_if = "is_false")]
pub case_insensitive: bool,
/// Show line numbers (content mode only)
#[serde(rename = "-n", default, skip_serializing_if = "is_false")]
pub line_numbers: bool,
/// Lines after match (content mode only)
#[serde(rename = "-A", skip_serializing_if = "Option::is_none")]
pub after_context: Option<u32>,
/// Lines before match (content mode only)
#[serde(rename = "-B", skip_serializing_if = "Option::is_none")]
pub before_context: Option<u32>,
/// Lines before and after match (content mode only)
#[serde(rename = "-C", skip_serializing_if = "Option::is_none")]
pub context: Option<u32>,
/// Enable multiline/cross-line matching
#[serde(default, skip_serializing_if = "is_false")]
pub multiline: bool,
/// Limit output to first N results
#[serde(skip_serializing_if = "Option::is_none")]
pub head_limit: Option<u32>,
}
impl std::fmt::Display for GrepToolParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "grep")?;
// Boolean flags
if self.case_insensitive {
write!(f, " -i")?;
}
if self.line_numbers {
write!(f, " -n")?;
}
// Context options
if let Some(after) = self.after_context {
write!(f, " -A {}", after)?;
}
if let Some(before) = self.before_context {
write!(f, " -B {}", before)?;
}
if let Some(context) = self.context {
write!(f, " -C {}", context)?;
}
// Output mode
if let Some(mode) = &self.output_mode {
match mode {
GrepOutputMode::FilesWithMatches => write!(f, " -l")?,
GrepOutputMode::Count => write!(f, " -c")?,
GrepOutputMode::Content => {} // Default mode
}
}
// Head limit
if let Some(limit) = self.head_limit {
write!(f, " | head -{}", limit)?;
}
// Glob pattern
if let Some(glob) = &self.glob {
write!(f, " --include=\"{}\"", glob)?;
}
// File type
if let Some(file_type) = &self.file_type {
write!(f, " --type={}", file_type)?;
}
// Multiline
if self.multiline {
write!(f, " -P")?; // Perl-compatible regex for multiline
}
// Pattern (escaped if contains special characters)
write!(f, " \"{}\"", self.pattern)?;
// Path
if let Some(path) = &self.path {
write!(f, " {}", path)?;
}
Ok(())
}
}
#[derive(Deserialize, Serialize, JsonSchema, strum::Display, Debug)]
#[serde(rename_all = "snake_case")]
pub enum TodoPriority {
High,
Medium,
Low,
}
impl Into<acp::PlanEntryPriority> for TodoPriority {
fn into(self) -> acp::PlanEntryPriority {
match self {
TodoPriority::High => acp::PlanEntryPriority::High,
TodoPriority::Medium => acp::PlanEntryPriority::Medium,
TodoPriority::Low => acp::PlanEntryPriority::Low,
}
}
}
#[derive(Deserialize, Serialize, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum TodoStatus {
Pending,
InProgress,
Completed,
}
impl Into<acp::PlanEntryStatus> for TodoStatus {
fn into(self) -> acp::PlanEntryStatus {
match self {
TodoStatus::Pending => acp::PlanEntryStatus::Pending,
TodoStatus::InProgress => acp::PlanEntryStatus::InProgress,
TodoStatus::Completed => acp::PlanEntryStatus::Completed,
}
}
}
#[derive(Deserialize, Serialize, JsonSchema, Debug)]
pub struct Todo {
/// Unique identifier
pub id: String,
/// Task description
pub content: String,
/// Priority level of the todo
pub priority: TodoPriority,
/// Current status of the todo
pub status: TodoStatus,
}
impl Into<acp::PlanEntry> for Todo {
fn into(self) -> acp::PlanEntry {
acp::PlanEntry {
content: self.content,
priority: self.priority.into(),
status: self.status.into(),
}
}
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct TodoWriteToolParams {
pub todos: Vec<Todo>,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct ExitPlanModeToolParams {
/// Implementation plan in markdown format
pub plan: String,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct TaskToolParams {
/// Short 3-5 word description of task
pub description: String,
/// Detailed task for agent to perform
pub prompt: String,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct NotebookReadToolParams {
/// Absolute path to .ipynb file
pub notebook_path: PathBuf,
/// Specific cell ID to read
#[serde(skip_serializing_if = "Option::is_none")]
pub cell_id: Option<String>,
}
#[derive(Deserialize, Serialize, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum CellType {
Code,
Markdown,
}
#[derive(Deserialize, Serialize, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum EditMode {
Replace,
Insert,
Delete,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct NotebookEditToolParams {
/// Absolute path to .ipynb file
pub notebook_path: PathBuf,
/// New cell content
pub new_source: String,
/// Cell ID to edit
#[serde(skip_serializing_if = "Option::is_none")]
pub cell_id: Option<String>,
/// Type of cell (code or markdown)
#[serde(skip_serializing_if = "Option::is_none")]
pub cell_type: Option<CellType>,
/// Edit operation mode
#[serde(skip_serializing_if = "Option::is_none")]
pub edit_mode: Option<EditMode>,
}
#[derive(Deserialize, Serialize, JsonSchema, Debug)]
pub struct MultiEditItem {
/// The text to search for and replace
pub old_string: String,
/// The replacement text
pub new_string: String,
/// Whether to replace all occurrences or just the first
#[serde(default, skip_serializing_if = "is_false")]
pub replace_all: bool,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct MultiEditToolParams {
/// Absolute path to file
pub file_path: PathBuf,
/// List of edits to apply
pub edits: Vec<MultiEditItem>,
}
fn is_false(v: &bool) -> bool {
!*v
}
#[derive(Deserialize, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum GrepOutputMode {
Content,
FilesWithMatches,
Count,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct WebFetchToolParams {
/// Valid URL to fetch
#[serde(rename = "url")]
pub url: String,
/// What to extract from content
pub prompt: String,
}
#[derive(Deserialize, JsonSchema, Debug)]
pub struct WebSearchToolParams {
/// Search query (min 2 chars)
pub query: String,
/// Only include these domains
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub allowed_domains: Vec<String>,
/// Exclude these domains
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub blocked_domains: Vec<String>,
}
impl std::fmt::Display for WebSearchToolParams {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "\"{}\"", self.query)?;
if !self.allowed_domains.is_empty() {
write!(f, " (allowed: {})", self.allowed_domains.join(", "))?;
}
if !self.blocked_domains.is_empty() {
write!(f, " (blocked: {})", self.blocked_domains.join(", "))?;
}
Ok(())
}
}

View File

@@ -0,0 +1,412 @@
use std::{path::Path, sync::Arc, time::Duration};
use crate::{AgentServer, AgentServerSettings, AllAgentServersSettings};
use acp_thread::{
AcpThread, AgentThreadEntry, ToolCall, ToolCallConfirmation, ToolCallContent, ToolCallStatus,
};
use agentic_coding_protocol as acp;
use futures::{FutureExt, StreamExt, channel::mpsc, select};
use gpui::{Entity, TestAppContext};
use indoc::indoc;
use project::{FakeFs, Project};
use serde_json::json;
use settings::{Settings, SettingsStore};
use util::path;
pub async fn test_basic(server: impl AgentServer + 'static, cx: &mut TestAppContext) {
let fs = init_test(cx).await;
let project = Project::test(fs, [], cx).await;
let thread = new_test_thread(server, project.clone(), "/private/tmp", cx).await;
thread
.update(cx, |thread, cx| thread.send_raw("Hello from Zed!", cx))
.await
.unwrap();
thread.read_with(cx, |thread, _| {
assert_eq!(thread.entries().len(), 2);
assert!(matches!(
thread.entries()[0],
AgentThreadEntry::UserMessage(_)
));
assert!(matches!(
thread.entries()[1],
AgentThreadEntry::AssistantMessage(_)
));
});
}
pub async fn test_path_mentions(server: impl AgentServer + 'static, cx: &mut TestAppContext) {
let _fs = init_test(cx).await;
let tempdir = tempfile::tempdir().unwrap();
std::fs::write(
tempdir.path().join("foo.rs"),
indoc! {"
fn main() {
println!(\"Hello, world!\");
}
"},
)
.expect("failed to write file");
let project = Project::example([tempdir.path()], &mut cx.to_async()).await;
let thread = new_test_thread(server, project.clone(), tempdir.path(), cx).await;
thread
.update(cx, |thread, cx| {
thread.send(
acp::SendUserMessageParams {
chunks: vec![
acp::UserMessageChunk::Text {
text: "Read the file ".into(),
},
acp::UserMessageChunk::Path {
path: Path::new("foo.rs").into(),
},
acp::UserMessageChunk::Text {
text: " and tell me what the content of the println! is".into(),
},
],
},
cx,
)
})
.await
.unwrap();
thread.read_with(cx, |thread, cx| {
assert_eq!(thread.entries().len(), 3);
assert!(matches!(
thread.entries()[0],
AgentThreadEntry::UserMessage(_)
));
assert!(matches!(thread.entries()[1], AgentThreadEntry::ToolCall(_)));
let AgentThreadEntry::AssistantMessage(assistant_message) = &thread.entries()[2] else {
panic!("Expected AssistantMessage")
};
assert!(
assistant_message.to_markdown(cx).contains("Hello, world!"),
"unexpected assistant message: {:?}",
assistant_message.to_markdown(cx)
);
});
}
pub async fn test_tool_call(server: impl AgentServer + 'static, cx: &mut TestAppContext) {
let fs = init_test(cx).await;
fs.insert_tree(
path!("/private/tmp"),
json!({"foo": "Lorem ipsum dolor", "bar": "bar", "baz": "baz"}),
)
.await;
let project = Project::test(fs, [path!("/private/tmp").as_ref()], cx).await;
let thread = new_test_thread(server, project.clone(), "/private/tmp", cx).await;
thread
.update(cx, |thread, cx| {
thread.send_raw(
"Read the '/private/tmp/foo' file and tell me what you see.",
cx,
)
})
.await
.unwrap();
thread.read_with(cx, |thread, _cx| {
assert!(thread.entries().iter().any(|entry| {
matches!(
entry,
AgentThreadEntry::ToolCall(ToolCall {
status: ToolCallStatus::Allowed { .. },
..
})
)
}));
assert!(
thread
.entries()
.iter()
.any(|entry| { matches!(entry, AgentThreadEntry::AssistantMessage(_)) })
);
});
}
pub async fn test_tool_call_with_confirmation(
server: impl AgentServer + 'static,
cx: &mut TestAppContext,
) {
let fs = init_test(cx).await;
let project = Project::test(fs, [path!("/private/tmp").as_ref()], cx).await;
let thread = new_test_thread(server, project.clone(), "/private/tmp", cx).await;
let full_turn = thread.update(cx, |thread, cx| {
thread.send_raw(
r#"Run `touch hello.txt && echo "Hello, world!" | tee hello.txt`"#,
cx,
)
});
run_until_first_tool_call(
&thread,
|entry| {
matches!(
entry,
AgentThreadEntry::ToolCall(ToolCall {
status: ToolCallStatus::WaitingForConfirmation { .. },
..
})
)
},
cx,
)
.await;
let tool_call_id = thread.read_with(cx, |thread, _cx| {
let AgentThreadEntry::ToolCall(ToolCall {
id,
status:
ToolCallStatus::WaitingForConfirmation {
confirmation: ToolCallConfirmation::Execute { root_command, .. },
..
},
..
}) = &thread
.entries()
.iter()
.find(|entry| matches!(entry, AgentThreadEntry::ToolCall(_)))
.unwrap()
else {
panic!();
};
assert!(root_command.contains("touch"));
*id
});
thread.update(cx, |thread, cx| {
thread.authorize_tool_call(tool_call_id, acp::ToolCallConfirmationOutcome::Allow, cx);
assert!(thread.entries().iter().any(|entry| matches!(
entry,
AgentThreadEntry::ToolCall(ToolCall {
status: ToolCallStatus::Allowed { .. },
..
})
)));
});
full_turn.await.unwrap();
thread.read_with(cx, |thread, cx| {
let AgentThreadEntry::ToolCall(ToolCall {
content: Some(ToolCallContent::Markdown { markdown }),
status: ToolCallStatus::Allowed { .. },
..
}) = thread
.entries()
.iter()
.find(|entry| matches!(entry, AgentThreadEntry::ToolCall(_)))
.unwrap()
else {
panic!();
};
markdown.read_with(cx, |md, _cx| {
assert!(
md.source().contains("Hello"),
r#"Expected '{}' to contain "Hello""#,
md.source()
);
});
});
}
pub async fn test_cancel(server: impl AgentServer + 'static, cx: &mut TestAppContext) {
let fs = init_test(cx).await;
let project = Project::test(fs, [path!("/private/tmp").as_ref()], cx).await;
let thread = new_test_thread(server, project.clone(), "/private/tmp", cx).await;
let full_turn = thread.update(cx, |thread, cx| {
thread.send_raw(
r#"Run `touch hello.txt && echo "Hello, world!" >> hello.txt`"#,
cx,
)
});
let first_tool_call_ix = run_until_first_tool_call(
&thread,
|entry| {
matches!(
entry,
AgentThreadEntry::ToolCall(ToolCall {
status: ToolCallStatus::WaitingForConfirmation { .. },
..
})
)
},
cx,
)
.await;
thread.read_with(cx, |thread, _cx| {
let AgentThreadEntry::ToolCall(ToolCall {
id,
status:
ToolCallStatus::WaitingForConfirmation {
confirmation: ToolCallConfirmation::Execute { root_command, .. },
..
},
..
}) = &thread.entries()[first_tool_call_ix]
else {
panic!("{:?}", thread.entries()[1]);
};
assert!(root_command.contains("touch"));
*id
});
thread
.update(cx, |thread, cx| thread.cancel(cx))
.await
.unwrap();
full_turn.await.unwrap();
thread.read_with(cx, |thread, _| {
let AgentThreadEntry::ToolCall(ToolCall {
status: ToolCallStatus::Canceled,
..
}) = &thread.entries()[first_tool_call_ix]
else {
panic!();
};
});
thread
.update(cx, |thread, cx| {
thread.send_raw(r#"Stop running and say goodbye to me."#, cx)
})
.await
.unwrap();
thread.read_with(cx, |thread, _| {
assert!(matches!(
&thread.entries().last().unwrap(),
AgentThreadEntry::AssistantMessage(..),
))
});
}
#[macro_export]
macro_rules! common_e2e_tests {
($server:expr) => {
mod common_e2e {
use super::*;
#[::gpui::test]
#[cfg_attr(not(feature = "e2e"), ignore)]
async fn basic(cx: &mut ::gpui::TestAppContext) {
$crate::e2e_tests::test_basic($server, cx).await;
}
#[::gpui::test]
#[cfg_attr(not(feature = "e2e"), ignore)]
async fn path_mentions(cx: &mut ::gpui::TestAppContext) {
$crate::e2e_tests::test_path_mentions($server, cx).await;
}
#[::gpui::test]
#[cfg_attr(not(feature = "e2e"), ignore)]
async fn tool_call(cx: &mut ::gpui::TestAppContext) {
$crate::e2e_tests::test_tool_call($server, cx).await;
}
#[::gpui::test]
#[cfg_attr(not(feature = "e2e"), ignore)]
async fn tool_call_with_confirmation(cx: &mut ::gpui::TestAppContext) {
$crate::e2e_tests::test_tool_call_with_confirmation($server, cx).await;
}
#[::gpui::test]
#[cfg_attr(not(feature = "e2e"), ignore)]
async fn cancel(cx: &mut ::gpui::TestAppContext) {
$crate::e2e_tests::test_cancel($server, cx).await;
}
}
};
}
// Helpers
pub async fn init_test(cx: &mut TestAppContext) -> Arc<FakeFs> {
env_logger::try_init().ok();
cx.update(|cx| {
let settings_store = SettingsStore::test(cx);
cx.set_global(settings_store);
Project::init_settings(cx);
language::init(cx);
crate::settings::init(cx);
crate::AllAgentServersSettings::override_global(
AllAgentServersSettings {
claude: Some(AgentServerSettings {
command: crate::claude::tests::local_command(),
}),
gemini: Some(AgentServerSettings {
command: crate::gemini::tests::local_command(),
}),
},
cx,
);
});
cx.executor().allow_parking();
FakeFs::new(cx.executor())
}
pub async fn new_test_thread(
server: impl AgentServer + 'static,
project: Entity<Project>,
current_dir: impl AsRef<Path>,
cx: &mut TestAppContext,
) -> Entity<AcpThread> {
let thread = cx
.update(|cx| server.new_thread(current_dir.as_ref(), &project, cx))
.await
.unwrap();
thread
.update(cx, |thread, _| thread.initialize())
.await
.unwrap();
thread
}
pub async fn run_until_first_tool_call(
thread: &Entity<AcpThread>,
wait_until: impl Fn(&AgentThreadEntry) -> bool + 'static,
cx: &mut TestAppContext,
) -> usize {
let (mut tx, mut rx) = mpsc::channel::<usize>(1);
let subscription = cx.update(|cx| {
cx.subscribe(thread, move |thread, _, cx| {
for (ix, entry) in thread.read(cx).entries().iter().enumerate() {
if wait_until(entry) {
return tx.try_send(ix).unwrap();
}
}
})
});
select! {
// We have to use a smol timer here because
// cx.background_executor().timer isn't real in the test context
_ = futures::FutureExt::fuse(smol::Timer::after(Duration::from_secs(20))) => {
panic!("Timeout waiting for tool call")
}
ix = rx.next().fuse() => {
drop(subscription);
ix.unwrap()
}
}
}

View File

@@ -0,0 +1,123 @@
use crate::stdio_agent_server::StdioAgentServer;
use crate::{AgentServerCommand, AgentServerVersion};
use anyhow::{Context as _, Result};
use gpui::{AsyncApp, Entity};
use project::Project;
use settings::SettingsStore;
use crate::AllAgentServersSettings;
#[derive(Clone)]
pub struct Gemini;
const ACP_ARG: &str = "--experimental-acp";
impl StdioAgentServer for Gemini {
fn name(&self) -> &'static str {
"Gemini"
}
fn empty_state_headline(&self) -> &'static str {
"Welcome to Gemini"
}
fn empty_state_message(&self) -> &'static str {
"Ask questions, edit files, run commands.\nBe specific for the best results."
}
fn supports_always_allow(&self) -> bool {
true
}
fn logo(&self) -> ui::IconName {
ui::IconName::AiGemini
}
async fn command(
&self,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> Result<AgentServerCommand> {
let settings = cx.read_global(|settings: &SettingsStore, _| {
settings.get::<AllAgentServersSettings>(None).gemini.clone()
})?;
if let Some(command) =
AgentServerCommand::resolve("gemini", &[ACP_ARG], settings, &project, cx).await
{
return Ok(command);
};
let (fs, node_runtime) = project.update(cx, |project, _| {
(project.fs().clone(), project.node_runtime().cloned())
})?;
let node_runtime = node_runtime.context("gemini not found on path")?;
let directory = ::paths::agent_servers_dir().join("gemini");
fs.create_dir(&directory).await?;
node_runtime
.npm_install_packages(&directory, &[("@google/gemini-cli", "latest")])
.await?;
let path = directory.join("node_modules/.bin/gemini");
Ok(AgentServerCommand {
path,
args: vec![ACP_ARG.into()],
env: None,
})
}
async fn version(&self, command: &AgentServerCommand) -> Result<AgentServerVersion> {
let version_fut = util::command::new_smol_command(&command.path)
.args(command.args.iter())
.arg("--version")
.kill_on_drop(true)
.output();
let help_fut = util::command::new_smol_command(&command.path)
.args(command.args.iter())
.arg("--help")
.kill_on_drop(true)
.output();
let (version_output, help_output) = futures::future::join(version_fut, help_fut).await;
let current_version = String::from_utf8(version_output?.stdout)?;
let supported = String::from_utf8(help_output?.stdout)?.contains(ACP_ARG);
if supported {
Ok(AgentServerVersion::Supported)
} else {
Ok(AgentServerVersion::Unsupported {
error_message: format!(
"Your installed version of Gemini {} doesn't support the Agentic Coding Protocol (ACP).",
current_version
).into(),
upgrade_message: "Upgrade Gemini to Latest".into(),
upgrade_command: "npm install -g @google/gemini-cli@latest".into(),
})
}
}
}
#[cfg(test)]
pub(crate) mod tests {
use super::*;
use crate::AgentServerCommand;
use std::path::Path;
crate::common_e2e_tests!(Gemini);
pub fn local_command() -> AgentServerCommand {
let cli_path = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../../gemini-cli/packages/cli")
.to_string_lossy()
.to_string();
AgentServerCommand {
path: "node".into(),
args: vec![cli_path, ACP_ARG.into()],
env: None,
}
}
}

View File

@@ -0,0 +1,45 @@
use crate::AgentServerCommand;
use anyhow::Result;
use gpui::App;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
pub fn init(cx: &mut App) {
AllAgentServersSettings::register(cx);
}
#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug)]
pub struct AllAgentServersSettings {
pub gemini: Option<AgentServerSettings>,
pub claude: Option<AgentServerSettings>,
}
#[derive(Deserialize, Serialize, Clone, JsonSchema, Debug)]
pub struct AgentServerSettings {
#[serde(flatten)]
pub command: AgentServerCommand,
}
impl settings::Settings for AllAgentServersSettings {
const KEY: Option<&'static str> = Some("agent_servers");
type FileContent = Self;
fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
let mut settings = AllAgentServersSettings::default();
for AllAgentServersSettings { gemini, claude } in sources.defaults_and_customizations() {
if gemini.is_some() {
settings.gemini = gemini.clone();
}
if claude.is_some() {
settings.claude = claude.clone();
}
}
Ok(settings)
}
fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
}

View File

@@ -0,0 +1,119 @@
use crate::{AgentServer, AgentServerCommand, AgentServerVersion};
use acp_thread::{AcpClientDelegate, AcpThread, LoadError};
use agentic_coding_protocol as acp;
use anyhow::{Result, anyhow};
use gpui::{App, AsyncApp, Entity, Task, prelude::*};
use project::Project;
use std::path::Path;
use util::ResultExt;
pub trait StdioAgentServer: Send + Clone {
fn logo(&self) -> ui::IconName;
fn name(&self) -> &'static str;
fn empty_state_headline(&self) -> &'static str;
fn empty_state_message(&self) -> &'static str;
fn supports_always_allow(&self) -> bool;
fn command(
&self,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> impl Future<Output = Result<AgentServerCommand>>;
fn version(
&self,
command: &AgentServerCommand,
) -> impl Future<Output = Result<AgentServerVersion>> + Send;
}
impl<T: StdioAgentServer + 'static> AgentServer for T {
fn name(&self) -> &'static str {
self.name()
}
fn empty_state_headline(&self) -> &'static str {
self.empty_state_headline()
}
fn empty_state_message(&self) -> &'static str {
self.empty_state_message()
}
fn logo(&self) -> ui::IconName {
self.logo()
}
fn supports_always_allow(&self) -> bool {
self.supports_always_allow()
}
fn new_thread(
&self,
root_dir: &Path,
project: &Entity<Project>,
cx: &mut App,
) -> Task<Result<Entity<AcpThread>>> {
let root_dir = root_dir.to_path_buf();
let project = project.clone();
let this = self.clone();
let title = self.name().into();
cx.spawn(async move |cx| {
let command = this.command(&project, cx).await?;
let mut child = util::command::new_smol_command(&command.path)
.args(command.args.iter())
.current_dir(root_dir)
.stdin(std::process::Stdio::piped())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::inherit())
.kill_on_drop(true)
.spawn()?;
let stdin = child.stdin.take().unwrap();
let stdout = child.stdout.take().unwrap();
cx.new(|cx| {
let foreground_executor = cx.foreground_executor().clone();
let (connection, io_fut) = acp::AgentConnection::connect_to_agent(
AcpClientDelegate::new(cx.entity().downgrade(), cx.to_async()),
stdin,
stdout,
move |fut| foreground_executor.spawn(fut).detach(),
);
let io_task = cx.background_spawn(async move {
io_fut.await.log_err();
});
let child_status = cx.background_spawn(async move {
let result = match child.status().await {
Err(e) => Err(anyhow!(e)),
Ok(result) if result.success() => Ok(()),
Ok(result) => {
if let Some(AgentServerVersion::Unsupported {
error_message,
upgrade_message,
upgrade_command,
}) = this.version(&command).await.log_err()
{
Err(anyhow!(LoadError::Unsupported {
error_message,
upgrade_message,
upgrade_command
}))
} else {
Err(anyhow!(LoadError::Exited(result.code().unwrap_or(-127))))
}
}
};
drop(io_task);
result
});
AcpThread::new(connection, title, Some(child_status), project.clone(), cx)
})
})
}
}

View File

@@ -6,9 +6,10 @@ use anyhow::{Result, bail};
use collections::IndexMap;
use gpui::{App, Pixels, SharedString};
use language_model::LanguageModel;
use schemars::{JsonSchema, schema::Schema};
use schemars::{JsonSchema, json_schema};
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources};
use std::borrow::Cow;
pub use crate::agent_profile::*;
@@ -49,7 +50,7 @@ pub struct AgentSettings {
pub dock: AgentDockPosition,
pub default_width: Pixels,
pub default_height: Pixels,
pub default_model: LanguageModelSelection,
pub default_model: Option<LanguageModelSelection>,
pub inline_assistant_model: Option<LanguageModelSelection>,
pub commit_message_model: Option<LanguageModelSelection>,
pub thread_summary_model: Option<LanguageModelSelection>,
@@ -66,6 +67,9 @@ pub struct AgentSettings {
pub model_parameters: Vec<LanguageModelParameters>,
pub preferred_completion_mode: CompletionMode,
pub enable_feedback: bool,
pub expand_edit_card: bool,
pub expand_terminal_card: bool,
pub use_modifier_to_send: bool,
}
impl AgentSettings {
@@ -171,6 +175,10 @@ impl AgentSettingsContent {
self.single_file_review = Some(allow);
}
pub fn set_use_modifier_to_send(&mut self, always_use: bool) {
self.use_modifier_to_send = Some(always_use);
}
pub fn set_profile(&mut self, profile_id: AgentProfileId) {
self.default_profile = Some(profile_id);
}
@@ -211,7 +219,6 @@ impl AgentSettingsContent {
}
#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug, Default)]
#[schemars(deny_unknown_fields)]
pub struct AgentSettingsContent {
/// Whether the Agent is enabled.
///
@@ -291,6 +298,18 @@ pub struct AgentSettingsContent {
///
/// Default: true
enable_feedback: Option<bool>,
/// Whether to have edit cards in the agent panel expanded, showing a preview of the full diff.
///
/// Default: true
expand_edit_card: Option<bool>,
/// Whether to have terminal cards in the agent panel expanded, showing the whole command output.
///
/// Default: true
expand_terminal_card: Option<bool>,
/// Whether to always use cmd-enter (or ctrl-enter on Linux) to send messages in the agent panel.
///
/// Default: false
use_modifier_to_send: Option<bool>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
@@ -321,29 +340,27 @@ pub struct LanguageModelSelection {
pub struct LanguageModelProviderSetting(pub String);
impl JsonSchema for LanguageModelProviderSetting {
fn schema_name() -> String {
fn schema_name() -> Cow<'static, str> {
"LanguageModelProviderSetting".into()
}
fn json_schema(_: &mut schemars::r#gen::SchemaGenerator) -> Schema {
schemars::schema::SchemaObject {
enum_values: Some(vec![
"anthropic".into(),
"amazon-bedrock".into(),
"google".into(),
"lmstudio".into(),
"ollama".into(),
"openai".into(),
"zed.dev".into(),
"copilot_chat".into(),
"deepseek".into(),
"openrouter".into(),
"mistral".into(),
"vercel".into(),
]),
..Default::default()
}
.into()
fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
json_schema!({
"enum": [
"anthropic",
"amazon-bedrock",
"google",
"lmstudio",
"ollama",
"openai",
"zed.dev",
"copilot_chat",
"deepseek",
"openrouter",
"mistral",
"vercel"
]
})
}
}
@@ -359,15 +376,6 @@ impl From<&str> for LanguageModelProviderSetting {
}
}
impl Default for LanguageModelSelection {
fn default() -> Self {
Self {
provider: LanguageModelProviderSetting("openai".to_string()),
model: "gpt-4".to_string(),
}
}
}
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
pub struct AgentProfileContent {
pub name: Arc<str>,
@@ -411,7 +419,10 @@ impl Settings for AgentSettings {
&mut settings.default_height,
value.default_height.map(Into::into),
);
merge(&mut settings.default_model, value.default_model.clone());
settings.default_model = value
.default_model
.clone()
.or(settings.default_model.take());
settings.inline_assistant_model = value
.inline_assistant_model
.clone()
@@ -449,6 +460,15 @@ impl Settings for AgentSettings {
value.preferred_completion_mode,
);
merge(&mut settings.enable_feedback, value.enable_feedback);
merge(&mut settings.expand_edit_card, value.expand_edit_card);
merge(
&mut settings.expand_terminal_card,
value.expand_terminal_card,
);
merge(
&mut settings.use_modifier_to_send,
value.use_modifier_to_send,
);
settings
.model_parameters

View File

@@ -13,14 +13,15 @@ path = "src/agent_ui.rs"
doctest = false
[features]
test-support = [
"gpui/test-support",
"language/test-support",
]
test-support = ["gpui/test-support", "language/test-support"]
[dependencies]
acp_thread.workspace = true
agent.workspace = true
agentic-coding-protocol.workspace = true
agent_settings.workspace = true
agent_servers.workspace = true
ai_onboarding.workspace = true
anyhow.workspace = true
assistant_context.workspace = true
assistant_slash_command.workspace = true
@@ -31,6 +32,7 @@ buffer_diff.workspace = true
chrono.workspace = true
client.workspace = true
collections.workspace = true
command_palette_hooks.workspace = true
component.workspace = true
context_server.workspace = true
db.workspace = true
@@ -52,6 +54,7 @@ itertools.workspace = true
jsonschema.workspace = true
language.workspace = true
language_model.workspace = true
language_models.workspace = true
log.workspace = true
lsp.workspace = true
markdown.workspace = true
@@ -76,6 +79,7 @@ serde_json_lenient.workspace = true
settings.workspace = true
smol.workspace = true
streaming_diff.workspace = true
task.workspace = true
telemetry.workspace = true
telemetry_events.workspace = true
terminal.workspace = true
@@ -85,6 +89,7 @@ theme.workspace = true
time.workspace = true
time_format.workspace = true
ui.workspace = true
ui_input.workspace = true
urlencoding.workspace = true
util.workspace = true
uuid.workspace = true

View File

@@ -0,0 +1,6 @@
mod completion_provider;
mod message_history;
mod thread_view;
pub use message_history::MessageHistory;
pub use thread_view::AcpThreadView;

View File

@@ -0,0 +1,574 @@
use std::ops::Range;
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::AtomicBool;
use anyhow::Result;
use collections::HashMap;
use editor::display_map::CreaseId;
use editor::{CompletionProvider, Editor, ExcerptId};
use file_icons::FileIcons;
use gpui::{App, Entity, Task, WeakEntity};
use language::{Buffer, CodeLabel, HighlightId};
use lsp::CompletionContext;
use parking_lot::Mutex;
use project::{Completion, CompletionIntent, CompletionResponse, ProjectPath, WorktreeId};
use rope::Point;
use text::{Anchor, ToPoint};
use ui::prelude::*;
use workspace::Workspace;
use crate::context_picker::MentionLink;
use crate::context_picker::file_context_picker::{extract_file_name_and_directory, search_files};
#[derive(Default)]
pub struct MentionSet {
paths_by_crease_id: HashMap<CreaseId, ProjectPath>,
}
impl MentionSet {
pub fn insert(&mut self, crease_id: CreaseId, path: ProjectPath) {
self.paths_by_crease_id.insert(crease_id, path);
}
pub fn path_for_crease_id(&self, crease_id: CreaseId) -> Option<ProjectPath> {
self.paths_by_crease_id.get(&crease_id).cloned()
}
pub fn drain(&mut self) -> impl Iterator<Item = CreaseId> {
self.paths_by_crease_id.drain().map(|(id, _)| id)
}
}
pub struct ContextPickerCompletionProvider {
workspace: WeakEntity<Workspace>,
editor: WeakEntity<Editor>,
mention_set: Arc<Mutex<MentionSet>>,
}
impl ContextPickerCompletionProvider {
pub fn new(
mention_set: Arc<Mutex<MentionSet>>,
workspace: WeakEntity<Workspace>,
editor: WeakEntity<Editor>,
) -> Self {
Self {
mention_set,
workspace,
editor,
}
}
fn completion_for_path(
project_path: ProjectPath,
path_prefix: &str,
is_recent: bool,
is_directory: bool,
excerpt_id: ExcerptId,
source_range: Range<Anchor>,
editor: Entity<Editor>,
mention_set: Arc<Mutex<MentionSet>>,
cx: &App,
) -> Completion {
let (file_name, directory) =
extract_file_name_and_directory(&project_path.path, path_prefix);
let label =
build_code_label_for_full_path(&file_name, directory.as_ref().map(|s| s.as_ref()), cx);
let full_path = if let Some(directory) = directory {
format!("{}{}", directory, file_name)
} else {
file_name.to_string()
};
let crease_icon_path = if is_directory {
FileIcons::get_folder_icon(false, cx).unwrap_or_else(|| IconName::Folder.path().into())
} else {
FileIcons::get_icon(Path::new(&full_path), cx)
.unwrap_or_else(|| IconName::File.path().into())
};
let completion_icon_path = if is_recent {
IconName::HistoryRerun.path().into()
} else {
crease_icon_path.clone()
};
let new_text = format!("{} ", MentionLink::for_file(&file_name, &full_path));
let new_text_len = new_text.len();
Completion {
replace_range: source_range.clone(),
new_text,
label,
documentation: None,
source: project::CompletionSource::Custom,
icon_path: Some(completion_icon_path),
insert_text_mode: None,
confirm: Some(confirm_completion_callback(
crease_icon_path,
file_name,
project_path,
excerpt_id,
source_range.start,
new_text_len - 1,
editor,
mention_set,
)),
}
}
}
fn build_code_label_for_full_path(file_name: &str, directory: Option<&str>, cx: &App) -> CodeLabel {
let comment_id = cx.theme().syntax().highlight_id("comment").map(HighlightId);
let mut label = CodeLabel::default();
label.push_str(&file_name, None);
label.push_str(" ", None);
if let Some(directory) = directory {
label.push_str(&directory, comment_id);
}
label.filter_range = 0..label.text().len();
label
}
impl CompletionProvider for ContextPickerCompletionProvider {
fn completions(
&self,
excerpt_id: ExcerptId,
buffer: &Entity<Buffer>,
buffer_position: Anchor,
_trigger: CompletionContext,
_window: &mut Window,
cx: &mut Context<Editor>,
) -> Task<Result<Vec<CompletionResponse>>> {
let state = buffer.update(cx, |buffer, _cx| {
let position = buffer_position.to_point(buffer);
let line_start = Point::new(position.row, 0);
let offset_to_line = buffer.point_to_offset(line_start);
let mut lines = buffer.text_for_range(line_start..position).lines();
let line = lines.next()?;
MentionCompletion::try_parse(line, offset_to_line)
});
let Some(state) = state else {
return Task::ready(Ok(Vec::new()));
};
let Some(workspace) = self.workspace.upgrade() else {
return Task::ready(Ok(Vec::new()));
};
let snapshot = buffer.read(cx).snapshot();
let source_range = snapshot.anchor_before(state.source_range.start)
..snapshot.anchor_after(state.source_range.end);
let editor = self.editor.clone();
let mention_set = self.mention_set.clone();
let MentionCompletion { argument, .. } = state;
let query = argument.unwrap_or_else(|| "".to_string());
let search_task = search_files(query.clone(), Arc::<AtomicBool>::default(), &workspace, cx);
cx.spawn(async move |_, cx| {
let matches = search_task.await;
let Some(editor) = editor.upgrade() else {
return Ok(Vec::new());
};
let completions = cx.update(|cx| {
matches
.into_iter()
.map(|mat| {
let path_match = &mat.mat;
let project_path = ProjectPath {
worktree_id: WorktreeId::from_usize(path_match.worktree_id),
path: path_match.path.clone(),
};
Self::completion_for_path(
project_path,
&path_match.path_prefix,
mat.is_recent,
path_match.is_dir,
excerpt_id,
source_range.clone(),
editor.clone(),
mention_set.clone(),
cx,
)
})
.collect()
})?;
Ok(vec![CompletionResponse {
completions,
// Since this does its own filtering (see `filter_completions()` returns false),
// there is no benefit to computing whether this set of completions is incomplete.
is_incomplete: true,
}])
})
}
fn is_completion_trigger(
&self,
buffer: &Entity<language::Buffer>,
position: language::Anchor,
_text: &str,
_trigger_in_words: bool,
_menu_is_open: bool,
cx: &mut Context<Editor>,
) -> bool {
let buffer = buffer.read(cx);
let position = position.to_point(buffer);
let line_start = Point::new(position.row, 0);
let offset_to_line = buffer.point_to_offset(line_start);
let mut lines = buffer.text_for_range(line_start..position).lines();
if let Some(line) = lines.next() {
MentionCompletion::try_parse(line, offset_to_line)
.map(|completion| {
completion.source_range.start <= offset_to_line + position.column as usize
&& completion.source_range.end >= offset_to_line + position.column as usize
})
.unwrap_or(false)
} else {
false
}
}
fn sort_completions(&self) -> bool {
false
}
fn filter_completions(&self) -> bool {
false
}
}
fn confirm_completion_callback(
crease_icon_path: SharedString,
crease_text: SharedString,
project_path: ProjectPath,
excerpt_id: ExcerptId,
start: Anchor,
content_len: usize,
editor: Entity<Editor>,
mention_set: Arc<Mutex<MentionSet>>,
) -> Arc<dyn Fn(CompletionIntent, &mut Window, &mut App) -> bool + Send + Sync> {
Arc::new(move |_, window, cx| {
let crease_text = crease_text.clone();
let crease_icon_path = crease_icon_path.clone();
let editor = editor.clone();
let project_path = project_path.clone();
let mention_set = mention_set.clone();
window.defer(cx, move |window, cx| {
let crease_id = crate::context_picker::insert_crease_for_mention(
excerpt_id,
start,
content_len,
crease_text.clone(),
crease_icon_path,
editor.clone(),
window,
cx,
);
if let Some(crease_id) = crease_id {
mention_set.lock().insert(crease_id, project_path);
}
});
false
})
}
#[derive(Debug, Default, PartialEq)]
struct MentionCompletion {
source_range: Range<usize>,
argument: Option<String>,
}
impl MentionCompletion {
fn try_parse(line: &str, offset_to_line: usize) -> Option<Self> {
let last_mention_start = line.rfind('@')?;
if last_mention_start >= line.len() {
return Some(Self::default());
}
if last_mention_start > 0
&& line
.chars()
.nth(last_mention_start - 1)
.map_or(false, |c| !c.is_whitespace())
{
return None;
}
let rest_of_line = &line[last_mention_start + 1..];
let mut argument = None;
let mut parts = rest_of_line.split_whitespace();
let mut end = last_mention_start + 1;
if let Some(argument_text) = parts.next() {
end += argument_text.len();
argument = Some(argument_text.to_string());
}
Some(Self {
source_range: last_mention_start + offset_to_line..end + offset_to_line,
argument,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use gpui::{EventEmitter, FocusHandle, Focusable, TestAppContext, VisualTestContext};
use project::{Project, ProjectPath};
use serde_json::json;
use settings::SettingsStore;
use std::{ops::Deref, rc::Rc};
use util::path;
use workspace::{AppState, Item};
#[test]
fn test_mention_completion_parse() {
assert_eq!(MentionCompletion::try_parse("Lorem Ipsum", 0), None);
assert_eq!(
MentionCompletion::try_parse("Lorem @", 0),
Some(MentionCompletion {
source_range: 6..7,
argument: None,
})
);
assert_eq!(
MentionCompletion::try_parse("Lorem @main", 0),
Some(MentionCompletion {
source_range: 6..11,
argument: Some("main".to_string()),
})
);
assert_eq!(MentionCompletion::try_parse("test@", 0), None);
}
struct AtMentionEditor(Entity<Editor>);
impl Item for AtMentionEditor {
type Event = ();
fn include_in_nav_history() -> bool {
false
}
fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
"Test".into()
}
}
impl EventEmitter<()> for AtMentionEditor {}
impl Focusable for AtMentionEditor {
fn focus_handle(&self, cx: &App) -> FocusHandle {
self.0.read(cx).focus_handle(cx).clone()
}
}
impl Render for AtMentionEditor {
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
self.0.clone().into_any_element()
}
}
#[gpui::test]
async fn test_context_completion_provider(cx: &mut TestAppContext) {
init_test(cx);
let app_state = cx.update(AppState::test);
cx.update(|cx| {
language::init(cx);
editor::init(cx);
workspace::init(app_state.clone(), cx);
Project::init_settings(cx);
});
app_state
.fs
.as_fake()
.insert_tree(
path!("/dir"),
json!({
"editor": "",
"a": {
"one.txt": "",
"two.txt": "",
"three.txt": "",
"four.txt": ""
},
"b": {
"five.txt": "",
"six.txt": "",
"seven.txt": "",
"eight.txt": "",
}
}),
)
.await;
let project = Project::test(app_state.fs.clone(), [path!("/dir").as_ref()], cx).await;
let window = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
let workspace = window.root(cx).unwrap();
let worktree = project.update(cx, |project, cx| {
let mut worktrees = project.worktrees(cx).collect::<Vec<_>>();
assert_eq!(worktrees.len(), 1);
worktrees.pop().unwrap()
});
let worktree_id = worktree.read_with(cx, |worktree, _| worktree.id());
let mut cx = VisualTestContext::from_window(*window.deref(), cx);
let paths = vec![
path!("a/one.txt"),
path!("a/two.txt"),
path!("a/three.txt"),
path!("a/four.txt"),
path!("b/five.txt"),
path!("b/six.txt"),
path!("b/seven.txt"),
path!("b/eight.txt"),
];
let mut opened_editors = Vec::new();
for path in paths {
let buffer = workspace
.update_in(&mut cx, |workspace, window, cx| {
workspace.open_path(
ProjectPath {
worktree_id,
path: Path::new(path).into(),
},
None,
false,
window,
cx,
)
})
.await
.unwrap();
opened_editors.push(buffer);
}
let editor = workspace.update_in(&mut cx, |workspace, window, cx| {
let editor = cx.new(|cx| {
Editor::new(
editor::EditorMode::full(),
multi_buffer::MultiBuffer::build_simple("", cx),
None,
window,
cx,
)
});
workspace.active_pane().update(cx, |pane, cx| {
pane.add_item(
Box::new(cx.new(|_| AtMentionEditor(editor.clone()))),
true,
true,
None,
window,
cx,
);
});
editor
});
let mention_set = Arc::new(Mutex::new(MentionSet::default()));
let editor_entity = editor.downgrade();
editor.update_in(&mut cx, |editor, window, cx| {
window.focus(&editor.focus_handle(cx));
editor.set_completion_provider(Some(Rc::new(ContextPickerCompletionProvider::new(
mention_set.clone(),
workspace.downgrade(),
editor_entity,
))));
});
cx.simulate_input("Lorem ");
editor.update(&mut cx, |editor, cx| {
assert_eq!(editor.text(cx), "Lorem ");
assert!(!editor.has_visible_completions_menu());
});
cx.simulate_input("@");
editor.update(&mut cx, |editor, cx| {
assert_eq!(editor.text(cx), "Lorem @");
assert!(editor.has_visible_completions_menu());
assert_eq!(
current_completion_labels(editor),
&[
"eight.txt dir/b/",
"seven.txt dir/b/",
"six.txt dir/b/",
"five.txt dir/b/",
"four.txt dir/a/",
"three.txt dir/a/",
"two.txt dir/a/",
"one.txt dir/a/",
"dir ",
"a dir/",
"four.txt dir/a/",
"one.txt dir/a/",
"three.txt dir/a/",
"two.txt dir/a/",
"b dir/",
"eight.txt dir/b/",
"five.txt dir/b/",
"seven.txt dir/b/",
"six.txt dir/b/",
"editor dir/"
]
);
});
// Select and confirm "File"
editor.update_in(&mut cx, |editor, window, cx| {
assert!(editor.has_visible_completions_menu());
editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx);
editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx);
editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx);
editor.context_menu_next(&editor::actions::ContextMenuNext, window, cx);
editor.confirm_completion(&editor::actions::ConfirmCompletion::default(), window, cx);
});
cx.run_until_parked();
editor.update(&mut cx, |editor, cx| {
assert_eq!(editor.text(cx), "Lorem [@four.txt](@file:dir/a/four.txt) ");
});
}
fn current_completion_labels(editor: &Editor) -> Vec<String> {
let completions = editor.current_completions().expect("Missing completions");
completions
.into_iter()
.map(|completion| completion.label.text.to_string())
.collect::<Vec<_>>()
}
pub(crate) fn init_test(cx: &mut TestAppContext) {
cx.update(|cx| {
let store = SettingsStore::test(cx);
cx.set_global(store);
theme::init(theme::LoadThemes::JustBase, cx);
client::init_settings(cx);
language::init(cx);
Project::init_settings(cx);
workspace::init_settings(cx);
editor::init_settings(cx);
});
}
}

View File

@@ -0,0 +1,87 @@
pub struct MessageHistory<T> {
items: Vec<T>,
current: Option<usize>,
}
impl<T> Default for MessageHistory<T> {
fn default() -> Self {
MessageHistory {
items: Vec::new(),
current: None,
}
}
}
impl<T> MessageHistory<T> {
pub fn push(&mut self, message: T) {
self.current.take();
self.items.push(message);
}
pub fn reset_position(&mut self) {
self.current.take();
}
pub fn prev(&mut self) -> Option<&T> {
if self.items.is_empty() {
return None;
}
let new_ix = self
.current
.get_or_insert(self.items.len())
.saturating_sub(1);
self.current = Some(new_ix);
self.items.get(new_ix)
}
pub fn next(&mut self) -> Option<&T> {
let current = self.current.as_mut()?;
*current += 1;
self.items.get(*current).or_else(|| {
self.current.take();
None
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_prev_next() {
let mut history = MessageHistory::default();
// Test empty history
assert_eq!(history.prev(), None);
assert_eq!(history.next(), None);
// Add some messages
history.push("first");
history.push("second");
history.push("third");
// Test prev navigation
assert_eq!(history.prev(), Some(&"third"));
assert_eq!(history.prev(), Some(&"second"));
assert_eq!(history.prev(), Some(&"first"));
assert_eq!(history.prev(), Some(&"first"));
assert_eq!(history.next(), Some(&"second"));
// Test mixed navigation
history.push("fourth");
assert_eq!(history.prev(), Some(&"fourth"));
assert_eq!(history.prev(), Some(&"third"));
assert_eq!(history.next(), Some(&"fourth"));
assert_eq!(history.next(), None);
// Test that push resets navigation
history.prev();
history.prev();
history.push("fifth");
assert_eq!(history.prev(), Some(&"fifth"));
}
}

File diff suppressed because it is too large Load Diff

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