Compare commits

...

452 Commits

Author SHA1 Message Date
Conrad Irwin
0683f3cfbc +Codex 2025-07-16 20:33:52 -06: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
731 changed files with 50648 additions and 16367 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 = "270538dc780f5240723233ff901e1054641ed318" },
]
[final-excludes]
@@ -33,7 +35,6 @@ workspace-members = [
"zed_emmet",
"zed_glsl",
"zed_html",
"perplexity",
"zed_proto",
"zed_ruff",
"slash_commands_example",

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,7 @@ 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 }}
runs-on:
- ubuntu-latest
steps:
@@ -51,9 +55,10 @@ jobs:
fi
# Specify anything which should skip full CI 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)))'
SKIP_REGEX='^(docs/|script/update_top_ranking_issues/|\.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
@@ -64,11 +69,17 @@ jobs:
else
echo "run_docs=false" >> $GITHUB_OUTPUT
fi
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep '^Cargo.lock') ]]; then
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -P '^(Cargo.lock|script/.*licenses)') ]]; then
echo "run_license=true" >> $GITHUB_OUTPUT
else
echo "run_license=false" >> $GITHUB_OUTPUT
fi
NIX_REGEX='^(nix/|flake\.|Cargo\.|rust-toolchain.toml|\.cargo/config.toml)'
if [[ $(git diff --name-only $COMPARE_REV ${{ github.sha }} | grep -P "$NIX_REGEX") ]]; then
echo "run_nix=true" >> $GITHUB_OUTPUT
else
echo "run_nix=false" >> $GITHUB_OUTPUT
fi
migration_checks:
name: Check Postgres and Protobuf migrations, mergability
@@ -383,7 +394,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 +415,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 +433,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
@@ -460,8 +461,10 @@ 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
# Only check test jobs if they were supposed to run
if [[ "${{ needs.job_spec.outputs.run_tests }}" == "true" ]]; then
[[ "${{ needs.workspace_hack.result }}" != 'success' ]] && { RET_CODE=1; echo "Workspace Hack failed"; }
@@ -493,9 +496,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 +578,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 +631,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 +679,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,19 +734,73 @@ 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: ${{ 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: false && ${{ !(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

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

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,6 +54,32 @@ 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
@@ -65,9 +94,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 +125,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
@@ -138,10 +160,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 +187,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 +228,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 +279,7 @@ jobs:
- bundle-mac
- bundle-linux-x86
- bundle-linux-arm
- bundle-windows-x64
steps:
- 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,

294
Cargo.lock generated
View File

@@ -2,6 +2,34 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "acp"
version = "0.1.0"
dependencies = [
"agent_servers",
"agentic-coding-protocol",
"anyhow",
"assistant_tool",
"async-pipe",
"buffer_diff",
"editor",
"env_logger 0.11.8",
"futures 0.3.31",
"gpui",
"indoc",
"itertools 0.14.0",
"language",
"markdown",
"project",
"serde_json",
"settings",
"smol",
"tempfile",
"ui",
"util",
"workspace-hack",
]
[[package]]
name = "activity_indicator"
version = "0.1.0"
@@ -78,6 +106,7 @@ dependencies = [
"language",
"language_model",
"log",
"parking_lot",
"paths",
"postage",
"pretty_assertions",
@@ -106,6 +135,24 @@ dependencies = [
"zstd",
]
[[package]]
name = "agent_servers"
version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"futures 0.3.31",
"gpui",
"paths",
"project",
"schemars",
"serde",
"settings",
"util",
"which 6.0.3",
"workspace-hack",
]
[[package]]
name = "agent_settings"
version = "0.1.0"
@@ -129,8 +176,11 @@ dependencies = [
name = "agent_ui"
version = "0.1.0"
dependencies = [
"acp",
"agent",
"agent_servers",
"agent_settings",
"agentic-coding-protocol",
"anyhow",
"assistant_context",
"assistant_slash_command",
@@ -190,6 +240,7 @@ dependencies = [
"settings",
"smol",
"streaming_diff",
"task",
"telemetry",
"telemetry_events",
"terminal",
@@ -211,6 +262,24 @@ dependencies = [
"zed_llm_client",
]
[[package]]
name = "agentic-coding-protocol"
version = "0.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e276b798eddd02562a339340a96919d90bbfcf78de118fdddc932524646fac7"
dependencies = [
"anyhow",
"chrono",
"derive_more 2.0.1",
"futures 0.3.31",
"log",
"parking_lot",
"schemars",
"semver",
"serde",
"serde_json",
]
[[package]]
name = "ahash"
version = "0.7.8"
@@ -537,6 +606,8 @@ dependencies = [
"anyhow",
"futures 0.3.31",
"gpui",
"net",
"parking_lot",
"smol",
"tempfile",
"util",
@@ -607,7 +678,7 @@ dependencies = [
"anyhow",
"async-trait",
"collections",
"derive_more",
"derive_more 0.99.19",
"extension",
"futures 0.3.31",
"gpui",
@@ -670,10 +741,11 @@ dependencies = [
"clock",
"collections",
"ctor",
"derive_more",
"derive_more 0.99.19",
"futures 0.3.31",
"gpui",
"icons",
"indoc",
"language",
"language_model",
"log",
@@ -706,7 +778,8 @@ dependencies = [
"clock",
"collections",
"component",
"derive_more",
"derive_more 0.99.19",
"diffy",
"editor",
"feature_flags",
"fs",
@@ -1163,7 +1236,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"derive_more",
"derive_more 0.99.19",
"gpui",
"parking_lot",
"rodio",
@@ -1910,7 +1983,6 @@ dependencies = [
"serde_json",
"strum 0.27.1",
"thiserror 2.0.12",
"tokio",
"workspace-hack",
]
@@ -2076,7 +2148,7 @@ dependencies = [
[[package]]
name = "blade-graphics"
version = "0.6.0"
source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
dependencies = [
"ash",
"ash-window",
@@ -2109,7 +2181,7 @@ dependencies = [
[[package]]
name = "blade-macros"
version = "0.3.0"
source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
dependencies = [
"proc-macro2",
"quote",
@@ -2119,7 +2191,7 @@ dependencies = [
[[package]]
name = "blade-util"
version = "0.2.0"
source = "git+https://github.com/kvark/blade?rev=e0ec4e720957edd51b945b64dd85605ea54bcfe5#e0ec4e720957edd51b945b64dd85605ea54bcfe5"
source = "git+https://github.com/kvark/blade?rev=416375211bb0b5826b3584dccdb6a43369e499ad#416375211bb0b5826b3584dccdb6a43369e499ad"
dependencies = [
"blade-graphics",
"bytemuck",
@@ -2857,7 +2929,7 @@ dependencies = [
"cocoa 0.26.0",
"collections",
"credentials_provider",
"derive_more",
"derive_more 0.99.19",
"feature_flags",
"fs",
"futures 0.3.31",
@@ -3041,10 +3113,11 @@ dependencies = [
"context_server",
"ctor",
"dap",
"dap-types",
"dap_adapters",
"dashmap 6.1.0",
"debugger_ui",
"derive_more",
"derive_more 0.99.19",
"editor",
"envy",
"extension",
@@ -3097,6 +3170,7 @@ dependencies = [
"session",
"settings",
"sha2",
"smol",
"sqlx",
"strum 0.27.1",
"subtle",
@@ -3249,7 +3323,7 @@ name = "command_palette_hooks"
version = "0.1.0"
dependencies = [
"collections",
"derive_more",
"derive_more 0.99.19",
"gpui",
"workspace-hack",
]
@@ -4132,7 +4206,7 @@ dependencies = [
[[package]]
name = "dap-types"
version = "0.0.1"
source = "git+https://github.com/zed-industries/dap-types?rev=b40956a7f4d1939da67429d941389ee306a3a308#b40956a7f4d1939da67429d941389ee306a3a308"
source = "git+https://github.com/zed-industries/dap-types?rev=7f39295b441614ca9dbf44293e53c32f666897f9#7f39295b441614ca9dbf44293e53c32f666897f9"
dependencies = [
"schemars",
"serde",
@@ -4147,6 +4221,8 @@ dependencies = [
"async-trait",
"collections",
"dap",
"dotenvy",
"fs",
"futures 0.3.31",
"gpui",
"json_dotpath",
@@ -4155,6 +4231,7 @@ dependencies = [
"paths",
"serde",
"serde_json",
"shlex",
"task",
"util",
"workspace-hack",
@@ -4308,6 +4385,7 @@ version = "0.1.0"
dependencies = [
"alacritty_terminal",
"anyhow",
"bitflags 2.9.0",
"client",
"collections",
"command_palette_hooks",
@@ -4320,11 +4398,15 @@ dependencies = [
"futures 0.3.31",
"fuzzy",
"gpui",
"hex",
"indoc",
"itertools 0.14.0",
"language",
"log",
"menu",
"notifications",
"parking_lot",
"parse_int",
"paths",
"picker",
"pretty_assertions",
@@ -4340,6 +4422,7 @@ dependencies = [
"tasks_ui",
"telemetry",
"terminal_view",
"text",
"theme",
"tree-sitter",
"tree-sitter-go",
@@ -4447,6 +4530,27 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "derive_more"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"unicode-xid",
]
[[package]]
name = "derive_refineable"
version = "0.1.0"
@@ -4673,12 +4777,6 @@ dependencies = [
"syn 2.0.101",
]
[[package]]
name = "dotenv"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
[[package]]
name = "dotenvy"
version = "0.15.7"
@@ -4811,6 +4909,7 @@ dependencies = [
"pretty_assertions",
"project",
"rand 0.8.5",
"regex",
"release_channel",
"rpc",
"schemars",
@@ -4831,6 +4930,7 @@ dependencies = [
"tree-sitter-python",
"tree-sitter-rust",
"tree-sitter-typescript",
"tree-sitter-yaml",
"ui",
"unicode-script",
"unicode-segmentation",
@@ -5111,7 +5211,7 @@ dependencies = [
"collections",
"debug_adapter_extension",
"dirs 4.0.0",
"dotenv",
"dotenvy",
"env_logger 0.11.8",
"extension",
"fs",
@@ -5187,6 +5287,16 @@ dependencies = [
"libc",
]
[[package]]
name = "explorer_command_injector"
version = "0.1.0"
dependencies = [
"windows 0.61.1",
"windows-core 0.61.0",
"windows-registry 0.5.1",
"workspace-hack",
]
[[package]]
name = "exr"
version = "1.73.0"
@@ -6139,7 +6249,7 @@ dependencies = [
"askpass",
"async-trait",
"collections",
"derive_more",
"derive_more 0.99.19",
"futures 0.3.31",
"git2",
"gpui",
@@ -7156,7 +7266,7 @@ dependencies = [
"core-video",
"cosmic-text",
"ctor",
"derive_more",
"derive_more 0.99.19",
"embed-resource",
"env_logger 0.11.8",
"etagere",
@@ -7702,7 +7812,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bytes 1.10.1",
"derive_more",
"derive_more 0.99.19",
"futures 0.3.31",
"http 1.3.1",
"log",
@@ -8140,7 +8250,7 @@ dependencies = [
"async-trait",
"cargo_metadata",
"collections",
"derive_more",
"derive_more 0.99.19",
"extension",
"fs",
"futures 0.3.31",
@@ -8844,6 +8954,7 @@ dependencies = [
"http_client",
"imara-diff",
"indoc",
"inventory",
"itertools 0.14.0",
"log",
"lsp",
@@ -8898,6 +9009,7 @@ dependencies = [
"gpui",
"language",
"lsp",
"project",
"serde",
"serde_json",
"util",
@@ -8942,8 +9054,10 @@ dependencies = [
"aws-credential-types",
"aws_http_client",
"bedrock",
"chrono",
"client",
"collections",
"component",
"copilot",
"credentials_provider",
"deepseek",
@@ -8982,6 +9096,7 @@ dependencies = [
"util",
"vercel",
"workspace-hack",
"x_ai",
"zed_llm_client",
]
@@ -9014,12 +9129,12 @@ dependencies = [
"collections",
"copilot",
"editor",
"feature_flags",
"futures 0.3.31",
"gpui",
"itertools 0.14.0",
"language",
"lsp",
"picker",
"project",
"release_channel",
"serde_json",
@@ -9237,7 +9352,7 @@ dependencies = [
[[package]]
name = "libwebrtc"
version = "0.3.10"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"cxx",
"jni",
@@ -9317,7 +9432,7 @@ checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
[[package]]
name = "livekit"
version = "0.7.8"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"chrono",
"futures-util",
@@ -9340,7 +9455,7 @@ dependencies = [
[[package]]
name = "livekit-api"
version = "0.4.2"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"futures-util",
"http 0.2.12",
@@ -9364,7 +9479,7 @@ dependencies = [
[[package]]
name = "livekit-protocol"
version = "0.3.9"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"futures-util",
"livekit-runtime",
@@ -9381,7 +9496,7 @@ dependencies = [
[[package]]
name = "livekit-runtime"
version = "0.4.0"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"tokio",
"tokio-stream",
@@ -9574,12 +9689,11 @@ dependencies = [
[[package]]
name = "lsp-types"
version = "0.95.1"
source = "git+https://github.com/zed-industries/lsp-types?rev=c9c189f1c5dd53c624a419ce35bc77ad6a908d18#c9c189f1c5dd53c624a419ce35bc77ad6a908d18"
source = "git+https://github.com/zed-industries/lsp-types?rev=6add7052b598ea1f40f7e8913622c3958b009b60#6add7052b598ea1f40f7e8913622c3958b009b60"
dependencies = [
"bitflags 1.3.2",
"serde",
"serde_json",
"serde_repr",
"url",
]
@@ -10226,6 +10340,18 @@ dependencies = [
"jni-sys",
]
[[package]]
name = "net"
version = "0.1.0"
dependencies = [
"anyhow",
"async-io",
"smol",
"tempfile",
"windows 0.61.1",
"workspace-hack",
]
[[package]]
name = "new_debug_unreachable"
version = "1.0.6"
@@ -11179,6 +11305,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parse_int"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c464266693329dd5a8715098c7f86e6c5fd5d985018b8318f53d9c6c2b21a31"
dependencies = [
"num-traits",
]
[[package]]
name = "partial-json-fixer"
version = "0.5.3"
@@ -11331,14 +11466,6 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]]
name = "perplexity"
version = "0.1.0"
dependencies = [
"serde",
"zed_extension_api 0.6.0",
]
[[package]]
name = "pest"
version = "2.8.0"
@@ -12230,6 +12357,7 @@ dependencies = [
"anyhow",
"askpass",
"async-trait",
"base64 0.22.1",
"buffer_diff",
"circular-buffer",
"client",
@@ -12255,6 +12383,7 @@ dependencies = [
"language",
"log",
"lsp",
"markdown",
"node_runtime",
"parking_lot",
"pathdiff",
@@ -12274,6 +12403,7 @@ dependencies = [
"sha2",
"shellexpand 2.1.2",
"shlex",
"smallvec",
"smol",
"snippet",
"snippet_provider",
@@ -12529,6 +12659,7 @@ dependencies = [
"prost 0.9.0",
"prost-build 0.9.0",
"serde",
"typed-path",
"workspace-hack",
]
@@ -13192,6 +13323,7 @@ dependencies = [
"fs",
"futures 0.3.31",
"git",
"git2",
"git_hosting_providers",
"gpui",
"gpui_tokio",
@@ -14006,7 +14138,7 @@ dependencies = [
[[package]]
name = "scap"
version = "0.0.8"
source = "git+https://github.com/zed-industries/scap?rev=08f0a01417505cc0990b9931a37e5120db92e0d0#08f0a01417505cc0990b9931a37e5120db92e0d0"
source = "git+https://github.com/zed-industries/scap?rev=270538dc780f5240723233ff901e1054641ed318#270538dc780f5240723233ff901e1054641ed318"
dependencies = [
"anyhow",
"cocoa 0.25.0",
@@ -14049,22 +14181,25 @@ dependencies = [
[[package]]
name = "schemars"
version = "0.8.22"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615"
checksum = "fe8c9d1c68d67dd9f97ecbc6f932b60eb289c5dbddd8aa1405484a8fd2fcd984"
dependencies = [
"chrono",
"dyn-clone",
"indexmap",
"ref-cast",
"schemars_derive",
"semver",
"serde",
"serde_json",
]
[[package]]
name = "schemars_derive"
version = "0.8.22"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d"
checksum = "6ca9fcb757952f8e8629b9ab066fc62da523c46c2b247b1708a3be06dd82530b"
dependencies = [
"proc-macro2",
"quote",
@@ -14551,29 +14686,46 @@ dependencies = [
"serde_json",
"serde_json_lenient",
"smallvec",
"streaming-iterator",
"tree-sitter",
"tree-sitter-json",
"unindent",
"util",
"workspace-hack",
"zlog",
]
[[package]]
name = "settings_ui"
version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"command_palette",
"command_palette_hooks",
"component",
"db",
"editor",
"feature_flags",
"fs",
"fuzzy",
"gpui",
"language",
"log",
"menu",
"notifications",
"paths",
"project",
"schemars",
"search",
"serde",
"serde_json",
"settings",
"telemetry",
"theme",
"tree-sitter-json",
"tree-sitter-rust",
"ui",
"ui_input",
"util",
"workspace",
"workspace-hack",
@@ -15523,6 +15675,18 @@ version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0193cc4331cfd2f3d2011ef287590868599a2f33c3e69bc22c1a3d3acf9e02fb"
[[package]]
name = "svg_preview"
version = "0.1.0"
dependencies = [
"editor",
"file_icons",
"gpui",
"ui",
"workspace",
"workspace-hack",
]
[[package]]
name = "svgtypes"
version = "0.15.3"
@@ -15989,11 +16153,12 @@ version = "0.1.0"
dependencies = [
"anyhow",
"collections",
"derive_more",
"derive_more 0.99.19",
"fs",
"futures 0.3.31",
"gpui",
"indexmap",
"inventory",
"log",
"palette",
"parking_lot",
@@ -16034,7 +16199,6 @@ dependencies = [
"indexmap",
"log",
"palette",
"rust-embed",
"serde",
"serde_json",
"serde_json_lenient",
@@ -16288,6 +16452,7 @@ dependencies = [
"schemars",
"serde",
"settings",
"settings_ui",
"smallvec",
"story",
"telemetry",
@@ -16865,8 +17030,7 @@ dependencies = [
[[package]]
name = "tree-sitter-python"
version = "0.23.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d065aaa27f3aaceaf60c1f0e0ac09e1cb9eb8ed28e7bcdaa52129cffc7f4b04"
source = "git+https://github.com/zed-industries/tree-sitter-python?rev=218fcbf3fda3d029225f3dec005cb497d111b35e#218fcbf3fda3d029225f3dec005cb497d111b35e"
dependencies = [
"cc",
"tree-sitter-language",
@@ -17005,6 +17169,12 @@ dependencies = [
"utf-8",
]
[[package]]
name = "typed-path"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c462d18470a2857aa657d338af5fa67170bb48bcc80a296710ce3b0802a32566"
[[package]]
name = "typeid"
version = "1.0.3"
@@ -17318,6 +17488,7 @@ dependencies = [
"rand 0.8.5",
"regex",
"rust-embed",
"schemars",
"serde",
"serde_json",
"serde_json_lenient",
@@ -18282,7 +18453,7 @@ dependencies = [
[[package]]
name = "webrtc-sys"
version = "0.3.7"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"cc",
"cxx",
@@ -18295,7 +18466,7 @@ dependencies = [
[[package]]
name = "webrtc-sys-build"
version = "0.3.6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=80bb8f4c9112789f7c24cc98d8423010977806a6#80bb8f4c9112789f7c24cc98d8423010977806a6"
source = "git+https://github.com/zed-industries/livekit-rust-sdks?rev=d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4#d2eade7a6b15d6dbdb38ba12a1ff7bf07fcebba4"
dependencies = [
"fs2",
"regex",
@@ -18327,7 +18498,6 @@ dependencies = [
"language",
"picker",
"project",
"schemars",
"serde",
"settings",
"telemetry",
@@ -19522,6 +19692,7 @@ dependencies = [
"rustix 1.0.7",
"rustls 0.23.26",
"rustls-webpki 0.103.1",
"schemars",
"scopeguard",
"sea-orm",
"sea-query-binder",
@@ -19674,6 +19845,17 @@ version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
[[package]]
name = "x_ai"
version = "0.1.0"
dependencies = [
"anyhow",
"schemars",
"serde",
"strum 0.27.1",
"workspace-hack",
]
[[package]]
name = "xattr"
version = "0.2.3"
@@ -19915,10 +20097,11 @@ dependencies = [
[[package]]
name = "zed"
version = "0.194.0"
version = "0.197.0"
dependencies = [
"activity_indicator",
"agent",
"agent_servers",
"agent_settings",
"agent_ui",
"anyhow",
@@ -20020,6 +20203,7 @@ dependencies = [
"snippet_provider",
"snippets_ui",
"supermaven",
"svg_preview",
"sysinfo",
"tab_switcher",
"task",
@@ -20112,9 +20296,9 @@ dependencies = [
[[package]]
name = "zed_llm_client"
version = "0.8.4"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de7d9523255f4e00ee3d0918e5407bd252d798a4a8e71f6d37f23317a1588203"
checksum = "6607f74dee2a18a9ce0f091844944a0e59881359ab62e0768fb0618f55d4c1dc"
dependencies = [
"anyhow",
"serde",

View File

@@ -2,9 +2,11 @@
resolver = "2"
members = [
"crates/activity_indicator",
"crates/acp",
"crates/agent_ui",
"crates/agent",
"crates/agent_settings",
"crates/agent_servers",
"crates/anthropic",
"crates/askpass",
"crates/assets",
@@ -45,6 +47,7 @@ members = [
"crates/diagnostics",
"crates/docs_preprocessor",
"crates/editor",
"crates/explorer_command_injector",
"crates/eval",
"crates/extension",
"crates/extension_api",
@@ -95,9 +98,11 @@ members = [
"crates/markdown_preview",
"crates/media",
"crates/menu",
"crates/svg_preview",
"crates/migrator",
"crates/mistral",
"crates/multi_buffer",
"crates/net",
"crates/node_runtime",
"crates/notifications",
"crates/ollama",
@@ -174,6 +179,7 @@ members = [
"crates/welcome",
"crates/workspace",
"crates/worktree",
"crates/x_ai",
"crates/zed",
"crates/zed_actions",
"crates/zeta",
@@ -187,7 +193,6 @@ members = [
"extensions/emmet",
"extensions/glsl",
"extensions/html",
"extensions/perplexity",
"extensions/proto",
"extensions/ruff",
"extensions/slash-commands-example",
@@ -214,10 +219,12 @@ edition = "2024"
# Workspace member crates
#
activity_indicator = { path = "crates/activity_indicator" }
acp = { path = "crates/acp" }
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" }
anthropic = { path = "crates/anthropic" }
askpass = { path = "crates/askpass" }
@@ -304,11 +311,13 @@ 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" }
net = { path = "crates/net" }
node_runtime = { path = "crates/node_runtime" }
notifications = { path = "crates/notifications" }
ollama = { path = "crates/ollama" }
@@ -386,6 +395,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 +406,7 @@ zlog_settings = { path = "crates/zlog_settings" }
# External crates
#
agentic-coding-protocol = { version = "0.0.9" }
aho-corasick = "1.1"
alacritty_terminal = { git = "https://github.com/zed-industries/alacritty.git", branch = "add-hush-login-flag" }
any_vec = "0.14"
@@ -423,9 +434,9 @@ aws-smithy-runtime-api = { version = "1.7.4", features = ["http-1x", "client"] }
aws-smithy-types = { version = "1.3.0", features = ["http-body-1-x"] }
base64 = "0.22"
bitflags = "2.6.0"
blade-graphics = { git = "https://github.com/kvark/blade", rev = "e0ec4e720957edd51b945b64dd85605ea54bcfe5" }
blade-macros = { git = "https://github.com/kvark/blade", rev = "e0ec4e720957edd51b945b64dd85605ea54bcfe5" }
blade-util = { git = "https://github.com/kvark/blade", rev = "e0ec4e720957edd51b945b64dd85605ea54bcfe5" }
blade-graphics = { git = "https://github.com/kvark/blade", rev = "416375211bb0b5826b3584dccdb6a43369e499ad" }
blade-macros = { git = "https://github.com/kvark/blade", rev = "416375211bb0b5826b3584dccdb6a43369e499ad" }
blade-util = { git = "https://github.com/kvark/blade", rev = "416375211bb0b5826b3584dccdb6a43369e499ad" }
blake3 = "1.5.3"
bytes = "1.0"
cargo_metadata = "0.19"
@@ -442,12 +453,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"
@@ -478,18 +489,18 @@ json_dotpath = "1.1"
jsonschema = "0.30.0"
jsonwebtoken = "9.3"
jupyter-protocol = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734" }
jupyter-websocket-client = { git = "https://github.com/ConradIrwin/runtimed" ,rev = "7130c804216b6914355d15d0b91ea91f6babd734" }
jupyter-websocket-client = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734" }
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 = "6add7052b598ea1f40f7e8913622c3958b009b60" }
markup5ever_rcdom = "0.3.0"
metal = "0.29"
moka = { version = "0.12.10", features = ["sync"] }
naga = { version = "25.0", features = ["wgsl-in"] }
nanoid = "0.4"
nbformat = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734" }
nbformat = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734" }
nix = "0.29"
num-format = "0.4.4"
objc = "0.2"
@@ -498,6 +509,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" }
@@ -529,7 +541,7 @@ reqwest = { git = "https://github.com/zed-industries/reqwest.git", rev = "951c77
"stream",
] }
rsa = "0.9.6"
runtimelib = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734", default-features = false, features = [
runtimelib = { git = "https://github.com/ConradIrwin/runtimed", rev = "7130c804216b6914355d15d0b91ea91f6babd734", default-features = false, features = [
"async-dispatcher-runtime",
] }
rust-embed = { version = "8.4", features = ["include-exclude"] }
@@ -537,8 +549,9 @@ 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"] }
# When updating scap rev, also update it in .config/hakari.toml
scap = { git = "https://github.com/zed-industries/scap", rev = "270538dc780f5240723233ff901e1054641ed318", default-features = false }
schemars = { version = "1.0", features = ["indexmap2"] }
semver = "1.0"
serde = { version = "1.0", features = ["derive", "rc"] }
serde_derive = { version = "1.0", features = ["deserialize_in_place"] }
@@ -595,7 +608,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 +635,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 +673,7 @@ features = [
"Win32_Graphics_Gdi",
"Win32_Graphics_Imaging",
"Win32_Graphics_Imaging_D2D",
"Win32_Networking_WinSock",
"Win32_Security",
"Win32_Security_Credentials",
"Win32_Storage_FileSystem",

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 @@
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Google Gemini</title><path d="M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81"/></svg>

After

Width:  |  Height:  |  Size: 402 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,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,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"
}
},
@@ -267,6 +268,14 @@
"ctrl-alt-t": "agent::NewThread"
}
},
{
"context": "AgentPanel && acp_thread",
"use_key_equivalents": true,
"bindings": {
"ctrl-n": "agent::NewAcpThread",
"ctrl-alt-t": "agent::NewThread"
}
},
{
"context": "MessageEditor > Editor",
"bindings": {
@@ -305,6 +314,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": {
@@ -456,8 +475,8 @@
"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 +509,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 +575,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 +623,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"
}
},
{
@@ -686,6 +728,13 @@
"pagedown": "editor::ContextMenuLast"
}
},
{
"context": "Editor && showing_signature_help && !showing_completions",
"bindings": {
"up": "editor::SignatureHelpPrevious",
"down": "editor::SignatureHelpNext"
}
},
// Custom bindings
{
"bindings": {
@@ -807,6 +856,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",
@@ -904,7 +954,9 @@
"context": "BreakpointList",
"bindings": {
"space": "debugger::ToggleEnableBreakpoint",
"backspace": "debugger::UnsetBreakpoint"
"backspace": "debugger::UnsetBreakpoint",
"left": "debugger::PreviousBreakpointProperty",
"right": "debugger::NextBreakpointProperty"
}
},
{
@@ -947,6 +999,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 +1103,47 @@
"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"
}
},
{
"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"
}
@@ -308,6 +309,14 @@
"cmd-alt-t": "agent::NewThread"
}
},
{
"context": "AgentPanel && acp_thread",
"use_key_equivalents": true,
"bindings": {
"cmd-n": "agent::NewAcpThread",
"cmd-alt-t": "agent::NewThread"
}
},
{
"context": "MessageEditor > Editor",
"use_key_equivalents": true,
@@ -356,6 +365,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": {
@@ -509,8 +528,8 @@
"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 +563,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 +620,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 +638,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 +677,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"
}
},
{
@@ -749,6 +792,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 +930,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",
@@ -963,7 +1014,9 @@
"context": "BreakpointList",
"bindings": {
"space": "debugger::ToggleEnableBreakpoint",
"backspace": "debugger::UnsetBreakpoint"
"backspace": "debugger::UnsetBreakpoint",
"left": "debugger::PreviousBreakpointProperty",
"right": "debugger::NextBreakpointProperty"
}
},
{
@@ -1045,13 +1098,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 +1204,45 @@
"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-alt-f": "keymap_editor::ToggleKeystrokeSearch",
"cmd-alt-c": "keymap_editor::ToggleConflictFilter"
}
},
{
"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

@@ -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": {

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": {

View File

@@ -189,6 +189,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 +212,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 +241,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 +309,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 +346,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 +364,40 @@
"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",
":": "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 +417,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 +465,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": {
@@ -846,9 +841,29 @@
"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": "GitCommit > Editor && VimControl && vim_mode == normal",
"bindings": {
"ctrl-c": "menu::Cancel",
"escape": "menu::Cancel"
}
},
{
"context": "Editor && edit_prediction",
"bindings": {
@@ -860,14 +875,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": {
@@ -228,7 +228,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 +362,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 +624,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.
@@ -746,8 +755,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 +817,7 @@
"edit_file": true,
"fetch": true,
"list_directory": true,
"project_notifications": true,
"move_path": true,
"now": true,
"find_path": true,
@@ -829,6 +837,7 @@
"diagnostics": true,
"fetch": true,
"list_directory": true,
"project_notifications": true,
"now": true,
"find_path": true,
"read_file": true,
@@ -855,7 +864,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": {
@@ -1118,6 +1135,7 @@
"**/.svn",
"**/.hg",
"**/.jj",
"**/.repo",
"**/CVS",
"**/.DS_Store",
"**/Thumbs.db",
@@ -1140,16 +1158,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 +1308,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 +1366,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 +1378,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 +1609,9 @@
"use_on_type_format": false,
"allow_rewrap": "anywhere",
"soft_wrap": "editor_width",
"completions": {
"words": "disabled"
},
"prettier": {
"allowed": true
}
@@ -1589,6 +1625,9 @@
}
},
"Plain Text": {
"completions": {
"words": "disabled"
},
"allow_rewrap": "anywhere"
},
"Python": {
@@ -1632,6 +1671,10 @@
"allowed": true
}
},
"SystemVerilog": {
"format_on_save": "off",
"use_on_type_format": false
},
"Vue.js": {
"language_servers": ["vue-language-server", "..."],
"prettier": {
@@ -1656,7 +1699,6 @@
// Different settings for specific language models.
"language_models": {
"anthropic": {
"version": "1",
"api_url": "https://api.anthropic.com"
},
"google": {
@@ -1666,7 +1708,6 @@
"api_url": "http://localhost:11434"
},
"openai": {
"version": "1",
"api_url": "https://api.openai.com/v1"
},
"open_router": {
@@ -1784,7 +1825,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 +1860,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",

47
crates/acp/Cargo.toml Normal file
View File

@@ -0,0 +1,47 @@
[package]
name = "acp"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/acp.rs"
doctest = false
[features]
test-support = ["gpui/test-support", "project/test-support"]
gemini = []
[dependencies]
agent_servers.workspace = true
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
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"] }
serde_json.workspace = true
tempfile.workspace = true
util.workspace = true
settings.workspace = true

1
crates/acp/LICENSE-GPL Symbolic link
View File

@@ -0,0 +1 @@
../../LICENSE-GPL

1967
crates/acp/src/acp.rs Normal file

File diff suppressed because it is too large Load Diff

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 {
@@ -442,7 +448,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

@@ -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,27 @@
[package]
name = "agent_servers"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
license = "GPL-3.0-or-later"
[lints]
workspace = true
[lib]
path = "src/agent_servers.rs"
doctest = false
[dependencies]
anyhow.workspace = true
collections.workspace = true
futures.workspace = true
gpui.workspace = true
paths.workspace = true
project.workspace = true
schemars.workspace = true
serde.workspace = true
settings.workspace = true
util.workspace = true
which.workspace = true
workspace-hack.workspace = true

View File

@@ -0,0 +1 @@
../../LICENSE-GPL

View File

@@ -0,0 +1,231 @@
use std::{
path::{Path, PathBuf},
sync::Arc,
};
use anyhow::{Context as _, Result};
use collections::HashMap;
use gpui::{App, AsyncApp, Entity, SharedString};
use project::Project;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsSources, SettingsStore};
use util::{ResultExt, paths};
pub fn init(cx: &mut App) {
AllAgentServersSettings::register(cx);
}
#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug)]
pub struct AllAgentServersSettings {
gemini: Option<AgentServerSettings>,
}
#[derive(Deserialize, Serialize, Clone, JsonSchema, Debug)]
pub struct AgentServerSettings {
#[serde(flatten)]
command: AgentServerCommand,
}
#[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>>,
}
pub struct Gemini;
pub struct AgentServerVersion {
pub current_version: SharedString,
pub supported: bool,
}
pub trait AgentServer: Send {
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;
}
const GEMINI_ACP_ARG: &str = "--experimental-acp";
impl AgentServer for Gemini {
async fn command(
&self,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> Result<AgentServerCommand> {
let custom_command = cx.read_global(|settings: &SettingsStore, _| {
let settings = settings.get::<AllAgentServersSettings>(None);
settings
.gemini
.as_ref()
.map(|gemini_settings| AgentServerCommand {
path: gemini_settings.command.path.clone(),
args: gemini_settings
.command
.args
.iter()
.cloned()
.chain(std::iter::once(GEMINI_ACP_ARG.into()))
.collect(),
env: gemini_settings.command.env.clone(),
})
})?;
if let Some(custom_command) = custom_command {
return Ok(custom_command);
}
if let Some(path) = find_bin_in_path("gemini", project, cx).await {
return Ok(AgentServerCommand {
path,
args: vec![GEMINI_ACP_ARG.into()],
env: None,
});
}
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![GEMINI_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)?.into();
let supported = String::from_utf8(help_output?.stdout)?.contains(GEMINI_ACP_ARG);
Ok(AgentServerVersion {
current_version,
supported,
})
}
}
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
}
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()
}
}
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 value in sources.defaults_and_customizations() {
if value.gemini.is_some() {
settings.gemini = value.gemini.clone();
}
}
Ok(settings)
}
fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
}

View File

@@ -0,0 +1,118 @@
use crate::stdio_agent_server::{StdioAgentServer, find_bin_in_path};
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 Codex;
const ACP_ARG: &str = "acp";
impl StdioAgentServer for Codex {
fn name(&self) -> &'static str {
"Codex"
}
fn empty_state_headline(&self) -> &'static str {
"Welcome to Codex"
}
fn empty_state_message(&self) -> &'static str {
"Ask questions, edit files, run commands.\nBe specific for the best results."
}
fn logo(&self) -> ui::IconName {
ui::IconName::AiOpenAi
}
async fn command(
&self,
project: &Entity<Project>,
cx: &mut AsyncApp,
) -> Result<AgentServerCommand> {
let custom_command = cx.read_global(|settings: &SettingsStore, _| {
let settings = settings.get::<AllAgentServersSettings>(None);
settings
.codex
.as_ref()
.map(|codex_settings| AgentServerCommand {
path: codex_settings.command.path.clone(),
args: codex_settings
.command
.args
.iter()
.cloned()
.chain(std::iter::once(ACP_ARG.into()))
.collect(),
env: codex_settings.command.env.clone(),
})
})?;
if let Some(custom_command) = custom_command {
return Ok(custom_command);
}
if let Some(path) = find_bin_in_path("codex", project, cx).await {
return Ok(AgentServerCommand {
path,
args: vec![ACP_ARG.into()],
env: None,
});
}
todo!()
// let (fs, node_runtime) = project.update(cx, |project, _| {
// (project.fs().clone(), project.node_runtime().cloned())
// })?;
// let node_runtime = node_runtime.context("codex not found on path")?;
// let directory = ::paths::agent_servers_dir().join("codex");
// 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 Codex {} doesn't support the Agentic Coding Protocol (ACP).",
current_version
).into(),
upgrade_message: "Upgrade Codex to Latest".into(),
upgrade_command: "npm install -g @openai/codex@latest".into(),
})
}
}
}

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,8 @@ 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,
}
impl AgentSettings {
@@ -211,7 +214,6 @@ impl AgentSettingsContent {
}
#[derive(Clone, Serialize, Deserialize, JsonSchema, Debug, Default)]
#[schemars(deny_unknown_fields)]
pub struct AgentSettingsContent {
/// Whether the Agent is enabled.
///
@@ -291,6 +293,14 @@ 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>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
@@ -321,29 +331,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 +367,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 +410,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 +451,11 @@ 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,
);
settings
.model_parameters

View File

@@ -13,14 +13,14 @@ 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.workspace = true
agent.workspace = true
agentic-coding-protocol.workspace = true
agent_settings.workspace = true
agent_servers.workspace = true
anyhow.workspace = true
assistant_context.workspace = true
assistant_slash_command.workspace = true
@@ -76,6 +76,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

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

View File

@@ -1,9 +1,7 @@
use crate::context_picker::{ContextPicker, MentionLink};
use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
use crate::message_editor::{extract_message_creases, insert_message_creases};
use crate::ui::{
AddedContext, AgentNotification, AgentNotificationEvent, AnimatedLabel, ContextPill,
};
use crate::ui::{AddedContext, AgentNotification, AgentNotificationEvent, ContextPill};
use crate::{AgentPanel, ModelUsageContext};
use agent::{
ContextStore, LastRestoreCheckpoint, MessageCrease, MessageId, MessageSegment, TextThreadStore,
@@ -19,7 +17,7 @@ use audio::{Audio, Sound};
use collections::{HashMap, HashSet};
use editor::actions::{MoveUp, Paste};
use editor::scroll::Autoscroll;
use editor::{Editor, EditorElement, EditorEvent, EditorStyle, MultiBuffer};
use editor::{Editor, EditorElement, EditorEvent, EditorStyle, MultiBuffer, SelectionEffects};
use gpui::{
AbsoluteLength, Animation, AnimationExt, AnyElement, App, ClickEvent, ClipboardEntry,
ClipboardItem, DefiniteLength, EdgesRefinement, Empty, Entity, EventEmitter, Focusable, Hsla,
@@ -47,8 +45,8 @@ use std::time::Duration;
use text::ToPoint;
use theme::ThemeSettings;
use ui::{
Disclosure, KeyBinding, PopoverMenuHandle, Scrollbar, ScrollbarState, TextSize, Tooltip,
prelude::*,
Banner, Disclosure, KeyBinding, PopoverMenuHandle, Scrollbar, ScrollbarState, TextSize,
Tooltip, prelude::*,
};
use util::ResultExt as _;
use util::markdown::MarkdownCodeBlock;
@@ -58,6 +56,7 @@ use zed_llm_client::CompletionIntent;
const CODEBLOCK_CONTAINER_GROUP: &str = "codeblock_container";
const EDIT_PREVIOUS_MESSAGE_MIN_LINES: usize = 1;
const RESPONSE_PADDING_X: Pixels = px(19.);
pub struct ActiveThread {
context_store: Entity<ContextStore>,
@@ -204,7 +203,7 @@ pub(crate) fn default_markdown_style(window: &Window, cx: &App) -> MarkdownStyle
MarkdownStyle {
base_text_style: text_style.clone(),
syntax: cx.theme().syntax().clone(),
selection_background_color: cx.theme().players().local().selection,
selection_background_color: cx.theme().colors().element_selection_background,
code_block_overflow_x_scroll: true,
table_overflow_x_scroll: true,
heading_level_styles: Some(HeadingLevelStyles {
@@ -301,7 +300,7 @@ fn tool_use_markdown_style(window: &Window, cx: &mut App) -> MarkdownStyle {
MarkdownStyle {
base_text_style: text_style,
syntax: cx.theme().syntax().clone(),
selection_background_color: cx.theme().players().local().selection,
selection_background_color: cx.theme().colors().element_selection_background,
code_block_overflow_x_scroll: false,
code_block: StyleRefinement {
margin: EdgesRefinement::default(),
@@ -689,9 +688,12 @@ fn open_markdown_link(
})
.context("Could not find matching symbol")?;
editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_anchor_ranges([symbol_range.start..symbol_range.start])
});
editor.change_selections(
SelectionEffects::scroll(Autoscroll::center()),
window,
cx,
|s| s.select_anchor_ranges([symbol_range.start..symbol_range.start]),
);
anyhow::Ok(())
})
})
@@ -708,10 +710,15 @@ fn open_markdown_link(
.downcast::<Editor>()
.context("Item is not an editor")?;
active_editor.update_in(cx, |editor, window, cx| {
editor.change_selections(Some(Autoscroll::center()), window, cx, |s| {
s.select_ranges([Point::new(line_range.start as u32, 0)
..Point::new(line_range.start as u32, 0)])
});
editor.change_selections(
SelectionEffects::scroll(Autoscroll::center()),
window,
cx,
|s| {
s.select_ranges([Point::new(line_range.start as u32, 0)
..Point::new(line_range.start as u32, 0)])
},
);
anyhow::Ok(())
})
})
@@ -780,6 +787,15 @@ impl ActiveThread {
.unwrap()
}
});
let workspace_subscription = if let Some(workspace) = workspace.upgrade() {
Some(cx.observe_release(&workspace, |this, _, cx| {
this.dismiss_notifications(cx);
}))
} else {
None
};
let mut this = Self {
language_registry,
thread_store,
@@ -827,6 +843,10 @@ impl ActiveThread {
}
}
if let Some(subscription) = workspace_subscription {
this._subscriptions.push(subscription);
}
this
}
@@ -976,30 +996,57 @@ impl ActiveThread {
| ThreadEvent::SummaryChanged => {
self.save_thread(cx);
}
ThreadEvent::Stopped(reason) => match reason {
Ok(StopReason::EndTurn | StopReason::MaxTokens) => {
let used_tools = self.thread.read(cx).used_tools_since_last_user_message();
self.play_notification_sound(window, cx);
self.show_notification(
if used_tools {
"Finished running tools"
} else {
"New message"
},
IconName::ZedAssistant,
window,
cx,
);
ThreadEvent::Stopped(reason) => {
match reason {
Ok(StopReason::EndTurn | StopReason::MaxTokens) => {
let used_tools = self.thread.read(cx).used_tools_since_last_user_message();
self.notify_with_sound(
if used_tools {
"Finished running tools"
} else {
"New message"
},
IconName::ZedAssistant,
window,
cx,
);
}
Ok(StopReason::ToolUse) => {
// Don't notify for intermediate tool use
}
Ok(StopReason::Refusal) => {
self.notify_with_sound(
"Language model refused to respond",
IconName::Warning,
window,
cx,
);
}
Err(error) => {
self.notify_with_sound(
"Agent stopped due to an error",
IconName::Warning,
window,
cx,
);
let error_message = error
.chain()
.map(|err| err.to_string())
.collect::<Vec<_>>()
.join("\n");
self.last_error = Some(ThreadError::Message {
header: "Error interacting with language model".into(),
message: error_message.into(),
});
}
}
_ => {}
},
}
ThreadEvent::ToolConfirmationNeeded => {
self.play_notification_sound(window, cx);
self.show_notification("Waiting for tool confirmation", IconName::Info, window, cx);
self.notify_with_sound("Waiting for tool confirmation", IconName::Info, window, cx);
}
ThreadEvent::ToolUseLimitReached => {
self.play_notification_sound(window, cx);
self.show_notification(
self.notify_with_sound(
"Consecutive tool use limit reached.",
IconName::Warning,
window,
@@ -1017,6 +1064,7 @@ impl ActiveThread {
}
}
ThreadEvent::MessageAdded(message_id) => {
self.clear_last_error();
if let Some(rendered_message) = self.thread.update(cx, |thread, cx| {
thread.message(*message_id).map(|message| {
RenderedMessage::from_segments(
@@ -1033,6 +1081,7 @@ impl ActiveThread {
cx.notify();
}
ThreadEvent::MessageEdited(message_id) => {
self.clear_last_error();
if let Some(index) = self.messages.iter().position(|id| id == message_id) {
if let Some(rendered_message) = self.thread.update(cx, |thread, cx| {
thread.message(*message_id).map(|message| {
@@ -1194,6 +1243,17 @@ impl ActiveThread {
}
}
fn notify_with_sound(
&mut self,
caption: impl Into<SharedString>,
icon: IconName,
window: &mut Window,
cx: &mut Context<ActiveThread>,
) {
self.play_notification_sound(window, cx);
self.show_notification(caption, icon, window, cx);
}
fn pop_up(
&mut self,
icon: IconName,
@@ -1449,6 +1509,7 @@ impl ActiveThread {
&configured_model.model,
cx,
),
thinking_allowed: true,
};
Some(configured_model.model.count_tokens(request, cx))
@@ -1806,7 +1867,7 @@ impl ActiveThread {
.my_3()
.mx_5()
.when(is_generating_stale || message.is_hidden, |this| {
this.child(AnimatedLabel::new("").size(LabelSize::Small))
this.child(LoadingLabel::new("").size(LabelSize::Small))
})
});
@@ -1835,9 +1896,10 @@ impl ActiveThread {
.filter(|(id, _)| *id == message_id)
.map(|(_, state)| state);
let colors = cx.theme().colors();
let editor_bg_color = colors.editor_background;
let panel_bg = colors.panel_background;
let (editor_bg_color, panel_bg) = {
let colors = cx.theme().colors();
(colors.editor_background, colors.panel_background)
};
let open_as_markdown = IconButton::new(("open-as-markdown", ix), IconName::DocumentText)
.icon_size(IconSize::XSmall)
@@ -1862,9 +1924,6 @@ impl ActiveThread {
this.scroll_to_top(cx);
}));
// For all items that should be aligned with the LLM's response.
const RESPONSE_PADDING_X: Pixels = px(19.);
let show_feedback = thread.is_turn_end(ix);
let feedback_container = h_flex()
.group("feedback_container")
@@ -2025,152 +2084,162 @@ impl ActiveThread {
}
});
let styled_message = match message.role {
Role::User => v_flex()
.id(("message-container", ix))
.pt_2()
.pl_2()
.pr_2p5()
.pb_4()
.child(
let styled_message = if message.ui_only {
self.render_ui_notification(message_content, ix, cx)
} else {
match message.role {
Role::User => {
let colors = cx.theme().colors();
v_flex()
.id(("user-message", ix))
.bg(editor_bg_color)
.rounded_lg()
.shadow_md()
.border_1()
.border_color(colors.border)
.hover(|hover| hover.border_color(colors.text_accent.opacity(0.5)))
.id(("message-container", ix))
.pt_2()
.pl_2()
.pr_2p5()
.pb_4()
.child(
v_flex()
.p_2p5()
.gap_1()
.children(message_content)
.when_some(editing_message_state, |this, state| {
let focus_handle = state.editor.focus_handle(cx).clone();
.id(("user-message", ix))
.bg(editor_bg_color)
.rounded_lg()
.shadow_md()
.border_1()
.border_color(colors.border)
.hover(|hover| hover.border_color(colors.text_accent.opacity(0.5)))
.child(
v_flex()
.p_2p5()
.gap_1()
.children(message_content)
.when_some(editing_message_state, |this, state| {
let focus_handle = state.editor.focus_handle(cx).clone();
this.child(
h_flex()
.w_full()
.gap_1()
.justify_between()
.flex_wrap()
.child(
this.child(
h_flex()
.gap_1p5()
.w_full()
.gap_1()
.justify_between()
.flex_wrap()
.child(
div()
.opacity(0.8)
h_flex()
.gap_1p5()
.child(
Icon::new(IconName::Warning)
.size(IconSize::Indicator)
.color(Color::Warning)
div()
.opacity(0.8)
.child(
Icon::new(IconName::Warning)
.size(IconSize::Indicator)
.color(Color::Warning)
),
)
.child(
Label::new("Editing will restart the thread from this point.")
.color(Color::Muted)
.size(LabelSize::XSmall),
),
)
.child(
Label::new("Editing will restart the thread from this point.")
.color(Color::Muted)
.size(LabelSize::XSmall),
),
)
.child(
h_flex()
.gap_0p5()
.child(
IconButton::new(
"cancel-edit-message",
IconName::Close,
)
.shape(ui::IconButtonShape::Square)
.icon_color(Color::Error)
.icon_size(IconSize::Small)
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Cancel Edit",
&menu::Cancel,
&focus_handle,
window,
cx,
h_flex()
.gap_0p5()
.child(
IconButton::new(
"cancel-edit-message",
IconName::Close,
)
}
})
.on_click(cx.listener(Self::handle_cancel_click)),
.shape(ui::IconButtonShape::Square)
.icon_color(Color::Error)
.icon_size(IconSize::Small)
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Cancel Edit",
&menu::Cancel,
&focus_handle,
window,
cx,
)
}
})
.on_click(cx.listener(Self::handle_cancel_click)),
)
.child(
IconButton::new(
"confirm-edit-message",
IconName::Return,
)
.disabled(state.editor.read(cx).is_empty(cx))
.shape(ui::IconButtonShape::Square)
.icon_color(Color::Muted)
.icon_size(IconSize::Small)
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Regenerate",
&menu::Confirm,
&focus_handle,
window,
cx,
)
}
})
.on_click(
cx.listener(Self::handle_regenerate_click),
),
),
)
.child(
IconButton::new(
"confirm-edit-message",
IconName::Return,
)
.disabled(state.editor.read(cx).is_empty(cx))
.shape(ui::IconButtonShape::Square)
.icon_color(Color::Muted)
.icon_size(IconSize::Small)
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Regenerate",
&menu::Confirm,
&focus_handle,
window,
cx,
)
}
})
.on_click(
cx.listener(Self::handle_regenerate_click),
),
),
)
)
}),
}),
)
.on_click(cx.listener({
let message_creases = message.creases.clone();
move |this, _, window, cx| {
if let Some(message_text) =
this.thread.read(cx).message(message_id).and_then(|message| {
message.segments.first().and_then(|segment| {
match segment {
MessageSegment::Text(message_text) => {
Some(Into::<Arc<str>>::into(message_text.as_str()))
}
_ => {
None
}
}
})
})
{
this.start_editing_message(
message_id,
message_text,
&message_creases,
window,
cx,
);
}
}
})),
)
.on_click(cx.listener({
let message_creases = message.creases.clone();
move |this, _, window, cx| {
if let Some(message_text) =
this.thread.read(cx).message(message_id).and_then(|message| {
message.segments.first().and_then(|segment| {
match segment {
MessageSegment::Text(message_text) => {
Some(Into::<Arc<str>>::into(message_text.as_str()))
}
_ => {
None
}
}
})
})
{
this.start_editing_message(
message_id,
message_text,
&message_creases,
window,
cx,
);
}
}
})),
),
Role::Assistant => v_flex()
.id(("message-container", ix))
.px(RESPONSE_PADDING_X)
.gap_2()
.children(message_content)
.when(has_tool_uses, |parent| {
parent.children(tool_uses.into_iter().map(|tool_use| {
self.render_tool_use(tool_use, window, workspace.clone(), cx)
}))
}),
Role::System => div().id(("message-container", ix)).py_1().px_2().child(
v_flex()
.bg(colors.editor_background)
.rounded_sm()
.child(div().p_4().children(message_content)),
),
}
Role::Assistant => v_flex()
.id(("message-container", ix))
.px(RESPONSE_PADDING_X)
.gap_2()
.children(message_content)
.when(has_tool_uses, |parent| {
parent.children(tool_uses.into_iter().map(|tool_use| {
self.render_tool_use(tool_use, window, workspace.clone(), cx)
}))
}),
Role::System => {
let colors = cx.theme().colors();
div().id(("message-container", ix)).py_1().px_2().child(
v_flex()
.bg(colors.editor_background)
.rounded_sm()
.child(div().p_4().children(message_content)),
)
}
}
};
let after_editing_message = self
@@ -2509,6 +2578,26 @@ impl ActiveThread {
.blend(cx.theme().colors().editor_foreground.opacity(0.025))
}
fn render_ui_notification(
&self,
message_content: impl IntoIterator<Item = impl IntoElement>,
ix: usize,
cx: &mut Context<Self>,
) -> Stateful<Div> {
let message = div()
.flex_1()
.min_w_0()
.text_size(TextSize::XSmall.rems(cx))
.text_color(cx.theme().colors().text_muted)
.children(message_content);
div()
.id(("message-container", ix))
.py_1()
.px_2p5()
.child(Banner::new().severity(ui::Severity::Warning).child(message))
}
fn render_message_thinking_segment(
&self,
message_id: MessageId,
@@ -2540,11 +2629,11 @@ impl ActiveThread {
h_flex()
.gap_1p5()
.child(
Icon::new(IconName::LightBulb)
.size(IconSize::XSmall)
Icon::new(IconName::ToolBulb)
.size(IconSize::Small)
.color(Color::Muted),
)
.child(AnimatedLabel::new("Thinking").size(LabelSize::Small)),
.child(LoadingLabel::new("Thinking").size(LabelSize::Small)),
)
.child(
h_flex()
@@ -2954,7 +3043,7 @@ impl ActiveThread {
.overflow_x_scroll()
.child(
Icon::new(tool_use.icon)
.size(IconSize::XSmall)
.size(IconSize::Small)
.color(Color::Muted),
)
.child(
@@ -3113,7 +3202,7 @@ impl ActiveThread {
.border_color(self.tool_card_border_color(cx))
.rounded_b_lg()
.child(
AnimatedLabel::new("Waiting for Confirmation").size(LabelSize::Small)
LoadingLabel::new("Waiting for Confirmation").size(LabelSize::Small)
)
.child(
h_flex()
@@ -3763,9 +3852,9 @@ mod tests {
// Stream response to user message
thread.update(cx, |thread, cx| {
let request =
thread.to_completion_request(model.clone(), CompletionIntent::UserPrompt, cx);
thread.stream_completion(request, model, cx.active_window(), cx)
let intent = CompletionIntent::UserPrompt;
let request = thread.to_completion_request(model.clone(), intent, cx);
thread.stream_completion(request, model, intent, cx.active_window(), cx)
});
// Follow the agent
cx.update(|window, cx| {

View File

@@ -16,16 +16,19 @@ use gpui::{
Focusable, ScrollHandle, Subscription, Task, Transformation, WeakEntity, percentage,
};
use language::LanguageRegistry;
use language_model::{LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry};
use language_model::{
LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry, ZED_CLOUD_PROVIDER_ID,
};
use notifications::status_toast::{StatusToast, ToastIcon};
use project::{
context_server_store::{ContextServerConfiguration, ContextServerStatus, ContextServerStore},
project_settings::{ContextServerSettings, ProjectSettings},
};
use proto::Plan;
use settings::{Settings, update_settings_file};
use ui::{
ContextMenu, Disclosure, ElevationIndex, Indicator, PopoverMenu, Scrollbar, ScrollbarState,
Switch, SwitchColor, Tooltip, prelude::*,
Chip, ContextMenu, Disclosure, Divider, DividerColor, ElevationIndex, Indicator, PopoverMenu,
Scrollbar, ScrollbarState, Switch, SwitchColor, Tooltip, prelude::*,
};
use util::ResultExt as _;
use workspace::Workspace;
@@ -86,6 +89,14 @@ impl AgentConfiguration {
let scroll_handle = ScrollHandle::new();
let scrollbar_state = ScrollbarState::new(scroll_handle.clone());
let mut expanded_provider_configurations = HashMap::default();
if LanguageModelRegistry::read_global(cx)
.provider(&ZED_CLOUD_PROVIDER_ID)
.map_or(false, |cloud_provider| cloud_provider.must_accept_terms(cx))
{
expanded_provider_configurations.insert(ZED_CLOUD_PROVIDER_ID, true);
}
let mut this = Self {
fs,
language_registry,
@@ -94,7 +105,7 @@ impl AgentConfiguration {
configuration_views_by_provider: HashMap::default(),
context_server_store,
expanded_context_server_tools: HashMap::default(),
expanded_provider_configurations: HashMap::default(),
expanded_provider_configurations,
tools,
_registry_subscription: registry_subscription,
scroll_handle,
@@ -161,20 +172,39 @@ impl AgentConfiguration {
.copied()
.unwrap_or(false);
let is_zed_provider = provider.id() == ZED_CLOUD_PROVIDER_ID;
let current_plan = if is_zed_provider {
self.workspace
.upgrade()
.and_then(|workspace| workspace.read(cx).user_store().read(cx).current_plan())
} else {
None
};
v_flex()
.py_2()
.gap_1p5()
.border_t_1()
.border_color(cx.theme().colors().border.opacity(0.6))
.when(is_expanded, |this| this.mb_2())
.child(
div()
.opacity(0.6)
.px_2()
.child(Divider::horizontal().color(DividerColor::Border)),
)
.child(
h_flex()
.map(|this| {
if is_expanded {
this.mt_2().mb_1()
} else {
this.my_2()
}
})
.w_full()
.gap_1()
.justify_between()
.child(
h_flex()
.id(provider_id_string.clone())
.cursor_pointer()
.px_2()
.py_0p5()
.w_full()
.justify_between()
@@ -188,14 +218,31 @@ impl AgentConfiguration {
.size(IconSize::Small)
.color(Color::Muted),
)
.child(Label::new(provider_name.clone()).size(LabelSize::Large))
.when(
provider.is_authenticated(cx) && !is_expanded,
|parent| {
parent.child(
Icon::new(IconName::Check).color(Color::Success),
.child(
h_flex()
.gap_1()
.child(
Label::new(provider_name.clone())
.size(LabelSize::Large),
)
},
.map(|this| {
if is_zed_provider {
this.gap_2().child(
self.render_zed_plan_info(current_plan, cx),
)
} else {
this.when(
provider.is_authenticated(cx)
&& !is_expanded,
|parent| {
parent.child(
Icon::new(IconName::Check)
.color(Color::Success),
)
},
)
}
}),
),
)
.child(
@@ -237,12 +284,16 @@ impl AgentConfiguration {
)
}),
)
.when(is_expanded, |parent| match configuration_view {
Some(configuration_view) => parent.child(configuration_view),
None => parent.child(Label::new(format!(
"No configuration view for {provider_name}",
))),
})
.child(
div()
.px_2()
.when(is_expanded, |parent| match configuration_view {
Some(configuration_view) => parent.child(configuration_view),
None => parent.child(Label::new(format!(
"No configuration view for {provider_name}",
))),
}),
)
}
fn render_provider_configuration_section(
@@ -252,12 +303,11 @@ impl AgentConfiguration {
let providers = LanguageModelRegistry::read_global(cx).providers();
v_flex()
.p(DynamicSpacing::Base16.rems(cx))
.pr(DynamicSpacing::Base20.rems(cx))
.border_b_1()
.border_color(cx.theme().colors().border)
.child(
v_flex()
.p(DynamicSpacing::Base16.rems(cx))
.pr(DynamicSpacing::Base20.rems(cx))
.pb_0()
.mb_2p5()
.gap_0p5()
.child(Headline::new("LLM Providers"))
@@ -266,10 +316,15 @@ impl AgentConfiguration {
.color(Color::Muted),
),
)
.children(
providers
.into_iter()
.map(|provider| self.render_provider_configuration_block(&provider, cx)),
.child(
div()
.pl(DynamicSpacing::Base08.rems(cx))
.pr(DynamicSpacing::Base20.rems(cx))
.children(
providers.into_iter().map(|provider| {
self.render_provider_configuration_block(&provider, cx)
}),
),
)
}
@@ -403,12 +458,43 @@ impl AgentConfiguration {
.child(self.render_sound_notification(cx))
}
fn render_zed_plan_info(&self, plan: Option<Plan>, cx: &mut Context<Self>) -> impl IntoElement {
if let Some(plan) = plan {
let free_chip_bg = cx
.theme()
.colors()
.editor_background
.opacity(0.5)
.blend(cx.theme().colors().text_accent.opacity(0.05));
let pro_chip_bg = cx
.theme()
.colors()
.editor_background
.opacity(0.5)
.blend(cx.theme().colors().text_accent.opacity(0.2));
let (plan_name, label_color, bg_color) = match plan {
Plan::Free => ("Free", Color::Default, free_chip_bg),
Plan::ZedProTrial => ("Pro Trial", Color::Accent, pro_chip_bg),
Plan::ZedPro => ("Pro", Color::Accent, pro_chip_bg),
};
Chip::new(plan_name.to_string())
.bg_color(bg_color)
.label_color(label_color)
.into_any_element()
} else {
div().into_any_element()
}
}
fn render_context_servers_section(
&mut self,
window: &mut Window,
cx: &mut Context<Self>,
) -> impl IntoElement {
let context_server_ids = self.context_server_store.read(cx).all_server_ids().clone();
let context_server_ids = self.context_server_store.read(cx).configured_server_ids();
v_flex()
.p(DynamicSpacing::Base16.rems(cx))
@@ -463,6 +549,7 @@ impl AgentConfiguration {
category_filter: Some(
ExtensionCategoryFilter::ContextServers,
),
id: None,
}
.boxed_clone(),
cx,

View File

@@ -180,7 +180,7 @@ impl ConfigurationSource {
}
fn context_server_input(existing: Option<(ContextServerId, ContextServerCommand)>) -> String {
let (name, path, args, env) = match existing {
let (name, command, args, env) = match existing {
Some((id, cmd)) => {
let args = serde_json::to_string(&cmd.args).unwrap();
let env = serde_json::to_string(&cmd.env.unwrap_or_default()).unwrap();
@@ -198,14 +198,12 @@ fn context_server_input(existing: Option<(ContextServerId, ContextServerCommand)
r#"{{
/// The name of your MCP server
"{name}": {{
"command": {{
/// The path to the executable
"path": "{path}",
/// The arguments to pass to the executable
"args": {args},
/// The environment variables to set for the executable
"env": {env}
}}
/// The command which runs the MCP server
"command": "{command}",
/// The arguments to pass to the MCP server
"args": {args},
/// The environment variables to set
"env": {env}
}}
}}"#
)
@@ -381,6 +379,14 @@ impl ConfigureContextServerModal {
};
self.state = State::Waiting;
let existing_server = self.context_server_store.read(cx).get_running_server(&id);
if existing_server.is_some() {
self.context_server_store.update(cx, |store, cx| {
store.stop_server(&id, cx).log_err();
});
}
let wait_for_context_server_task =
wait_for_context_server(&self.context_server_store, id.clone(), cx);
cx.spawn({
@@ -401,13 +407,21 @@ impl ConfigureContextServerModal {
})
.detach();
// When we write the settings to the file, the context server will be restarted.
workspace.update(cx, |workspace, cx| {
let fs = workspace.app_state().fs.clone();
update_settings_file::<ProjectSettings>(fs.clone(), cx, |project_settings, _| {
project_settings.context_servers.insert(id.0, settings);
let settings_changed =
ProjectSettings::get_global(cx).context_servers.get(&id.0) != Some(&settings);
if settings_changed {
// When we write the settings to the file, the context server will be restarted.
workspace.update(cx, |workspace, cx| {
let fs = workspace.app_state().fs.clone();
update_settings_file::<ProjectSettings>(fs.clone(), cx, |project_settings, _| {
project_settings.context_servers.insert(id.0, settings);
});
});
});
} else if let Some(existing_server) = existing_server {
self.context_server_store
.update(cx, |store, cx| store.start_server(existing_server, cx));
}
}
fn cancel(&mut self, _: &menu::Cancel, cx: &mut Context<Self>) {
@@ -439,8 +453,7 @@ fn parse_input(text: &str) -> Result<(ContextServerId, ContextServerCommand)> {
let object = value.as_object().context("Expected object")?;
anyhow::ensure!(object.len() == 1, "Expected exactly one key-value pair");
let (context_server_name, value) = object.into_iter().next().unwrap();
let command = value.get("command").context("Expected command")?;
let command: ContextServerCommand = serde_json::from_value(command.clone())?;
let command: ContextServerCommand = serde_json::from_value(value.clone())?;
Ok((ContextServerId(context_server_name.clone().into()), command))
}
@@ -727,7 +740,9 @@ fn wait_for_context_server(
});
cx.spawn(async move |_cx| {
let result = rx.await.unwrap();
let result = rx
.await
.map_err(|_| Arc::from("Context server store was dropped"))?;
drop(subscription);
result
})
@@ -748,7 +763,7 @@ pub(crate) fn default_markdown_style(window: &Window, cx: &App) -> MarkdownStyle
MarkdownStyle {
base_text_style: text_style.clone(),
selection_background_color: cx.theme().players().local().selection,
selection_background_color: colors.element_selection_background,
link: TextStyleRefinement {
background_color: Some(colors.editor_foreground.opacity(0.025)),
underline: Some(UnderlineStyle {

View File

@@ -1,11 +1,14 @@
use crate::{Keep, KeepAll, OpenAgentDiff, Reject, RejectAll};
use agent::{Thread, ThreadEvent};
use acp::{AcpThread, AcpThreadEvent};
use agent::{Thread, ThreadEvent, ThreadSummary};
use agent_settings::AgentSettings;
use anyhow::Result;
use assistant_tool::ActionLog;
use buffer_diff::DiffHunkStatus;
use collections::{HashMap, HashSet};
use editor::{
Direction, Editor, EditorEvent, EditorSettings, MultiBuffer, MultiBufferSnapshot, ToPoint,
Direction, Editor, EditorEvent, EditorSettings, MultiBuffer, MultiBufferSnapshot,
SelectionEffects, ToPoint,
actions::{GoToHunk, GoToPreviousHunk},
scroll::Autoscroll,
};
@@ -40,16 +43,108 @@ use zed_actions::assistant::ToggleFocus;
pub struct AgentDiffPane {
multibuffer: Entity<MultiBuffer>,
editor: Entity<Editor>,
thread: Entity<Thread>,
thread: AgentDiffThread,
focus_handle: FocusHandle,
workspace: WeakEntity<Workspace>,
title: SharedString,
_subscriptions: Vec<Subscription>,
}
#[derive(PartialEq, Eq, Clone)]
pub enum AgentDiffThread {
Native(Entity<Thread>),
AcpThread(Entity<AcpThread>),
}
impl AgentDiffThread {
fn project(&self, cx: &App) -> Entity<Project> {
match self {
AgentDiffThread::Native(thread) => thread.read(cx).project().clone(),
AgentDiffThread::AcpThread(thread) => thread.read(cx).project().clone(),
}
}
fn action_log(&self, cx: &App) -> Entity<ActionLog> {
match self {
AgentDiffThread::Native(thread) => thread.read(cx).action_log().clone(),
AgentDiffThread::AcpThread(thread) => thread.read(cx).action_log().clone(),
}
}
fn summary(&self, cx: &App) -> ThreadSummary {
match self {
AgentDiffThread::Native(thread) => thread.read(cx).summary().clone(),
AgentDiffThread::AcpThread(thread) => ThreadSummary::Ready(thread.read(cx).title()),
}
}
fn is_generating(&self, cx: &App) -> bool {
match self {
AgentDiffThread::Native(thread) => thread.read(cx).is_generating(),
AgentDiffThread::AcpThread(thread) => {
thread.read(cx).status() == acp::ThreadStatus::Generating
}
}
}
fn has_pending_edit_tool_uses(&self, cx: &App) -> bool {
match self {
AgentDiffThread::Native(thread) => thread.read(cx).has_pending_edit_tool_uses(),
AgentDiffThread::AcpThread(thread) => thread.read(cx).has_pending_edit_tool_calls(),
}
}
fn downgrade(&self) -> WeakAgentDiffThread {
match self {
AgentDiffThread::Native(thread) => WeakAgentDiffThread::Native(thread.downgrade()),
AgentDiffThread::AcpThread(thread) => {
WeakAgentDiffThread::AcpThread(thread.downgrade())
}
}
}
}
impl From<Entity<Thread>> for AgentDiffThread {
fn from(entity: Entity<Thread>) -> Self {
AgentDiffThread::Native(entity)
}
}
impl From<Entity<AcpThread>> for AgentDiffThread {
fn from(entity: Entity<AcpThread>) -> Self {
AgentDiffThread::AcpThread(entity)
}
}
#[derive(PartialEq, Eq, Clone)]
pub enum WeakAgentDiffThread {
Native(WeakEntity<Thread>),
AcpThread(WeakEntity<AcpThread>),
}
impl WeakAgentDiffThread {
pub fn upgrade(&self) -> Option<AgentDiffThread> {
match self {
WeakAgentDiffThread::Native(weak) => weak.upgrade().map(AgentDiffThread::Native),
WeakAgentDiffThread::AcpThread(weak) => weak.upgrade().map(AgentDiffThread::AcpThread),
}
}
}
impl From<WeakEntity<Thread>> for WeakAgentDiffThread {
fn from(entity: WeakEntity<Thread>) -> Self {
WeakAgentDiffThread::Native(entity)
}
}
impl From<WeakEntity<AcpThread>> for WeakAgentDiffThread {
fn from(entity: WeakEntity<AcpThread>) -> Self {
WeakAgentDiffThread::AcpThread(entity)
}
}
impl AgentDiffPane {
pub fn deploy(
thread: Entity<Thread>,
thread: impl Into<AgentDiffThread>,
workspace: WeakEntity<Workspace>,
window: &mut Window,
cx: &mut App,
@@ -60,14 +155,16 @@ impl AgentDiffPane {
}
pub fn deploy_in_workspace(
thread: Entity<Thread>,
thread: impl Into<AgentDiffThread>,
workspace: &mut Workspace,
window: &mut Window,
cx: &mut Context<Workspace>,
) -> Entity<Self> {
let thread = thread.into();
let existing_diff = workspace
.items_of_type::<AgentDiffPane>(cx)
.find(|diff| diff.read(cx).thread == thread);
if let Some(existing_diff) = existing_diff {
workspace.activate_item(&existing_diff, true, true, window, cx);
existing_diff
@@ -80,7 +177,7 @@ impl AgentDiffPane {
}
pub fn new(
thread: Entity<Thread>,
thread: AgentDiffThread,
workspace: WeakEntity<Workspace>,
window: &mut Window,
cx: &mut Context<Self>,
@@ -88,7 +185,7 @@ impl AgentDiffPane {
let focus_handle = cx.focus_handle();
let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
let project = thread.read(cx).project().clone();
let project = thread.project(cx).clone();
let editor = cx.new(|cx| {
let mut editor =
Editor::for_multibuffer(multibuffer.clone(), Some(project.clone()), window, cx);
@@ -99,16 +196,27 @@ impl AgentDiffPane {
editor
});
let action_log = thread.read(cx).action_log().clone();
let action_log = thread.action_log(cx).clone();
let mut this = Self {
_subscriptions: vec![
cx.observe_in(&action_log, window, |this, _action_log, window, cx| {
this.update_excerpts(window, cx)
}),
cx.subscribe(&thread, |this, _thread, event, cx| {
this.handle_thread_event(event, cx)
}),
],
_subscriptions: [
Some(
cx.observe_in(&action_log, window, |this, _action_log, window, cx| {
this.update_excerpts(window, cx)
}),
),
match &thread {
AgentDiffThread::Native(thread) => {
Some(cx.subscribe(&thread, |this, _thread, event, cx| {
this.handle_thread_event(event, cx)
}))
}
AgentDiffThread::AcpThread(_) => None,
},
]
.into_iter()
.flatten()
.collect(),
title: SharedString::default(),
multibuffer,
editor,
@@ -122,8 +230,7 @@ impl AgentDiffPane {
}
fn update_excerpts(&mut self, window: &mut Window, cx: &mut Context<Self>) {
let thread = self.thread.read(cx);
let changed_buffers = thread.action_log().read(cx).changed_buffers(cx);
let changed_buffers = self.thread.action_log(cx).read(cx).changed_buffers(cx);
let mut paths_to_delete = self.multibuffer.read(cx).paths().collect::<HashSet<_>>();
for (buffer, diff_handle) in changed_buffers {
@@ -171,15 +278,9 @@ impl AgentDiffPane {
if let Some(first_hunk) = first_hunk {
let first_hunk_start = first_hunk.multi_buffer_range().start;
editor.change_selections(
Some(Autoscroll::fit()),
window,
cx,
|selections| {
selections
.select_anchor_ranges([first_hunk_start..first_hunk_start]);
},
)
editor.change_selections(Default::default(), window, cx, |selections| {
selections.select_anchor_ranges([first_hunk_start..first_hunk_start]);
})
}
}
@@ -216,7 +317,7 @@ impl AgentDiffPane {
}
fn update_title(&mut self, cx: &mut Context<Self>) {
let new_title = self.thread.read(cx).summary().unwrap_or("Agent Changes");
let new_title = self.thread.summary(cx).unwrap_or("Agent Changes");
if new_title != self.title {
self.title = new_title;
cx.emit(EditorEvent::TitleChanged);
@@ -242,7 +343,7 @@ impl AgentDiffPane {
if let Some(first_hunk) = first_hunk {
let first_hunk_start = first_hunk.multi_buffer_range().start;
editor.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
editor.change_selections(Default::default(), window, cx, |selections| {
selections.select_anchor_ranges([first_hunk_start..first_hunk_start]);
})
}
@@ -280,14 +381,15 @@ impl AgentDiffPane {
fn keep_all(&mut self, _: &KeepAll, _window: &mut Window, cx: &mut Context<Self>) {
self.thread
.update(cx, |thread, cx| thread.keep_all_edits(cx));
.action_log(cx)
.update(cx, |action_log, cx| action_log.keep_all_edits(cx))
}
}
fn keep_edits_in_selection(
editor: &mut Editor,
buffer_snapshot: &MultiBufferSnapshot,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut Context<Editor>,
) {
@@ -302,7 +404,7 @@ fn keep_edits_in_selection(
fn reject_edits_in_selection(
editor: &mut Editor,
buffer_snapshot: &MultiBufferSnapshot,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut Context<Editor>,
) {
@@ -316,7 +418,7 @@ fn reject_edits_in_selection(
fn keep_edits_in_ranges(
editor: &mut Editor,
buffer_snapshot: &MultiBufferSnapshot,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
ranges: Vec<Range<editor::Anchor>>,
window: &mut Window,
cx: &mut Context<Editor>,
@@ -331,8 +433,8 @@ fn keep_edits_in_ranges(
for hunk in &diff_hunks_in_ranges {
let buffer = multibuffer.read(cx).buffer(hunk.buffer_id);
if let Some(buffer) = buffer {
thread.update(cx, |thread, cx| {
thread.keep_edits_in_range(buffer, hunk.buffer_range.clone(), cx)
thread.action_log(cx).update(cx, |action_log, cx| {
action_log.keep_edits_in_range(buffer, hunk.buffer_range.clone(), cx)
});
}
}
@@ -341,7 +443,7 @@ fn keep_edits_in_ranges(
fn reject_edits_in_ranges(
editor: &mut Editor,
buffer_snapshot: &MultiBufferSnapshot,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
ranges: Vec<Range<editor::Anchor>>,
window: &mut Window,
cx: &mut Context<Editor>,
@@ -367,8 +469,9 @@ fn reject_edits_in_ranges(
for (buffer, ranges) in ranges_by_buffer {
thread
.update(cx, |thread, cx| {
thread.reject_edits_in_ranges(buffer, ranges, cx)
.action_log(cx)
.update(cx, |action_log, cx| {
action_log.reject_edits_in_ranges(buffer, ranges, cx)
})
.detach_and_log_err(cx);
}
@@ -416,7 +519,7 @@ fn update_editor_selection(
};
if let Some(target_hunk) = target_hunk {
editor.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
editor.change_selections(Default::default(), window, cx, |selections| {
let next_hunk_start = target_hunk.multi_buffer_range().start;
selections.select_anchor_ranges([next_hunk_start..next_hunk_start]);
})
@@ -466,7 +569,7 @@ impl Item for AgentDiffPane {
}
fn tab_content(&self, params: TabContentParams, _window: &Window, cx: &App) -> AnyElement {
let summary = self.thread.read(cx).summary().unwrap_or("Agent Changes");
let summary = self.thread.summary(cx).unwrap_or("Agent Changes");
Label::new(format!("Review: {}", summary))
.color(if params.selected {
Color::Default
@@ -646,7 +749,7 @@ impl Render for AgentDiffPane {
}
}
fn diff_hunk_controls(thread: &Entity<Thread>) -> editor::RenderDiffHunkControlsFn {
fn diff_hunk_controls(thread: &AgentDiffThread) -> editor::RenderDiffHunkControlsFn {
let thread = thread.clone();
Arc::new(
@@ -681,7 +784,7 @@ fn render_diff_hunk_controls(
hunk_range: Range<editor::Anchor>,
is_created_file: bool,
line_height: Pixels,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
editor: &Entity<Editor>,
window: &mut Window,
cx: &mut App,
@@ -1117,11 +1220,8 @@ impl Render for AgentDiffToolbar {
return Empty.into_any();
};
let has_pending_edit_tool_use = agent_diff
.read(cx)
.thread
.read(cx)
.has_pending_edit_tool_uses();
let has_pending_edit_tool_use =
agent_diff.read(cx).thread.has_pending_edit_tool_uses(cx);
if has_pending_edit_tool_use {
return div().px_2().child(spinner_icon).into_any();
@@ -1192,8 +1292,8 @@ pub enum EditorState {
}
struct WorkspaceThread {
thread: WeakEntity<Thread>,
_thread_subscriptions: [Subscription; 2],
thread: WeakAgentDiffThread,
_thread_subscriptions: (Subscription, Subscription),
singleton_editors: HashMap<WeakEntity<Buffer>, HashMap<WeakEntity<Editor>, Subscription>>,
_settings_subscription: Subscription,
_workspace_subscription: Option<Subscription>,
@@ -1217,23 +1317,23 @@ impl AgentDiff {
pub fn set_active_thread(
workspace: &WeakEntity<Workspace>,
thread: &Entity<Thread>,
thread: impl Into<AgentDiffThread>,
window: &mut Window,
cx: &mut App,
) {
Self::global(cx).update(cx, |this, cx| {
this.register_active_thread_impl(workspace, thread, window, cx);
this.register_active_thread_impl(workspace, thread.into(), window, cx);
});
}
fn register_active_thread_impl(
&mut self,
workspace: &WeakEntity<Workspace>,
thread: &Entity<Thread>,
thread: AgentDiffThread,
window: &mut Window,
cx: &mut Context<Self>,
) {
let action_log = thread.read(cx).action_log().clone();
let action_log = thread.action_log(cx).clone();
let action_log_subscription = cx.observe_in(&action_log, window, {
let workspace = workspace.clone();
@@ -1242,17 +1342,25 @@ impl AgentDiff {
}
});
let thread_subscription = cx.subscribe_in(&thread, window, {
let workspace = workspace.clone();
move |this, _thread, event, window, cx| {
this.handle_thread_event(&workspace, event, window, cx)
}
});
let thread_subscription = match &thread {
AgentDiffThread::Native(thread) => cx.subscribe_in(&thread, window, {
let workspace = workspace.clone();
move |this, _thread, event, window, cx| {
this.handle_native_thread_event(&workspace, event, window, cx)
}
}),
AgentDiffThread::AcpThread(thread) => cx.subscribe_in(&thread, window, {
let workspace = workspace.clone();
move |this, thread, event, window, cx| {
this.handle_acp_thread_event(&workspace, thread, event, window, cx)
}
}),
};
if let Some(workspace_thread) = self.workspace_threads.get_mut(&workspace) {
// replace thread and action log subscription, but keep editors
workspace_thread.thread = thread.downgrade();
workspace_thread._thread_subscriptions = [action_log_subscription, thread_subscription];
workspace_thread._thread_subscriptions = (action_log_subscription, thread_subscription);
self.update_reviewing_editors(&workspace, window, cx);
return;
}
@@ -1277,7 +1385,7 @@ impl AgentDiff {
workspace.clone(),
WorkspaceThread {
thread: thread.downgrade(),
_thread_subscriptions: [action_log_subscription, thread_subscription],
_thread_subscriptions: (action_log_subscription, thread_subscription),
singleton_editors: HashMap::default(),
_settings_subscription: settings_subscription,
_workspace_subscription: workspace_subscription,
@@ -1324,7 +1432,7 @@ impl AgentDiff {
fn register_review_action<T: Action>(
workspace: &mut Workspace,
review: impl Fn(&Entity<Editor>, &Entity<Thread>, &mut Window, &mut App) -> PostReviewState
review: impl Fn(&Entity<Editor>, &AgentDiffThread, &mut Window, &mut App) -> PostReviewState
+ 'static,
this: &Entity<AgentDiff>,
) {
@@ -1343,7 +1451,7 @@ impl AgentDiff {
});
}
fn handle_thread_event(
fn handle_native_thread_event(
&mut self,
workspace: &WeakEntity<Workspace>,
event: &ThreadEvent,
@@ -1384,6 +1492,40 @@ impl AgentDiff {
}
}
fn handle_acp_thread_event(
&mut self,
workspace: &WeakEntity<Workspace>,
thread: &Entity<AcpThread>,
event: &AcpThreadEvent,
window: &mut Window,
cx: &mut Context<Self>,
) {
match event {
AcpThreadEvent::NewEntry => {
if thread
.read(cx)
.entries()
.last()
.and_then(|entry| entry.diff())
.is_some()
{
self.update_reviewing_editors(workspace, window, cx);
}
}
AcpThreadEvent::EntryUpdated(ix) => {
if thread
.read(cx)
.entries()
.get(*ix)
.and_then(|entry| entry.diff())
.is_some()
{
self.update_reviewing_editors(workspace, window, cx);
}
}
}
}
fn handle_workspace_event(
&mut self,
workspace: &Entity<Workspace>,
@@ -1489,7 +1631,7 @@ impl AgentDiff {
return;
};
let action_log = thread.read(cx).action_log();
let action_log = thread.action_log(cx);
let changed_buffers = action_log.read(cx).changed_buffers(cx);
let mut unaffected = self.reviewing_editors.clone();
@@ -1514,7 +1656,7 @@ impl AgentDiff {
multibuffer.add_diff(diff_handle.clone(), cx);
});
let new_state = if thread.read(cx).is_generating() {
let new_state = if thread.is_generating(cx) {
EditorState::Generating
} else {
EditorState::Reviewing
@@ -1543,7 +1685,7 @@ impl AgentDiff {
let first_hunk_start = first_hunk.multi_buffer_range().start;
editor.change_selections(
Some(Autoscroll::center()),
SelectionEffects::scroll(Autoscroll::center()),
window,
cx,
|selections| {
@@ -1610,7 +1752,7 @@ impl AgentDiff {
fn keep_all(
editor: &Entity<Editor>,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut App,
) -> PostReviewState {
@@ -1630,7 +1772,7 @@ impl AgentDiff {
fn reject_all(
editor: &Entity<Editor>,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut App,
) -> PostReviewState {
@@ -1650,7 +1792,7 @@ impl AgentDiff {
fn keep(
editor: &Entity<Editor>,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut App,
) -> PostReviewState {
@@ -1663,7 +1805,7 @@ impl AgentDiff {
fn reject(
editor: &Entity<Editor>,
thread: &Entity<Thread>,
thread: &AgentDiffThread,
window: &mut Window,
cx: &mut App,
) -> PostReviewState {
@@ -1686,7 +1828,7 @@ impl AgentDiff {
fn review_in_active_editor(
&mut self,
workspace: &mut Workspace,
review: impl Fn(&Entity<Editor>, &Entity<Thread>, &mut Window, &mut App) -> PostReviewState,
review: impl Fn(&Entity<Editor>, &AgentDiffThread, &mut Window, &mut App) -> PostReviewState,
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
@@ -1707,7 +1849,7 @@ impl AgentDiff {
if let PostReviewState::AllReviewed = review(&editor, &thread, window, cx) {
if let Some(curr_buffer) = editor.read(cx).buffer().read(cx).as_singleton() {
let changed_buffers = thread.read(cx).action_log().read(cx).changed_buffers(cx);
let changed_buffers = thread.action_log(cx).read(cx).changed_buffers(cx);
let mut keys = changed_buffers.keys().cycle();
keys.find(|k| *k == &curr_buffer);
@@ -1805,8 +1947,9 @@ mod tests {
})
.await
.unwrap();
let thread = thread_store.update(cx, |store, cx| store.create_thread(cx));
let action_log = thread.read_with(cx, |thread, _| thread.action_log().clone());
let thread =
AgentDiffThread::Native(thread_store.update(cx, |store, cx| store.create_thread(cx)));
let action_log = cx.read(|cx| thread.action_log(cx));
let (workspace, cx) =
cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
@@ -1867,7 +2010,7 @@ mod tests {
// Rejecting a hunk also moves the cursor to the next hunk, possibly cycling if it's at the end.
editor.update_in(cx, |editor, window, cx| {
editor.change_selections(None, window, cx, |selections| {
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |selections| {
selections.select_ranges([Point::new(10, 0)..Point::new(10, 0)])
});
});
@@ -1992,8 +2135,9 @@ mod tests {
});
// Set the active thread
let thread = AgentDiffThread::Native(thread);
cx.update(|window, cx| {
AgentDiff::set_active_thread(&workspace.downgrade(), &thread, window, cx)
AgentDiff::set_active_thread(&workspace.downgrade(), thread.clone(), window, cx)
});
let buffer1 = project
@@ -2123,7 +2267,7 @@ mod tests {
// Rejecting a hunk also moves the cursor to the next hunk, possibly cycling if it's at the end.
editor1.update_in(cx, |editor, window, cx| {
editor.change_selections(None, window, cx, |selections| {
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |selections| {
selections.select_ranges([Point::new(10, 0)..Point::new(10, 0)])
});
});

View File

@@ -11,7 +11,7 @@ use language_model::{ConfiguredModel, LanguageModelRegistry};
use picker::popover_menu::PickerPopoverMenu;
use settings::update_settings_file;
use std::sync::Arc;
use ui::{PopoverMenuHandle, Tooltip, prelude::*};
use ui::{ButtonLike, PopoverMenuHandle, Tooltip, prelude::*};
pub struct AgentModelSelector {
selector: Entity<LanguageModelSelector>,
@@ -94,20 +94,35 @@ impl Render for AgentModelSelector {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let model = self.selector.read(cx).delegate.active_model(cx);
let model_name = model
.as_ref()
.map(|model| model.model.name().0)
.unwrap_or_else(|| SharedString::from("No model selected"));
let provider_icon = model
.as_ref()
.map(|model| model.provider.icon())
.unwrap_or_else(|| IconName::Ai);
let focus_handle = self.focus_handle.clone();
PickerPopoverMenu::new(
self.selector.clone(),
Button::new("active-model", model_name)
.label_size(LabelSize::Small)
.color(Color::Muted)
.icon(IconName::ChevronDown)
.icon_size(IconSize::XSmall)
.icon_position(IconPosition::End)
.icon_color(Color::Muted),
ButtonLike::new("active-model")
.child(
Icon::new(provider_icon)
.color(Color::Muted)
.size(IconSize::XSmall),
)
.child(
Label::new(model_name)
.color(Color::Muted)
.size(LabelSize::Small)
.ml_0p5(),
)
.child(
Icon::new(IconName::ChevronDown)
.color(Color::Muted)
.size(IconSize::XSmall),
),
move |window, cx| {
Tooltip::for_action_in(
"Change Model",

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,11 @@
mod acp;
mod active_thread;
mod agent_configuration;
mod agent_diff;
mod agent_model_selector;
mod agent_panel;
mod buffer_codegen;
mod burn_mode_tooltip;
mod context_picker;
mod context_server_configuration;
mod context_strip;
@@ -11,7 +13,6 @@ mod debug;
mod inline_assistant;
mod inline_prompt_editor;
mod language_model_selector;
mod max_mode_tooltip;
mod message_editor;
mod profile_selector;
mod slash_command;
@@ -48,57 +49,94 @@ pub use crate::agent_panel::{AgentPanel, ConcreteAssistantPanelDelegate};
pub use crate::inline_assistant::InlineAssistant;
use crate::slash_command_settings::SlashCommandSettings;
pub use agent_diff::{AgentDiffPane, AgentDiffToolbar};
pub use text_thread_editor::AgentPanelDelegate;
pub use text_thread_editor::{AgentPanelDelegate, TextThreadEditor};
pub use ui::preview::{all_agent_previews, get_agent_preview};
actions!(
agent,
[
/// Creates a new text-based conversation thread.
NewTextThread,
/// Creates a new external agent conversation thread.
NewAcpThread,
/// Toggles the context picker interface for adding files, symbols, or other context.
ToggleContextPicker,
/// Toggles the navigation menu for switching between threads and views.
ToggleNavigationMenu,
/// Toggles the options menu for agent settings and preferences.
ToggleOptionsMenu,
/// Deletes the recently opened thread from history.
DeleteRecentlyOpenThread,
/// Toggles the profile selector for switching between agent profiles.
ToggleProfileSelector,
/// Removes all added context from the current conversation.
RemoveAllContext,
/// Expands the message editor to full size.
ExpandMessageEditor,
/// Opens the conversation history view.
OpenHistory,
/// Adds a context server to the configuration.
AddContextServer,
/// Removes the currently selected thread.
RemoveSelectedThread,
Chat,
/// Starts a chat conversation with follow-up enabled.
ChatWithFollow,
/// Cycles to the next inline assist suggestion.
CycleNextInlineAssist,
/// Cycles to the previous inline assist suggestion.
CyclePreviousInlineAssist,
/// Moves focus up in the interface.
FocusUp,
/// Moves focus down in the interface.
FocusDown,
/// Moves focus left in the interface.
FocusLeft,
/// Moves focus right in the interface.
FocusRight,
/// Removes the currently focused context item.
RemoveFocusedContext,
/// Accepts the suggested context item.
AcceptSuggestedContext,
/// Opens the active thread as a markdown file.
OpenActiveThreadAsMarkdown,
/// Opens the agent diff view to review changes.
OpenAgentDiff,
/// Keeps the current suggestion or change.
Keep,
/// Rejects the current suggestion or change.
Reject,
/// Rejects all suggestions or changes.
RejectAll,
/// Keeps all suggestions or changes.
KeepAll,
/// Follows the agent's suggestions.
Follow,
/// Resets the trial upsell notification.
ResetTrialUpsell,
/// Resets the trial end upsell notification.
ResetTrialEndUpsell,
/// Continues the current thread.
ContinueThread,
/// Continues the thread with burn mode enabled.
ContinueWithBurnMode,
/// Toggles burn mode for faster responses.
ToggleBurnMode,
]
);
/// Creates a new conversation thread, optionally based on an existing thread.
#[derive(Default, Clone, PartialEq, Deserialize, JsonSchema, Action)]
#[action(namespace = agent)]
#[serde(deny_unknown_fields)]
pub struct NewThread {
#[serde(default)]
from_thread_id: Option<ThreadId>,
}
/// Opens the profile management interface for configuring agent tools and settings.
#[derive(PartialEq, Clone, Default, Debug, Deserialize, JsonSchema, Action)]
#[action(namespace = agent)]
#[serde(deny_unknown_fields)]
pub struct ManageProfiles {
#[serde(default)]
pub customize_tools: Option<AgentProfileId>,
@@ -157,6 +195,7 @@ pub fn init(
agent::init(cx);
agent_panel::init(cx);
context_server_configuration::init(language_registry.clone(), fs.clone(), cx);
TextThreadEditor::init(cx);
register_slash_commands(cx);
inline_assistant::init(
@@ -208,7 +247,7 @@ fn update_active_language_model_from_settings(cx: &mut App) {
}
}
let default = to_selected_model(&settings.default_model);
let default = settings.default_model.as_ref().map(to_selected_model);
let inline_assistant = settings
.inline_assistant_model
.as_ref()
@@ -228,7 +267,7 @@ fn update_active_language_model_from_settings(cx: &mut App) {
.collect::<Vec<_>>();
LanguageModelRegistry::global(cx).update(cx, |registry, cx| {
registry.select_default_model(Some(&default), cx);
registry.select_default_model(default.as_ref(), cx);
registry.select_inline_assistant_model(inline_assistant.as_ref(), cx);
registry.select_commit_message_model(commit_message.as_ref(), cx);
registry.select_thread_summary_model(thread_summary.as_ref(), cx);

View File

@@ -475,6 +475,7 @@ impl CodegenAlternative {
stop: Vec::new(),
temperature,
messages: vec![request_message],
thinking_allowed: false,
}
}))
}
@@ -1094,15 +1095,9 @@ mod tests {
};
use language_model::{LanguageModelRegistry, TokenUsage};
use rand::prelude::*;
use serde::Serialize;
use settings::SettingsStore;
use std::{future, sync::Arc};
#[derive(Serialize)]
pub struct DummyCompletionRequest {
pub name: String,
}
#[gpui::test(iterations = 10)]
async fn test_transform_autoindent(cx: &mut TestAppContext, mut rng: StdRng) {
init_test(cx);

View File

@@ -1,11 +1,11 @@
use gpui::{Context, FontWeight, IntoElement, Render, Window};
use ui::{prelude::*, tooltip_container};
pub struct MaxModeTooltip {
pub struct BurnModeTooltip {
selected: bool,
}
impl MaxModeTooltip {
impl BurnModeTooltip {
pub fn new() -> Self {
Self { selected: false }
}
@@ -16,7 +16,7 @@ impl MaxModeTooltip {
}
}
impl Render for MaxModeTooltip {
impl Render for BurnModeTooltip {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let (icon, color) = if self.selected {
(IconName::ZedBurnModeOn, Color::Error)

View File

@@ -1,6 +1,6 @@
mod completion_provider;
mod fetch_context_picker;
mod file_context_picker;
pub(crate) mod file_context_picker;
mod rules_context_picker;
mod symbol_context_picker;
mod thread_context_picker;
@@ -426,6 +426,7 @@ impl ContextPicker {
this.add_recent_file(project_path.clone(), window, cx);
})
},
None,
)
}
RecentEntry::Thread(thread) => {
@@ -443,6 +444,7 @@ impl ContextPicker {
.detach_and_log_err(cx);
})
},
None,
)
}
}
@@ -661,7 +663,7 @@ fn recent_context_picker_entries(
let active_thread_id = workspace
.panel::<AgentPanel>(cx)
.and_then(|panel| Some(panel.read(cx).active_thread()?.read(cx).id()));
.and_then(|panel| Some(panel.read(cx).active_thread(cx)?.read(cx).id()));
if let Some((thread_store, text_thread_store)) = thread_store
.and_then(|store| store.upgrade())
@@ -930,8 +932,8 @@ impl MentionLink {
format!(
"[@{} ({}-{})]({}:{}:{}-{})",
file_name,
line_range.start,
line_range.end,
line_range.start + 1,
line_range.end + 1,
Self::SELECTION,
full_path,
line_range.start,

View File

@@ -686,6 +686,7 @@ impl ContextPickerCompletionProvider {
let mut label = CodeLabel::plain(symbol.name.clone(), None);
label.push_str(" ", None);
label.push_str(&file_name, comment_id);
label.push_str(&format!(" L{}", symbol.range.start.0.row + 1), comment_id);
let new_text = format!("{} ", MentionLink::for_symbol(&symbol.name, &full_path));
let new_text_len = new_text.len();

View File

@@ -161,7 +161,7 @@ impl ContextStrip {
let workspace = self.workspace.upgrade()?;
let panel = workspace.read(cx).panel::<AgentPanel>(cx)?.read(cx);
if let Some(active_thread) = panel.active_thread() {
if let Some(active_thread) = panel.active_thread(cx) {
let weak_active_thread = active_thread.downgrade();
let active_thread = active_thread.read(cx);

View File

@@ -18,6 +18,7 @@ use agent_settings::AgentSettings;
use anyhow::{Context as _, Result};
use client::telemetry::Telemetry;
use collections::{HashMap, HashSet, VecDeque, hash_map};
use editor::SelectionEffects;
use editor::{
Anchor, AnchorRangeExt, CodeActionProvider, Editor, EditorEvent, ExcerptId, ExcerptRange,
MultiBuffer, MultiBufferSnapshot, ToOffset as _, ToPoint,
@@ -659,7 +660,6 @@ impl InlineAssistant {
height: Some(prompt_editor_height),
render: build_assist_editor_renderer(prompt_editor),
priority: 0,
render_in_minimap: false,
},
BlockProperties {
style: BlockStyle::Sticky,
@@ -674,7 +674,6 @@ impl InlineAssistant {
.into_any_element()
}),
priority: 0,
render_in_minimap: false,
},
];
@@ -1159,7 +1158,7 @@ impl InlineAssistant {
let position = assist.range.start;
editor.update(cx, |editor, cx| {
editor.change_selections(None, window, cx, |selections| {
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |selections| {
selections.select_anchor_ranges([position..position])
});
@@ -1450,7 +1449,6 @@ impl InlineAssistant {
.into_any_element()
}),
priority: 0,
render_in_minimap: false,
});
}

View File

@@ -18,6 +18,7 @@ use ui::{ListItem, ListItemSpacing, prelude::*};
actions!(
agent,
[
/// Toggles the language model selector dropdown.
#[action(deprecated_aliases = ["assistant::ToggleModelSelector", "assistant2::ToggleModelSelector"])]
ToggleModelSelector
]
@@ -399,7 +400,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
cx: &mut Context<Picker<Self>>,
) -> Task<()> {
let all_models = self.all_models.clone();
let current_index = self.selected_index;
let active_model = (self.get_active_model)(cx);
let bg_executor = cx.background_executor();
let language_model_registry = LanguageModelRegistry::global(cx);
@@ -441,12 +442,9 @@ impl PickerDelegate for LanguageModelPickerDelegate {
cx.spawn_in(window, async move |this, cx| {
this.update_in(cx, |this, window, cx| {
this.delegate.filtered_entries = filtered_models.entries();
// Preserve selection focus
let new_index = if current_index >= this.delegate.filtered_entries.len() {
0
} else {
current_index
};
// Finds the currently selected model in the list
let new_index =
Self::get_active_model_index(&this.delegate.filtered_entries, active_model);
this.set_selected_index(new_index, Some(picker::Direction::Down), true, window, cx);
cx.notify();
})

View File

@@ -2,6 +2,7 @@ use std::collections::BTreeMap;
use std::rc::Rc;
use std::sync::Arc;
use crate::agent_diff::AgentDiffThread;
use crate::agent_model_selector::AgentModelSelector;
use crate::language_model_selector::ToggleModelSelector;
use crate::tool_compatibility::{IncompatibleToolsState, IncompatibleToolsTooltip};
@@ -47,13 +48,14 @@ use ui::{
};
use util::ResultExt as _;
use workspace::{CollaboratorId, Workspace};
use zed_actions::agent::Chat;
use zed_llm_client::CompletionIntent;
use crate::context_picker::{ContextPicker, ContextPickerCompletionProvider, crease_for_mention};
use crate::context_strip::{ContextStrip, ContextStripEvent, SuggestContextKind};
use crate::profile_selector::ProfileSelector;
use crate::{
ActiveThread, AgentDiffPane, Chat, ChatWithFollow, ExpandMessageEditor, Follow, KeepAll,
ActiveThread, AgentDiffPane, ChatWithFollow, ExpandMessageEditor, Follow, KeepAll,
ModelUsageContext, NewThread, OpenAgentDiff, RejectAll, RemoveAllContext, ToggleBurnMode,
ToggleContextPicker, ToggleProfileSelector, register_agent_preview,
};
@@ -474,9 +476,12 @@ impl MessageEditor {
window: &mut Window,
cx: &mut Context<Self>,
) {
if let Ok(diff) =
AgentDiffPane::deploy(self.thread.clone(), self.workspace.clone(), window, cx)
{
if let Ok(diff) = AgentDiffPane::deploy(
AgentDiffThread::Native(self.thread.clone()),
self.workspace.clone(),
window,
cx,
) {
let path_key = multi_buffer::PathKey::for_buffer(&buffer, cx);
diff.update(cx, |diff, cx| diff.move_to_path(path_key, window, cx));
}
@@ -575,7 +580,7 @@ impl MessageEditor {
fn render_burn_mode_toggle(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
let thread = self.thread.read(cx);
let model = thread.configured_model();
if !model?.model.supports_max_mode() {
if !model?.model.supports_burn_mode() {
return None;
}
@@ -1160,7 +1165,7 @@ impl MessageEditor {
})
.child(
h_flex()
.id("file-name")
.id(("file-name", index))
.pr_8()
.gap_1p5()
.max_w_full()
@@ -1171,9 +1176,16 @@ impl MessageEditor {
.gap_0p5()
.children(file_name)
.children(file_path),
), // TODO: Implement line diff
// .child(Label::new("+").color(Color::Created))
// .child(Label::new("-").color(Color::Deleted)),
)
.on_click({
let buffer = buffer.clone();
cx.listener(move |this, _, window, cx| {
this.handle_file_click(buffer.clone(), window, cx);
})
}), // TODO: Implement line diff
// .child(Label::new("+").color(Color::Created))
// .child(Label::new("-").color(Color::Deleted)),
//
)
.child(
h_flex()
@@ -1250,9 +1262,7 @@ impl MessageEditor {
self.thread
.read(cx)
.configured_model()
.map_or(false, |model| {
model.provider.id().0 == ZED_CLOUD_PROVIDER_ID
})
.map_or(false, |model| model.provider.id() == ZED_CLOUD_PROVIDER_ID)
}
fn render_usage_callout(&self, line_height: Pixels, cx: &mut Context<Self>) -> Option<Div> {
@@ -1448,6 +1458,7 @@ impl MessageEditor {
tool_choice: None,
stop: vec![],
temperature: AgentSettings::temperature_for_model(&model.model, cx),
thinking_allowed: true,
};
Some(model.model.count_tokens(request, cx))
@@ -1615,6 +1626,7 @@ impl Render for MessageEditor {
v_flex()
.size_full()
.bg(cx.theme().colors().panel_background)
.when(changed_buffers.len() > 0, |parent| {
parent.child(self.render_edits_bar(&changed_buffers, window, cx))
})

View File

@@ -297,6 +297,7 @@ impl TerminalInlineAssistant {
tool_choice: None,
stop: Vec::new(),
temperature,
thinking_allowed: false,
}
}))
}

View File

@@ -1,8 +1,8 @@
use crate::{
burn_mode_tooltip::BurnModeTooltip,
language_model_selector::{
LanguageModelSelector, ToggleModelSelector, language_model_selector,
},
max_mode_tooltip::MaxModeTooltip,
};
use agent_settings::{AgentSettings, CompletionMode};
use anyhow::Result;
@@ -21,7 +21,6 @@ use editor::{
BlockPlacement, BlockProperties, BlockStyle, Crease, CreaseMetadata, CustomBlockId, FoldId,
RenderBlock, ToDisplayPoint,
},
scroll::Autoscroll,
};
use editor::{FoldPlaceholder, display_map::CreaseId};
use fs::Fs;
@@ -39,8 +38,8 @@ use language::{
language_settings::{SoftWrap, all_language_settings},
};
use language_model::{
ConfigurationError, LanguageModelImage, LanguageModelProviderTosView, LanguageModelRegistry,
Role,
ConfigurationError, LanguageModelExt, LanguageModelImage, LanguageModelProviderTosView,
LanguageModelRegistry, Role,
};
use multi_buffer::MultiBufferRow;
use picker::{Picker, popover_menu::PickerPopoverMenu};
@@ -69,7 +68,7 @@ use workspace::{
searchable::{Direction, SearchableItemHandle},
};
use workspace::{
Save, Toast, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace,
Save, Toast, Workspace,
item::{self, FollowableItem, Item, ItemHandle},
notifications::NotificationId,
pane,
@@ -86,16 +85,24 @@ use assistant_context::{
actions!(
assistant,
[
/// Sends the current message to the assistant.
Assist,
/// Confirms and executes the entered slash command.
ConfirmCommand,
/// Copies code from the assistant's response to the clipboard.
CopyCode,
/// Cycles between user and assistant message roles.
CycleMessageRole,
/// Inserts the selected text into the active editor.
InsertIntoEditor,
/// Quotes the current selection in the assistant conversation.
QuoteSelection,
/// Splits the conversation at the current cursor position.
Split,
]
);
/// Inserts files that were dragged and dropped into the assistant conversation.
#[derive(PartialEq, Clone, Action)]
#[action(namespace = assistant, no_json, no_register)]
pub enum InsertDraggedFiles {
@@ -389,7 +396,7 @@ impl TextThreadEditor {
cursor..cursor
};
self.editor.update(cx, |editor, cx| {
editor.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
editor.change_selections(Default::default(), window, cx, |selections| {
selections.select_ranges([new_selection])
});
});
@@ -449,8 +456,7 @@ impl TextThreadEditor {
if let Some(command) = self.slash_commands.command(name, cx) {
self.editor.update(cx, |editor, cx| {
editor.transact(window, cx, |editor, window, cx| {
editor
.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel());
editor.change_selections(Default::default(), window, cx, |s| s.try_cancel());
let snapshot = editor.buffer().read(cx).snapshot(cx);
let newest_cursor = editor.selections.newest::<Point>(cx).head();
if newest_cursor.column > 0
@@ -1250,7 +1256,6 @@ impl TextThreadEditor {
),
priority: usize::MAX,
render: render_block(MessageMetadata::from(message)),
render_in_minimap: false,
};
let mut new_blocks = vec![];
let mut block_index_to_message = vec![];
@@ -1583,7 +1588,7 @@ impl TextThreadEditor {
self.editor.update(cx, |editor, cx| {
editor.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
this.change_selections(Default::default(), window, cx, |s| {
s.select(selections);
});
this.insert("", window, cx);
@@ -1852,7 +1857,6 @@ impl TextThreadEditor {
.into_any_element()
}),
priority: 0,
render_in_minimap: false,
})
})
.collect::<Vec<_>>();
@@ -2075,12 +2079,12 @@ impl TextThreadEditor {
)
}
fn render_max_mode_toggle(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
fn render_burn_mode_toggle(&self, cx: &mut Context<Self>) -> Option<AnyElement> {
let context = self.context().read(cx);
let active_model = LanguageModelRegistry::read_global(cx)
.default_model()
.map(|default| default.model)?;
if !active_model.supports_max_mode() {
if !active_model.supports_burn_mode() {
return None;
}
@@ -2107,7 +2111,7 @@ impl TextThreadEditor {
});
}))
.tooltip(move |_window, cx| {
cx.new(|_| MaxModeTooltip::new().selected(burn_mode_enabled))
cx.new(|_| BurnModeTooltip::new().selected(burn_mode_enabled))
.into()
})
.into_any_element(),
@@ -2122,12 +2126,21 @@ impl TextThreadEditor {
let active_model = LanguageModelRegistry::read_global(cx)
.default_model()
.map(|default| default.model);
let focus_handle = self.editor().focus_handle(cx).clone();
let model_name = match active_model {
Some(model) => model.name().0,
None => SharedString::from("No model selected"),
};
let active_provider = LanguageModelRegistry::read_global(cx)
.default_model()
.map(|default| default.provider);
let provider_icon = match active_provider {
Some(provider) => provider.icon(),
None => IconName::Ai,
};
let focus_handle = self.editor().focus_handle(cx).clone();
PickerPopoverMenu::new(
self.language_model_selector.clone(),
ButtonLike::new("active-model")
@@ -2135,10 +2148,16 @@ impl TextThreadEditor {
.child(
h_flex()
.gap_0p5()
.child(
Icon::new(provider_icon)
.color(Color::Muted)
.size(IconSize::XSmall),
)
.child(
Label::new(model_name)
.color(Color::Muted)
.size(LabelSize::Small)
.color(Color::Muted),
.ml_0p5(),
)
.child(
Icon::new(IconName::ChevronDown)
@@ -2575,7 +2594,7 @@ impl Render for TextThreadEditor {
};
let language_model_selector = self.language_model_selector_menu_handle.clone();
let max_mode_toggle = self.render_max_mode_toggle(cx);
let burn_mode_toggle = self.render_burn_mode_toggle(cx);
v_flex()
.key_context("ContextEditor")
@@ -2630,7 +2649,7 @@ impl Render for TextThreadEditor {
h_flex()
.gap_0p5()
.child(self.render_inject_context_menu(cx))
.when_some(max_mode_toggle, |this, element| this.child(element)),
.when_some(burn_mode_toggle, |this, element| this.child(element)),
)
.child(
h_flex()
@@ -2924,13 +2943,6 @@ impl FollowableItem for TextThreadEditor {
}
}
pub struct ContextEditorToolbarItem {
active_context_editor: Option<WeakEntity<TextThreadEditor>>,
model_summary_editor: Entity<Editor>,
}
impl ContextEditorToolbarItem {}
pub fn render_remaining_tokens(
context_editor: &Entity<TextThreadEditor>,
cx: &App,
@@ -2983,98 +2995,6 @@ pub fn render_remaining_tokens(
)
}
impl Render for ContextEditorToolbarItem {
fn render(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let left_side = h_flex()
.group("chat-title-group")
.gap_1()
.items_center()
.flex_grow()
.child(
div()
.w_full()
.when(self.active_context_editor.is_some(), |left_side| {
left_side.child(self.model_summary_editor.clone())
}),
)
.child(
div().visible_on_hover("chat-title-group").child(
IconButton::new("regenerate-context", IconName::RefreshTitle)
.shape(ui::IconButtonShape::Square)
.tooltip(Tooltip::text("Regenerate Title"))
.on_click(cx.listener(move |_, _, _window, cx| {
cx.emit(ContextEditorToolbarItemEvent::RegenerateSummary)
})),
),
);
let right_side = h_flex()
.gap_2()
// TODO display this in a nicer way, once we have a design for it.
// .children({
// let project = self
// .workspace
// .upgrade()
// .map(|workspace| workspace.read(cx).project().downgrade());
//
// let scan_items_remaining = cx.update_global(|db: &mut SemanticDb, cx| {
// project.and_then(|project| db.remaining_summaries(&project, cx))
// });
// scan_items_remaining
// .map(|remaining_items| format!("Files to scan: {}", remaining_items))
// })
.children(
self.active_context_editor
.as_ref()
.and_then(|editor| editor.upgrade())
.and_then(|editor| render_remaining_tokens(&editor, cx)),
);
h_flex()
.px_0p5()
.size_full()
.gap_2()
.justify_between()
.child(left_side)
.child(right_side)
}
}
impl ToolbarItemView for ContextEditorToolbarItem {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn ItemHandle>,
_window: &mut Window,
cx: &mut Context<Self>,
) -> ToolbarItemLocation {
self.active_context_editor = active_pane_item
.and_then(|item| item.act_as::<TextThreadEditor>(cx))
.map(|editor| editor.downgrade());
cx.notify();
if self.active_context_editor.is_none() {
ToolbarItemLocation::Hidden
} else {
ToolbarItemLocation::PrimaryRight
}
}
fn pane_focus_update(
&mut self,
_pane_focused: bool,
_window: &mut Window,
cx: &mut Context<Self>,
) {
cx.notify();
}
}
impl EventEmitter<ToolbarItemEvent> for ContextEditorToolbarItem {}
pub enum ContextEditorToolbarItemEvent {
RegenerateSummary,
}
impl EventEmitter<ContextEditorToolbarItemEvent> for ContextEditorToolbarItem {}
enum PendingSlashCommand {}
fn invoked_slash_command_fold_placeholder(
@@ -3141,7 +3061,7 @@ fn token_state(context: &Entity<AssistantContext>, cx: &App) -> Option<TokenStat
.default_model()?
.model;
let token_count = context.read(cx).token_count()?;
let max_token_count = model.max_token_count();
let max_token_count = model.max_token_count_for_mode(context.read(cx).completion_mode().into());
let token_state = if max_token_count.saturating_sub(token_count) == 0 {
TokenState::NoTokensLeft {
max_token_count,
@@ -3240,6 +3160,7 @@ pub fn make_lsp_adapter_delegate(
#[cfg(test)]
mod tests {
use super::*;
use editor::SelectionEffects;
use fs::FakeFs;
use gpui::{App, TestAppContext, VisualTestContext};
use indoc::indoc;
@@ -3465,7 +3386,9 @@ mod tests {
) {
context_editor.update_in(cx, |context_editor, window, cx| {
context_editor.editor.update(cx, |editor, cx| {
editor.change_selections(None, window, cx, |s| s.select_ranges([range]));
editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
s.select_ranges([range])
});
});
context_editor.copy(&Default::default(), window, cx);

View File

@@ -42,8 +42,8 @@ impl IncompatibleToolsState {
.profile()
.enabled_tools(cx)
.iter()
.filter(|tool| tool.input_schema(model.tool_input_format()).is_err())
.cloned()
.filter(|(_, tool)| tool.input_schema(model.tool_input_format()).is_err())
.map(|(_, tool)| tool.clone())
.collect()
})
}

View File

@@ -1,13 +1,11 @@
mod agent_notification;
mod animated_label;
mod burn_mode_tooltip;
mod context_pill;
mod max_mode_tooltip;
mod onboarding_modal;
pub mod preview;
mod upsell;
pub use agent_notification::*;
pub use animated_label::*;
pub use burn_mode_tooltip::*;
pub use context_pill::*;
pub use max_mode_tooltip::*;
pub use onboarding_modal::*;

View File

@@ -6,7 +6,7 @@ use anyhow::{Context as _, Result, anyhow};
use chrono::{DateTime, Utc};
use futures::{AsyncBufReadExt, AsyncReadExt, StreamExt, io::BufReader, stream::BoxStream};
use http_client::http::{self, HeaderMap, HeaderValue};
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest};
use http_client::{AsyncBody, HttpClient, Method, Request as HttpRequest, StatusCode};
use serde::{Deserialize, Serialize};
use strum::{EnumIter, EnumString};
use thiserror::Error;
@@ -356,7 +356,7 @@ pub async fn complete(
.send(request)
.await
.map_err(AnthropicError::HttpSend)?;
let status = response.status();
let status_code = response.status();
let mut body = String::new();
response
.body_mut()
@@ -364,12 +364,12 @@ pub async fn complete(
.await
.map_err(AnthropicError::ReadResponse)?;
if status.is_success() {
if status_code.is_success() {
Ok(serde_json::from_str(&body).map_err(AnthropicError::DeserializeResponse)?)
} else {
Err(AnthropicError::HttpResponseError {
status: status.as_u16(),
body,
status_code,
message: body,
})
}
}
@@ -444,11 +444,7 @@ impl RateLimitInfo {
}
Self {
retry_after: headers
.get("retry-after")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.parse::<u64>().ok())
.map(Duration::from_secs),
retry_after: parse_retry_after(headers),
requests: RateLimit::from_headers("requests", headers).ok(),
tokens: RateLimit::from_headers("tokens", headers).ok(),
input_tokens: RateLimit::from_headers("input-tokens", headers).ok(),
@@ -457,6 +453,17 @@ impl RateLimitInfo {
}
}
/// Parses the Retry-After header value as an integer number of seconds (anthropic always uses
/// seconds). Note that other services might specify an HTTP date or some other format for this
/// header. Returns `None` if the header is not present or cannot be parsed.
pub fn parse_retry_after(headers: &HeaderMap<HeaderValue>) -> Option<Duration> {
headers
.get("retry-after")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.parse::<u64>().ok())
.map(Duration::from_secs)
}
fn get_header<'a>(key: &str, headers: &'a HeaderMap) -> anyhow::Result<&'a str> {
Ok(headers
.get(key)
@@ -520,6 +527,10 @@ pub async fn stream_completion_with_rate_limit_info(
})
.boxed();
Ok((stream, Some(rate_limits)))
} else if response.status().as_u16() == 529 {
Err(AnthropicError::ServerOverloaded {
retry_after: rate_limits.retry_after,
})
} else if let Some(retry_after) = rate_limits.retry_after {
Err(AnthropicError::RateLimit { retry_after })
} else {
@@ -532,10 +543,9 @@ pub async fn stream_completion_with_rate_limit_info(
match serde_json::from_str::<Event>(&body) {
Ok(Event::Error { error }) => Err(AnthropicError::ApiError(error)),
Ok(_) => Err(AnthropicError::UnexpectedResponseFormat(body)),
Err(_) => Err(AnthropicError::HttpResponseError {
status: response.status().as_u16(),
body: body,
Ok(_) | Err(_) => Err(AnthropicError::HttpResponseError {
status_code: response.status(),
message: body,
}),
}
}
@@ -801,16 +811,19 @@ pub enum AnthropicError {
ReadResponse(io::Error),
/// HTTP error response from the API
HttpResponseError { status: u16, body: String },
HttpResponseError {
status_code: StatusCode,
message: String,
},
/// Rate limit exceeded
RateLimit { retry_after: Duration },
/// Server overloaded
ServerOverloaded { retry_after: Option<Duration> },
/// API returned an error response
ApiError(ApiError),
/// Unexpected response format
UnexpectedResponseFormat(String),
}
#[derive(Debug, Serialize, Deserialize, Error)]

View File

@@ -15,6 +15,8 @@ path = "src/askpass.rs"
anyhow.workspace = true
futures.workspace = true
gpui.workspace = true
net.workspace = true
parking_lot.workspace = true
smol.workspace = true
tempfile.workspace = true
util.workspace = true

View File

@@ -1,21 +1,14 @@
use std::path::{Path, PathBuf};
use std::time::Duration;
use std::{ffi::OsStr, time::Duration};
#[cfg(unix)]
use anyhow::Context as _;
use anyhow::{Context as _, Result};
use futures::channel::{mpsc, oneshot};
#[cfg(unix)]
use futures::{AsyncBufReadExt as _, io::BufReader};
#[cfg(unix)]
use futures::{AsyncWriteExt as _, FutureExt as _, select_biased};
use futures::{SinkExt, StreamExt};
use futures::{
AsyncBufReadExt as _, AsyncWriteExt as _, FutureExt as _, SinkExt, StreamExt, io::BufReader,
select_biased,
};
use gpui::{AsyncApp, BackgroundExecutor, Task};
#[cfg(unix)]
use smol::fs;
#[cfg(unix)]
use smol::net::unix::UnixListener;
#[cfg(unix)]
use util::{ResultExt as _, fs::make_file_executable, get_shell_safe_zed_path};
use util::ResultExt as _;
#[derive(PartialEq, Eq)]
pub enum AskPassResult {
@@ -42,41 +35,56 @@ impl AskPassDelegate {
Self { tx, _task: task }
}
pub async fn ask_password(&mut self, prompt: String) -> anyhow::Result<String> {
pub async fn ask_password(&mut self, prompt: String) -> Result<String> {
let (tx, rx) = oneshot::channel();
self.tx.send((prompt, tx)).await?;
Ok(rx.await?)
}
}
#[cfg(unix)]
pub struct AskPassSession {
script_path: PathBuf,
#[cfg(not(target_os = "windows"))]
script_path: std::path::PathBuf,
#[cfg(target_os = "windows")]
askpass_helper: String,
#[cfg(target_os = "windows")]
secret: std::sync::Arc<parking_lot::Mutex<String>>,
_askpass_task: Task<()>,
askpass_opened_rx: Option<oneshot::Receiver<()>>,
askpass_kill_master_rx: Option<oneshot::Receiver<()>>,
}
#[cfg(unix)]
#[cfg(not(target_os = "windows"))]
const ASKPASS_SCRIPT_NAME: &str = "askpass.sh";
#[cfg(target_os = "windows")]
const ASKPASS_SCRIPT_NAME: &str = "askpass.ps1";
impl AskPassSession {
/// This will create a new AskPassSession.
/// You must retain this session until the master process exits.
#[must_use]
pub async fn new(
executor: &BackgroundExecutor,
mut delegate: AskPassDelegate,
) -> anyhow::Result<Self> {
pub async fn new(executor: &BackgroundExecutor, mut delegate: AskPassDelegate) -> Result<Self> {
use net::async_net::UnixListener;
use util::fs::make_file_executable;
#[cfg(target_os = "windows")]
let secret = std::sync::Arc::new(parking_lot::Mutex::new(String::new()));
let temp_dir = tempfile::Builder::new().prefix("zed-askpass").tempdir()?;
let askpass_socket = temp_dir.path().join("askpass.sock");
let askpass_script_path = temp_dir.path().join("askpass.sh");
let askpass_script_path = temp_dir.path().join(ASKPASS_SCRIPT_NAME);
let (askpass_opened_tx, askpass_opened_rx) = oneshot::channel::<()>();
let listener =
UnixListener::bind(&askpass_socket).context("failed to create askpass socket")?;
let zed_path = get_shell_safe_zed_path()?;
let listener = UnixListener::bind(&askpass_socket).context("creating askpass socket")?;
#[cfg(not(target_os = "windows"))]
let zed_path = util::get_shell_safe_zed_path()?;
#[cfg(target_os = "windows")]
let zed_path = std::env::current_exe()
.context("finding current executable path for use in askpass")?;
let (askpass_kill_master_tx, askpass_kill_master_rx) = oneshot::channel::<()>();
let mut kill_tx = Some(askpass_kill_master_tx);
#[cfg(target_os = "windows")]
let askpass_secret = secret.clone();
let askpass_task = executor.spawn(async move {
let mut askpass_opened_tx = Some(askpass_opened_tx);
@@ -93,10 +101,14 @@ impl AskPassSession {
if let Some(password) = delegate
.ask_password(prompt.to_string())
.await
.context("failed to get askpass password")
.context("getting askpass password")
.log_err()
{
stream.write_all(password.as_bytes()).await.log_err();
#[cfg(target_os = "windows")]
{
*askpass_secret.lock() = password;
}
} else {
if let Some(kill_tx) = kill_tx.take() {
kill_tx.send(()).log_err();
@@ -112,34 +124,49 @@ impl AskPassSession {
});
// Create an askpass script that communicates back to this process.
let askpass_script = format!(
"{shebang}\n{print_args} | {zed_exe} --askpass={askpass_socket} 2> /dev/null \n",
zed_exe = zed_path,
askpass_socket = askpass_socket.display(),
print_args = "printf '%s\\0' \"$@\"",
shebang = "#!/bin/sh",
);
fs::write(&askpass_script_path, askpass_script).await?;
let askpass_script = generate_askpass_script(&zed_path, &askpass_socket);
fs::write(&askpass_script_path, askpass_script)
.await
.with_context(|| format!("creating askpass script at {askpass_script_path:?}"))?;
make_file_executable(&askpass_script_path).await?;
#[cfg(target_os = "windows")]
let askpass_helper = format!(
"powershell.exe -ExecutionPolicy Bypass -File {}",
askpass_script_path.display()
);
Ok(Self {
#[cfg(not(target_os = "windows"))]
script_path: askpass_script_path,
#[cfg(target_os = "windows")]
secret,
#[cfg(target_os = "windows")]
askpass_helper,
_askpass_task: askpass_task,
askpass_kill_master_rx: Some(askpass_kill_master_rx),
askpass_opened_rx: Some(askpass_opened_rx),
})
}
pub fn script_path(&self) -> &Path {
#[cfg(not(target_os = "windows"))]
pub fn script_path(&self) -> impl AsRef<OsStr> {
&self.script_path
}
#[cfg(target_os = "windows")]
pub fn script_path(&self) -> impl AsRef<OsStr> {
&self.askpass_helper
}
// This will run the askpass task forever, resolving as many authentication requests as needed.
// The caller is responsible for examining the result of their own commands and cancelling this
// future when this is no longer needed. Note that this can only be called once, but due to the
// drop order this takes an &mut, so you can `drop()` it after you're done with the master process.
pub async fn run(&mut self) -> AskPassResult {
let connection_timeout = Duration::from_secs(10);
// This is the default timeout setting used by VSCode.
let connection_timeout = Duration::from_secs(17);
let askpass_opened_rx = self.askpass_opened_rx.take().expect("Only call run once");
let askpass_kill_master_rx = self
.askpass_kill_master_rx
@@ -158,14 +185,19 @@ impl AskPassSession {
}
}
}
/// This will return the password that was last set by the askpass script.
#[cfg(target_os = "windows")]
pub fn get_password(&self) -> String {
self.secret.lock().clone()
}
}
/// The main function for when Zed is running in netcat mode for use in askpass.
/// Called from both the remote server binary and the zed binary in their respective main functions.
#[cfg(unix)]
pub fn main(socket: &str) {
use net::UnixStream;
use std::io::{self, Read, Write};
use std::os::unix::net::UnixStream;
use std::process::exit;
let mut stream = match UnixStream::connect(socket) {
@@ -182,6 +214,10 @@ pub fn main(socket: &str) {
exit(1);
}
#[cfg(target_os = "windows")]
while buffer.last().map_or(false, |&b| b == b'\n' || b == b'\r') {
buffer.pop();
}
if buffer.last() != Some(&b'\0') {
buffer.push(b'\0');
}
@@ -202,28 +238,28 @@ pub fn main(socket: &str) {
exit(1);
}
}
#[cfg(not(unix))]
pub fn main(_socket: &str) {}
#[cfg(not(unix))]
pub struct AskPassSession {
path: PathBuf,
#[inline]
#[cfg(not(target_os = "windows"))]
fn generate_askpass_script(zed_path: &str, askpass_socket: &std::path::Path) -> String {
format!(
"{shebang}\n{print_args} | {zed_exe} --askpass={askpass_socket} 2> /dev/null \n",
zed_exe = zed_path,
askpass_socket = askpass_socket.display(),
print_args = "printf '%s\\0' \"$@\"",
shebang = "#!/bin/sh",
)
}
#[cfg(not(unix))]
impl AskPassSession {
pub async fn new(_: &BackgroundExecutor, _: AskPassDelegate) -> anyhow::Result<Self> {
Ok(Self {
path: PathBuf::new(),
})
}
pub fn script_path(&self) -> &Path {
&self.path
}
pub async fn run(&mut self) -> AskPassResult {
futures::FutureExt::fuse(smol::Timer::after(Duration::from_secs(20))).await;
AskPassResult::Timedout
}
#[inline]
#[cfg(target_os = "windows")]
fn generate_askpass_script(zed_path: &std::path::Path, askpass_socket: &std::path::Path) -> String {
format!(
r#"
$ErrorActionPreference = 'Stop';
($args -join [char]0) | & "{zed_exe}" --askpass={askpass_socket} 2> $null
"#,
zed_exe = zed_path.display(),
askpass_socket = askpass_socket.display(),
)
}

View File

@@ -2140,7 +2140,8 @@ impl AssistantContext {
);
}
LanguageModelCompletionEvent::ToolUse(_) |
LanguageModelCompletionEvent::UsageUpdate(_) => {}
LanguageModelCompletionEvent::ToolUseJsonParseError { .. } |
LanguageModelCompletionEvent::UsageUpdate(_) => {}
}
});
@@ -2292,6 +2293,7 @@ impl AssistantContext {
tool_choice: None,
stop: Vec::new(),
temperature: model.and_then(|model| AgentSettings::temperature_for_model(model, cx)),
thinking_allowed: true,
};
for message in self.messages(cx) {
if message.status != MessageStatus::Done {
@@ -2346,13 +2348,13 @@ impl AssistantContext {
completion_request.messages.push(request_message);
}
}
let supports_max_mode = if let Some(model) = model {
model.supports_max_mode()
let supports_burn_mode = if let Some(model) = model {
model.supports_burn_mode()
} else {
false
};
if supports_max_mode {
if supports_burn_mode {
completion_request.mode = Some(self.completion_mode.into());
}
completion_request

View File

@@ -34,6 +34,11 @@ impl ExtensionSlashCommandProxy for SlashCommandRegistryProxy {
self.slash_command_registry
.register_command(ExtensionSlashCommand::new(extension, command), false)
}
fn unregister_slash_command(&self, command_name: Arc<str>) {
self.slash_command_registry
.unregister_command_by_name(&command_name)
}
}
/// An adapter that allows an [`LspAdapterDelegate`] to be used as a [`WorktreeDelegate`].

View File

@@ -74,7 +74,7 @@ impl SlashCommand for DeltaSlashCommand {
.slice(section.range.to_offset(&context_buffer)),
);
file_command_new_outputs.push(Arc::new(FileSlashCommand).run(
&[metadata.path.clone()],
std::slice::from_ref(&metadata.path),
context_slash_command_output_sections,
context_buffer.clone(),
workspace.clone(),

View File

@@ -22,6 +22,7 @@ gpui.workspace = true
icons.workspace = true
language.workspace = true
language_model.workspace = true
log.workspace = true
parking_lot.workspace = true
project.workspace = true
regex.workspace = true
@@ -39,6 +40,7 @@ collections = { workspace = true, features = ["test-support"] }
clock = { workspace = true, features = ["test-support"] }
ctor.workspace = true
gpui = { workspace = true, features = ["test-support"] }
indoc.workspace = true
language = { workspace = true, features = ["test-support"] }
language_model = { workspace = true, features = ["test-support"] }
log.workspace = true

View File

@@ -1,5 +1,6 @@
use anyhow::{Context as _, Result};
use buffer_diff::BufferDiff;
use clock;
use collections::BTreeMap;
use futures::{FutureExt, StreamExt, channel::mpsc};
use gpui::{App, AppContext, AsyncApp, Context, Entity, Subscription, Task, WeakEntity};
@@ -7,7 +8,10 @@ use language::{Anchor, Buffer, BufferEvent, DiskState, Point, ToPoint};
use project::{Project, ProjectItem, lsp_store::OpenLspBufferHandle};
use std::{cmp, ops::Range, sync::Arc};
use text::{Edit, Patch, Rope};
use util::RangeExt;
use util::{
RangeExt, ResultExt as _,
paths::{PathStyle, RemotePathBuf},
};
/// Tracks actions performed by tools in a thread
pub struct ActionLog {
@@ -43,6 +47,71 @@ impl ActionLog {
self.edited_since_project_diagnostics_check
}
pub fn latest_snapshot(&self, buffer: &Entity<Buffer>) -> Option<text::BufferSnapshot> {
Some(self.tracked_buffers.get(buffer)?.snapshot.clone())
}
pub fn has_unnotified_user_edits(&self) -> bool {
self.tracked_buffers
.values()
.any(|tracked| tracked.has_unnotified_user_edits)
}
/// Return a unified diff patch with user edits made since last read or notification
pub fn unnotified_user_edits(&self, cx: &Context<Self>) -> Option<String> {
if !self.has_unnotified_user_edits() {
return None;
}
let unified_diff = self
.tracked_buffers
.values()
.filter_map(|tracked| {
if !tracked.has_unnotified_user_edits {
return None;
}
let text_with_latest_user_edits = tracked.diff_base.to_string();
let text_with_last_seen_user_edits = tracked.last_seen_base.to_string();
if text_with_latest_user_edits == text_with_last_seen_user_edits {
return None;
}
let patch = language::unified_diff(
&text_with_last_seen_user_edits,
&text_with_latest_user_edits,
);
let buffer = tracked.buffer.clone();
let file_path = buffer
.read(cx)
.file()
.map(|file| RemotePathBuf::new(file.full_path(cx), PathStyle::Posix).to_proto())
.unwrap_or_else(|| format!("buffer_{}", buffer.entity_id()));
let mut result = String::new();
result.push_str(&format!("--- a/{}\n", file_path));
result.push_str(&format!("+++ b/{}\n", file_path));
result.push_str(&patch);
Some(result)
})
.collect::<Vec<_>>()
.join("\n\n");
Some(unified_diff)
}
/// Return a unified diff patch with user edits made since last read/notification
/// and mark them as notified
pub fn flush_unnotified_user_edits(&mut self, cx: &Context<Self>) -> Option<String> {
let patch = self.unnotified_user_edits(cx);
self.tracked_buffers.values_mut().for_each(|tracked| {
tracked.has_unnotified_user_edits = false;
tracked.last_seen_base = tracked.diff_base.clone();
});
patch
}
fn track_buffer_internal(
&mut self,
buffer: Entity<Buffer>,
@@ -92,26 +161,31 @@ impl ActionLog {
let diff = cx.new(|cx| BufferDiff::new(&text_snapshot, cx));
let (diff_update_tx, diff_update_rx) = mpsc::unbounded();
let diff_base;
let last_seen_base;
let unreviewed_edits;
if is_created {
diff_base = Rope::default();
last_seen_base = Rope::default();
unreviewed_edits = Patch::new(vec![Edit {
old: 0..1,
new: 0..text_snapshot.max_point().row + 1,
}])
} else {
diff_base = buffer.read(cx).as_rope().clone();
last_seen_base = diff_base.clone();
unreviewed_edits = Patch::default();
}
TrackedBuffer {
buffer: buffer.clone(),
diff_base,
unreviewed_edits: unreviewed_edits,
last_seen_base,
unreviewed_edits,
snapshot: text_snapshot.clone(),
status,
version: buffer.read(cx).version(),
diff,
diff_update: diff_update_tx,
has_unnotified_user_edits: false,
_open_lsp_handle: open_lsp_handle,
_maintain_diff: cx.spawn({
let buffer = buffer.clone();
@@ -251,19 +325,23 @@ impl ActionLog {
buffer_snapshot: text::BufferSnapshot,
cx: &mut AsyncApp,
) -> Result<()> {
let rebase = this.read_with(cx, |this, cx| {
let rebase = this.update(cx, |this, cx| {
let tracked_buffer = this
.tracked_buffers
.get(buffer)
.get_mut(buffer)
.context("buffer not tracked")?;
if let ChangeAuthor::User = author {
tracked_buffer.has_unnotified_user_edits = true;
}
let rebase = cx.background_spawn({
let mut base_text = tracked_buffer.diff_base.clone();
let old_snapshot = tracked_buffer.snapshot.clone();
let new_snapshot = buffer_snapshot.clone();
let unreviewed_edits = tracked_buffer.unreviewed_edits.clone();
let edits = diff_snapshots(&old_snapshot, &new_snapshot);
async move {
let edits = diff_snapshots(&old_snapshot, &new_snapshot);
if let ChangeAuthor::User = author {
apply_non_conflicting_edits(
&unreviewed_edits,
@@ -704,6 +782,22 @@ impl ActionLog {
cx.notify();
}
pub fn reject_all_edits(&mut self, cx: &mut Context<Self>) -> Task<()> {
let futures = self.changed_buffers(cx).into_keys().map(|buffer| {
let reject = self.reject_edits_in_ranges(buffer, vec![Anchor::MIN..Anchor::MAX], cx);
async move {
reject.await.log_err();
}
});
let task = futures::future::join_all(futures);
cx.spawn(async move |_, _| {
task.await;
})
}
/// Returns the set of buffers that contain edits that haven't been reviewed by the user.
pub fn changed_buffers(&self, cx: &App) -> BTreeMap<Entity<Buffer>, Entity<BufferDiff>> {
self.tracked_buffers
@@ -856,12 +950,14 @@ enum TrackedBufferStatus {
struct TrackedBuffer {
buffer: Entity<Buffer>,
diff_base: Rope,
last_seen_base: Rope,
unreviewed_edits: Patch<u32>,
status: TrackedBufferStatus,
version: clock::Global,
diff: Entity<BufferDiff>,
snapshot: text::BufferSnapshot,
diff_update: mpsc::UnboundedSender<(ChangeAuthor, text::BufferSnapshot)>,
has_unnotified_user_edits: bool,
_open_lsp_handle: OpenLspBufferHandle,
_maintain_diff: Task<()>,
_subscription: Subscription,
@@ -892,6 +988,7 @@ mod tests {
use super::*;
use buffer_diff::DiffHunkStatusKind;
use gpui::TestAppContext;
use indoc::indoc;
use language::Point;
use project::{FakeFs, Fs, Project, RemoveOptions};
use rand::prelude::*;
@@ -1174,6 +1271,110 @@ mod tests {
assert_eq!(unreviewed_hunks(&action_log, cx), vec![]);
}
#[gpui::test(iterations = 10)]
async fn test_user_edits_notifications(cx: &mut TestAppContext) {
init_test(cx);
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
path!("/dir"),
json!({"file": indoc! {"
abc
def
ghi
jkl
mno"}}),
)
.await;
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
let action_log = cx.new(|_| ActionLog::new(project.clone()));
let file_path = project
.read_with(cx, |project, cx| project.find_project_path("dir/file", cx))
.unwrap();
let buffer = project
.update(cx, |project, cx| project.open_buffer(file_path, cx))
.await
.unwrap();
// Agent edits
cx.update(|cx| {
action_log.update(cx, |log, cx| log.buffer_read(buffer.clone(), cx));
buffer.update(cx, |buffer, cx| {
buffer
.edit([(Point::new(1, 2)..Point::new(2, 3), "F\nGHI")], None, cx)
.unwrap()
});
action_log.update(cx, |log, cx| log.buffer_edited(buffer.clone(), cx));
});
cx.run_until_parked();
assert_eq!(
buffer.read_with(cx, |buffer, _| buffer.text()),
indoc! {"
abc
deF
GHI
jkl
mno"}
);
assert_eq!(
unreviewed_hunks(&action_log, cx),
vec![(
buffer.clone(),
vec![HunkStatus {
range: Point::new(1, 0)..Point::new(3, 0),
diff_status: DiffHunkStatusKind::Modified,
old_text: "def\nghi\n".into(),
}],
)]
);
// User edits
buffer.update(cx, |buffer, cx| {
buffer.edit(
[
(Point::new(0, 2)..Point::new(0, 2), "X"),
(Point::new(3, 0)..Point::new(3, 0), "Y"),
],
None,
cx,
)
});
cx.run_until_parked();
assert_eq!(
buffer.read_with(cx, |buffer, _| buffer.text()),
indoc! {"
abXc
deF
GHI
Yjkl
mno"}
);
// User edits should be stored separately from agent's
let user_edits = action_log.update(cx, |log, cx| log.unnotified_user_edits(cx));
assert_eq!(
user_edits.expect("should have some user edits"),
indoc! {"
--- a/dir/file
+++ b/dir/file
@@ -1,5 +1,5 @@
-abc
+abXc
def
ghi
-jkl
+Yjkl
mno
"}
);
action_log.update(cx, |log, cx| {
log.keep_edits_in_range(buffer.clone(), Point::new(0, 0)..Point::new(1, 0), cx)
});
cx.run_until_parked();
assert_eq!(unreviewed_hunks(&action_log, cx), vec![]);
}
#[gpui::test(iterations = 10)]
async fn test_creating_files(cx: &mut TestAppContext) {
init_test(cx);
@@ -2163,4 +2364,61 @@ mod tests {
.collect()
})
}
#[gpui::test]
async fn test_format_patch(cx: &mut TestAppContext) {
init_test(cx);
let fs = FakeFs::new(cx.executor());
fs.insert_tree(
path!("/dir"),
json!({"test.txt": "line 1\nline 2\nline 3\n"}),
)
.await;
let project = Project::test(fs.clone(), [path!("/dir").as_ref()], cx).await;
let action_log = cx.new(|_| ActionLog::new(project.clone()));
let file_path = project
.read_with(cx, |project, cx| {
project.find_project_path("dir/test.txt", cx)
})
.unwrap();
let buffer = project
.update(cx, |project, cx| project.open_buffer(file_path, cx))
.await
.unwrap();
cx.update(|cx| {
// Track the buffer and mark it as read first
action_log.update(cx, |log, cx| {
log.buffer_read(buffer.clone(), cx);
});
// Make some edits to create a patch
buffer.update(cx, |buffer, cx| {
buffer
.edit([(Point::new(1, 0)..Point::new(1, 6), "CHANGED")], None, cx)
.unwrap(); // Replace "line2" with "CHANGED"
});
});
cx.run_until_parked();
// Get the patch
let patch = action_log.update(cx, |log, cx| log.unnotified_user_edits(cx));
// Verify the patch format contains expected unified diff elements
assert_eq!(
patch.unwrap(),
indoc! {"
--- a/dir/test.txt
+++ b/dir/test.txt
@@ -1,3 +1,3 @@
line 1
-line 2
+CHANGED
line 3
"}
);
}
}

View File

@@ -25,10 +25,15 @@ fn preprocess_json_schema(json: &mut Value) -> Result<()> {
// `additionalProperties` defaults to `false` unless explicitly specified.
// This prevents models from hallucinating tool parameters.
if let Value::Object(obj) = json {
if let Some(Value::String(type_str)) = obj.get("type") {
if type_str == "object" && !obj.contains_key("additionalProperties") {
if matches!(obj.get("type"), Some(Value::String(s)) if s == "object") {
if !obj.contains_key("additionalProperties") {
obj.insert("additionalProperties".to_string(), Value::Bool(false));
}
// OpenAI API requires non-missing `properties`
if !obj.contains_key("properties") {
obj.insert("properties".to_string(), Value::Object(Default::default()));
}
}
}
Ok(())

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