diff --git a/Cargo.lock b/Cargo.lock index 69b9599a..aa6d27e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3143,7 +3143,7 @@ dependencies = [ [[package]] name = "tw-api" -version = "0.75.0" +version = "0.76.0" dependencies = [ "serde", "serde_json", @@ -3154,7 +3154,7 @@ dependencies = [ [[package]] name = "tw-bedrock" -version = "0.75.0" +version = "0.76.0" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -3175,7 +3175,7 @@ dependencies = [ [[package]] name = "tw-breaker" -version = "0.75.0" +version = "0.76.0" dependencies = [ "serde", "serde_json", @@ -3183,7 +3183,7 @@ dependencies = [ [[package]] name = "tw-config" -version = "0.75.0" +version = "0.76.0" dependencies = [ "blake3", "libc", @@ -3208,7 +3208,7 @@ dependencies = [ [[package]] name = "tw-control" -version = "0.75.0" +version = "0.76.0" dependencies = [ "axum", "base64", @@ -3251,7 +3251,7 @@ dependencies = [ [[package]] name = "tw-dialect" -version = "0.75.0" +version = "0.76.0" dependencies = [ "memchr", "serde", @@ -3260,7 +3260,7 @@ dependencies = [ [[package]] name = "tw-engine" -version = "0.75.0" +version = "0.76.0" dependencies = [ "chrono", "serde", @@ -3274,7 +3274,7 @@ dependencies = [ [[package]] name = "tw-gateway" -version = "0.75.0" +version = "0.76.0" dependencies = [ "arc-swap", "async-stream", @@ -3325,7 +3325,7 @@ dependencies = [ [[package]] name = "tw-guard" -version = "0.75.0" +version = "0.76.0" dependencies = [ "aho-corasick", "base64", @@ -3343,7 +3343,7 @@ dependencies = [ [[package]] name = "tw-link" -version = "0.75.0" +version = "0.76.0" dependencies = [ "serde", "serde_json", @@ -3357,7 +3357,7 @@ dependencies = [ [[package]] name = "tw-observe" -version = "0.75.0" +version = "0.76.0" dependencies = [ "tokio", "tracing", @@ -3366,7 +3366,7 @@ dependencies = [ [[package]] name = "tw-plugin" -version = "0.75.0" +version = "0.76.0" dependencies = [ "libc", "rand 0.10.2", @@ -3381,7 +3381,7 @@ dependencies = [ [[package]] name = "tw-pricing" -version = "0.75.0" +version = "0.76.0" dependencies = [ "arc-swap", "flate2", @@ -3394,14 +3394,14 @@ dependencies = [ [[package]] name = "tw-secret" -version = "0.75.0" +version = "0.76.0" dependencies = [ "thiserror", ] [[package]] name = "tw-store" -version = "0.75.0" +version = "0.76.0" dependencies = [ "blake3", "bytes", @@ -3421,7 +3421,7 @@ dependencies = [ [[package]] name = "tw-types" -version = "0.75.0" +version = "0.76.0" dependencies = [ "serde", "serde_json", @@ -3430,7 +3430,7 @@ dependencies = [ [[package]] name = "tw-watch" -version = "0.75.0" +version = "0.76.0" dependencies = [ "libc", "notify", @@ -3441,7 +3441,7 @@ dependencies = [ [[package]] name = "tw-yaml" -version = "0.75.0" +version = "0.76.0" dependencies = [ "saphyr-parser", "serde_yaml_ng", @@ -3451,7 +3451,7 @@ dependencies = [ [[package]] name = "twcore" -version = "0.75.0" +version = "0.76.0" dependencies = [ "anyhow", "axum", diff --git a/Cargo.toml b/Cargo.toml index 436260ae..8d4796e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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 ─────────────────────────────────────────── diff --git a/release-notes/0.76.0.md b/release-notes/0.76.0.md new file mode 100644 index 00000000..6fc28ae4 --- /dev/null +++ b/release-notes/0.76.0.md @@ -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.