Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 19 additions & 19 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ categories = ["network-programming", "web-programming::http-server"]

# 二进制走 CalVer,crate 走 SemVer —— 两者是两回事,卖给不同的人。
# 这里是 crate 的版本。
version = "0.75.0"
version = "0.76.0"

[workspace.dependencies]
# ── 内部 crate ───────────────────────────────────────────
Expand Down
16 changes: 16 additions & 0 deletions release-notes/0.76.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
This release makes `/live` report how fast running requests are generating right now, so a client can show a live speed during a long request, and names a broken answer body instead of reporting a decoding error.

**Upgrade notes**

- The control-plane protocol version is now 49. ThinkWatch Lite must be upgraded together with core: a Lite release with protocol 48 does not connect to 0.76.0, and the other way round.
- The request store's schema and the configuration are unchanged; nothing is cleared.
- For crates that embed the gateway: `Ending::streaming` takes the gateway's `pace` table, `AppState` has a `pace` field, `tw_observe::Meter` and `EventBus::meter` are new, and `tw_engine::TextTokens` is public. The public API of `tw_guard` is unchanged.

**Live generation speed.** `/live` used to give the speed of requests that finished in the last minute, so it had nothing to show while a long request ran.
- The gateway keeps reading a successful stream after its first token and estimates the output as it arrives: text, reasoning text and tool arguments, with the same rule as the input estimate.
- The estimate is multiplied by a ratio per upstream and model. Each streaming request that ends with reported usage updates that ratio (moving average, bounded between 0.5 and 2; skipped when reasoning was hidden). Gemini's cumulative usage in the stream is used when it is higher.
- `LiveView.tokens_per_sec` is the total of the running requests over the last 3 seconds: null when nothing runs, 0 when requests run but none is generating yet.
- `RunningView` has `tokens_per_sec` and `output_tokens` for each running request, null before the first token and for non-streaming requests.
- The speed recorded for a finished request is unchanged and still uses the usage the upstream reports.

**Broken answer bodies.** An upstream that hung up in the middle of an answer was reported as "error decoding response body". Such failures now have their own code, `gw.upstream.body_broken`, with the causes spelled out, and `gw.upstream.forward_failed` carries every cause, with the URL reduced to its origin.
Loading