Skip to content

language_models: Fix the partial json streaming to not blast \ everywhere#51976

Merged
Veykril merged 1 commit intozed-industries:mainfrom
feitreim:bugfix-llm-response-streaming
Mar 20, 2026
Merged

language_models: Fix the partial json streaming to not blast \ everywhere#51976
Veykril merged 1 commit intozed-industries:mainfrom
feitreim:bugfix-llm-response-streaming

Conversation

@feitreim
Copy link
Copy Markdown
Contributor

Context

This PR fixes one of the issues in #51905, where model outputs are full of errant \ characters.

heres the problem: As the response is streamed back to zed, we accumulate the message chunks and and need to convert those chunks to valid json, to do that we use partial_json_fixer::fix_json, when the last character of a chunk is \, the fix_json has to escape that backslash, because its inside of a string (if it isn't, its invalid json and the tool call will crash) and other wise you would end up escaping the end " and everything would be messed up.

why is this a problem for zed:
T_0 is the output at some step.
T_1 is the output at the next step.

the fix_json system is meant to be used by replacing T_0 with T_1, however in the editor, replacing the entirety of T_0 with T_1 would be slow/cause flickering/etc.. so we calculate the difference between T_0 and T_1 and just add it to the current buffer state. So when a chunk ends on \, we end up with something like ... end of line\\"} at the end of T_0,
in T_1, this becomes ... end of line\n .... then when we add the new chunk from T_1, it just picks up after the \n because its tracking the length to manage the deltas.

How to Review

utils.rs:
fix_streamed_json => remove trailing backslashes from incoming json streams so that partial_json_fixer::fix_json doesn't try to escape them.
other files: call fix_streamed_json before passing to serde_json

I had claude write a bunch of tests while I was working on the fix, which I have kept in for now, but the end functionality of fix_streamed_json is really simple now, so maybe these arent really needed.

Videos

Behavior Before:

before.mov

Behavior After:

after.mov

Self-Review Checklist

  • I've reviewed my own diff for quality, security, and reliability
  • Unsafe blocks (if any) have justifying comments
  • The content is consistent with the UI/UX checklist
  • Tests cover the new/changed behavior
  • Performance impact has been considered and is acceptable

Release Notes:

  • language_models: fixed partial json streaming

@cla-bot cla-bot bot added the cla-signed The user has signed the Contributor License Agreement label Mar 19, 2026
@zed-codeowner-coordinator zed-codeowner-coordinator bot requested review from a team and removed request for a team March 19, 2026 22:31
@zed-community-bot zed-community-bot bot added the guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions label Mar 19, 2026
@SomeoneToIgnore SomeoneToIgnore added the area:ai Improvement related to Agent Panel, Edit Prediction, Copilot, or other AI features label Mar 19, 2026
@danilo-leal danilo-leal removed their assignment Mar 19, 2026
Copy link
Copy Markdown
Member

@Veykril Veykril left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@Veykril Veykril self-assigned this Mar 20, 2026
@Veykril Veykril enabled auto-merge (squash) March 20, 2026 07:01
@Veykril Veykril merged commit fdf144f into zed-industries:main Mar 20, 2026
49 checks passed
AmaanBilwar pushed a commit to AmaanBilwar/zed that referenced this pull request Mar 20, 2026
…ywhere (zed-industries#51976)

## Context

This PR fixes one of the issues in zed-industries#51905, where model outputs are full
of errant `\` characters.

heres the problem: As the response is streamed back to zed, we
accumulate the message chunks and and need to convert those chunks to
valid json, to do that we use `partial_json_fixer::fix_json`, when the
last character of a chunk is `\`, the `fix_json` has to escape that
backslash, because its inside of a string (if it isn't, its invalid json
and the tool call will crash) and other wise you would end up escaping
the end `"` and everything would be messed up.

why is this a problem for zed:
T_0 is the output at some step.
T_1 is the output at the next step.

the `fix_json` system is meant to be used by replacing T_0 with T_1,
however in the editor, replacing the entirety of T_0 with T_1 would be
slow/cause flickering/etc.. so we calculate the difference between T_0
and T_1 and just add it to the current buffer state. So when a chunk
ends on `\`, we end up with something like `... end of line\\"}` at the
end of T_0,
in T_1, this becomes `... end of line\n ...`. then when we add the new
chunk from T_1, it just picks up after the \n because its tracking the
length to manage the deltas.


## How to Review

utils.rs:
fix_streamed_json => remove trailing backslashes from incoming json
streams so that `partial_json_fixer::fix_json` doesn't try to escape
them.
other files: call fix_streamed_json before passing to `serde_json`

I had claude write a bunch of tests while I was working on the fix,
which I have kept in for now, but the end functionality of
fix_streamed_json is really simple now, so maybe these arent really
needed.

## Videos
Behavior Before:


https://github.com/user-attachments/assets/f23f5579-b2e1-4d71-9e24-f15ea831de52

Behavior After:


https://github.com/user-attachments/assets/40acdc23-4522-4621-be28-895965f4f262


## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- language_models: fixed partial json streaming
@feitreim feitreim deleted the bugfix-llm-response-streaming branch March 20, 2026 15:26
toshmukhamedov pushed a commit to toshmukhamedov/zed that referenced this pull request Mar 20, 2026
…ywhere (zed-industries#51976)

## Context

This PR fixes one of the issues in zed-industries#51905, where model outputs are full
of errant `\` characters.

heres the problem: As the response is streamed back to zed, we
accumulate the message chunks and and need to convert those chunks to
valid json, to do that we use `partial_json_fixer::fix_json`, when the
last character of a chunk is `\`, the `fix_json` has to escape that
backslash, because its inside of a string (if it isn't, its invalid json
and the tool call will crash) and other wise you would end up escaping
the end `"` and everything would be messed up.

why is this a problem for zed:
T_0 is the output at some step.
T_1 is the output at the next step.

the `fix_json` system is meant to be used by replacing T_0 with T_1,
however in the editor, replacing the entirety of T_0 with T_1 would be
slow/cause flickering/etc.. so we calculate the difference between T_0
and T_1 and just add it to the current buffer state. So when a chunk
ends on `\`, we end up with something like `... end of line\\"}` at the
end of T_0,
in T_1, this becomes `... end of line\n ...`. then when we add the new
chunk from T_1, it just picks up after the \n because its tracking the
length to manage the deltas.


## How to Review

utils.rs:
fix_streamed_json => remove trailing backslashes from incoming json
streams so that `partial_json_fixer::fix_json` doesn't try to escape
them.
other files: call fix_streamed_json before passing to `serde_json`

I had claude write a bunch of tests while I was working on the fix,
which I have kept in for now, but the end functionality of
fix_streamed_json is really simple now, so maybe these arent really
needed.

## Videos
Behavior Before:


https://github.com/user-attachments/assets/f23f5579-b2e1-4d71-9e24-f15ea831de52

Behavior After:


https://github.com/user-attachments/assets/40acdc23-4522-4621-be28-895965f4f262


## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- language_models: fixed partial json streaming
AmaanBilwar pushed a commit to AmaanBilwar/zed that referenced this pull request Mar 23, 2026
…ywhere (zed-industries#51976)

## Context

This PR fixes one of the issues in zed-industries#51905, where model outputs are full
of errant `\` characters.

heres the problem: As the response is streamed back to zed, we
accumulate the message chunks and and need to convert those chunks to
valid json, to do that we use `partial_json_fixer::fix_json`, when the
last character of a chunk is `\`, the `fix_json` has to escape that
backslash, because its inside of a string (if it isn't, its invalid json
and the tool call will crash) and other wise you would end up escaping
the end `"` and everything would be messed up.

why is this a problem for zed:
T_0 is the output at some step.
T_1 is the output at the next step.

the `fix_json` system is meant to be used by replacing T_0 with T_1,
however in the editor, replacing the entirety of T_0 with T_1 would be
slow/cause flickering/etc.. so we calculate the difference between T_0
and T_1 and just add it to the current buffer state. So when a chunk
ends on `\`, we end up with something like `... end of line\\"}` at the
end of T_0,
in T_1, this becomes `... end of line\n ...`. then when we add the new
chunk from T_1, it just picks up after the \n because its tracking the
length to manage the deltas.


## How to Review

utils.rs:
fix_streamed_json => remove trailing backslashes from incoming json
streams so that `partial_json_fixer::fix_json` doesn't try to escape
them.
other files: call fix_streamed_json before passing to `serde_json`

I had claude write a bunch of tests while I was working on the fix,
which I have kept in for now, but the end functionality of
fix_streamed_json is really simple now, so maybe these arent really
needed.

## Videos
Behavior Before:


https://github.com/user-attachments/assets/f23f5579-b2e1-4d71-9e24-f15ea831de52

Behavior After:


https://github.com/user-attachments/assets/40acdc23-4522-4621-be28-895965f4f262


## Self-Review Checklist

<!-- Check before requesting review: -->
- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- language_models: fixed partial json streaming
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:ai Improvement related to Agent Panel, Edit Prediction, Copilot, or other AI features cla-signed The user has signed the Contributor License Agreement guild Pull requests by someone in Zed Guild. NOTE: the label application is automated via github actions Size M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants