diff --git a/Cargo.lock b/Cargo.lock index c82f98cf..104c42c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -329,7 +329,7 @@ dependencies = [ "serde", "serde_json", "thiserror 2.0.18", - "tokio-tungstenite", + "tokio-tungstenite 0.29.0", "zeroize", ] @@ -886,7 +886,7 @@ dependencies = [ "sha1 0.10.7", "sync_wrapper", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.29.0", "tower", "tower-layer", "tower-service", @@ -1239,9 +1239,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -1249,9 +1249,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -1261,9 +1261,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.4" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", @@ -1809,9 +1809,9 @@ dependencies = [ [[package]] name = "dimpl" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa936d6931067b24f3467ae6d1747a7985b5713aec477aacea2d1d8995234e8" +checksum = "07d467d37bfdcc290bb8dcbedc8ca356eb730e46459b1687f98c3bae28aa6814" dependencies = [ "aes", "arrayvec", @@ -2517,16 +2517,17 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "ddc03d96684f9226b8a787cdb71488417b53ab5ea8fdb1dac946cb9431cc8bff" dependencies = [ - "base64 0.22.1", + "base64 0.23.1", "bytes", "futures-channel", "futures-util", "http", "http-body", + "httparse", "hyper", "ipnet", "libc", @@ -2790,9 +2791,9 @@ checksum = "6a756c3fac73139e83f14c2d742155dd2b78d3ee56597b419a0579b7bdd6dd78" [[package]] name = "is" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d08f9118d003d441f79c1070e84d0a2a89f35721ca8ae0cd5e1f9026dc4a2517" +checksum = "b6edbbdc611843e8c65878ee735f68c495cede11ae5a9582b17fe0369c456ef5" dependencies = [ "crc", "serde", @@ -2956,9 +2957,9 @@ dependencies = [ [[package]] name = "jsonschema" -version = "0.52.1" +version = "0.58.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e842fa72fd1e50ca4676a527641c13f5ee0d423ac699bfe1cd2afa3a4fdbac" +checksum = "ea18b8d5e1469b1bdd6b349169305141316a7c26da27f239773b65c830c0f5d6" dependencies = [ "ahash", "bytecount", @@ -2985,22 +2986,23 @@ dependencies = [ [[package]] name = "jsonschema-regex" -version = "0.52.1" +version = "0.58.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d90ea83fa606c96f0b4737ecedf1fa6b624272022edc42039565f8d8af0b78" +checksum = "854e9e22c420535035e95eed240cbfb4a5f4b7da74d122d63144e0c31926dbfd" dependencies = [ "regex-syntax", ] [[package]] name = "jsonschema-value" -version = "0.52.1" +version = "0.58.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4ab4cbe58181a117d8c3582844ce20b07184319b51ba6d756596c1c451aebc" +checksum = "4e3bfac11ac357ec620880025757d38c67da8fd5b9ef5024d19f0f360002b4ca" dependencies = [ "ahash", "bytecount", "fraction", + "getrandom 0.3.4", "num-cmp", "num-traits", "serde_json", @@ -3009,9 +3011,9 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "11.0.0" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881733cbc631fc9e472e24447ce32a64bedf2da498d6d8570b08edc87de71f65" +checksum = "e75fe14a82d81e5f5af639997db37d8b96045938a7ac6ab18cdbe1c7467e05e1" dependencies = [ "aws-lc-rs", "base64 0.22.1", @@ -3125,7 +3127,7 @@ dependencies = [ "tar", "tempfile", "tokio", - "tokio-tungstenite", + "tokio-tungstenite 0.30.0", "tokio-util", "toml", "toml_edit", @@ -3763,9 +3765,9 @@ dependencies = [ [[package]] name = "opus-pure" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de6a3cef053e1fdea38a5e50edb0789590a31184c5a59f6cd5e462fe844793e7" +checksum = "4de7c2ad44427a636b27bf0b03eb29e713775ba1b45ff31a0618c19ee5adb215" [[package]] name = "ordered-float" @@ -4344,11 +4346,12 @@ dependencies = [ [[package]] name = "ratatui-image" -version = "11.0.8" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399baa06251282b0c1bbb5762848cf98a6b7b84f44af7f0daf3213ace16df4f0" +checksum = "9593d10c61ec2007f429d1fafc4f4a19fecdbae4d06b531a2d505227fb82f5ea" dependencies = [ "base64-simd", + "flate2", "icy_sixel", "image", "rand 0.8.8", @@ -4423,9 +4426,9 @@ dependencies = [ [[package]] name = "referencing" -version = "0.52.1" +version = "0.58.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38a014525040cdc9893361b7419bcf1f43b7ba7055eabaf6d91d6b75caa8b3f" +checksum = "590efadb0a669f1712c1e3ab810a55d4c3d20d0127c455f7236dd0710aba0346" dependencies = [ "ahash", "fluent-uri", @@ -4810,9 +4813,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctp-proto" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a22cbe1d867f74fc377b9e63ac74457ea7dcfda23a0deaba6af083ad7e060019" +checksum = "250132c5814c3d4f01269ee7a261450bc38dd5119280262d3c13a40062cfde55" dependencies = [ "bytes", "crc", @@ -5243,9 +5246,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "str0m" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8522aa06c731cfdc1488e32de7fcebcfc8d9d86d49a6ecc95a64779fe7b545f2" +checksum = "018e4267976f45bf568c146b559bbabd2e823a9dc8c10b5b86e83118b597b89c" dependencies = [ "arrayvec", "base64ct", @@ -5572,6 +5575,18 @@ dependencies = [ "tungstenite 0.29.0", ] +[[package]] +name = "tokio-tungstenite" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17a073bfed563fa236697a068031408a93cd9522e08abf9933ead3e73411bd71" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.30.0", +] + [[package]] name = "tokio-util" version = "0.7.19" @@ -5590,9 +5605,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.5+spec-1.1.0" +version = "1.1.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" dependencies = [ "indexmap 2.14.0", "serde_core", @@ -5614,9 +5629,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.13+spec-1.1.0" +version = "0.25.15+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6975367e4d2ef766d86af01ffad14b622fecc8d4357a998fbc4deb6e9bacaf9b" +checksum = "1340ea94a5856333492c9064b02c778b191dd2c853778d9609debdcdfea3a614" dependencies = [ "indexmap 2.14.0", "toml_datetime", @@ -5961,9 +5976,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.0" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" dependencies = [ "getrandom 0.4.3", "js-sys", diff --git a/Cargo.toml b/Cargo.toml index 4c8a4f9d..18eeb121 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "kit" version = "0.2.8" edition = "2024" -rust-version = "1.94.0" +rust-version = "1.99.0" publish = false [features] @@ -26,9 +26,9 @@ tui = [ ] [dependencies] -opus-pure = { version = "=0.2.1", default-features = false, optional = true } -str0m = { version = "=0.23.1", default-features = false, features = ["aws-lc-rs"], optional = true } -tokio-tungstenite = { version = "=0.29.0", default-features = false, features = ["handshake"], optional = true } +opus-pure = { version = "=0.2.2", default-features = false, optional = true } +str0m = { version = "=0.24.0", default-features = false, features = ["aws-lc-rs"], optional = true } +tokio-tungstenite = { version = "=0.30.0", default-features = false, features = ["handshake"], optional = true } a2a-protocol-client = "=0.11.0" a2a-protocol-server = { version = "=0.11.0", default-features = false } a2a-protocol-types = "=0.11.0" @@ -57,24 +57,24 @@ axum = "=0.8.9" base64 = "=0.23.1" blake3 = "=1.8.7" bytes = "=1.12.1" -clap = { version = "=4.6.6", features = ["derive"] } +clap = { version = "=4.6.7", features = ["derive"] } crossterm = { version = "=0.29.0", features = ["event-stream"], optional = true } flate2 = "=1.1.10" ignore = "=0.4.33" futures-util = "=0.3.34" getrandom = "=0.4.3" hyper = "=1.11.1" -hyper-util = { version = "=0.1.20", features = ["server", "http1", "http2", "tokio"] } +hyper-util = { version = "=0.1.21", features = ["server", "http1", "http2", "tokio"] } image = { version = "=0.25.10", default-features = false, features = ["gif", "jpeg", "png", "webp"] } -jsonwebtoken = { version = "=11.0.0", default-features = false, features = ["aws_lc_rs"] } +jsonwebtoken = { version = "=11.1.0", default-features = false, features = ["aws_lc_rs"] } keyring = { version = "=4.2.0", default-features = false, features = ["v1"] } -jsonschema = { version = "=0.52.1", default-features = false, features = ["idna"] } +jsonschema = { version = "=0.58.5", default-features = false, features = ["idna"] } neo_frizbee = "=0.11.0" opentelemetry = { version = "=0.32.0", default-features = false, features = ["trace"] } opentelemetry-otlp = { version = "=0.32.0", default-features = false, features = ["grpc-tonic", "http-proto", "http-json", "reqwest-client", "tls-webpki-roots", "trace"] } opentelemetry_sdk = { version = "=0.32.1", default-features = false, features = ["experimental_trace_batch_span_processor_with_async_runtime", "rt-tokio", "trace"] } ratatui = { version = "=0.30.2", default-features = false, features = ["crossterm", "layout-cache"], optional = true } -ratatui-image = { version = "=11.0.8", default-features = false, features = ["crossterm"], optional = true } +ratatui-image = { version = "=11.1.0", default-features = false, features = ["crossterm"], optional = true } reqwest = { version = "=0.13.5", default-features = false, features = ["blocking", "form", "rustls", "stream"] } rmcp = { version = "=3.2.0", default-features = false, features = ["auth", "client"] } rpassword = "=7.5.4" @@ -86,8 +86,8 @@ sha2 = "=0.11.0" subtle = "=2.6.1" tar = { version = "=0.4.46", default-features = false } tempfile = "=3.27.0" -toml = "=1.1.5" -toml_edit = { version = "=0.25.13", default-features = false, features = ["parse", "display"] } +toml = "=1.1.6" +toml_edit = { version = "=0.25.15", default-features = false, features = ["parse", "display"] } tokio = { version = "=1.53.1", features = ["fs", "io-util", "macros", "net", "process", "rt-multi-thread", "signal", "sync", "time"] } tokio-util = { version = "=0.7.19", features = ["compat"] } tower = { version = "=0.5.3", features = ["util"] } @@ -97,7 +97,7 @@ tracing-subscriber = { version = "=0.3.23", default-features = false, features = unicode-segmentation = { version = "=1.13.3", optional = true } unicode-width = { version = "=0.2.2", optional = true } url = "=2.5.8" -uuid = { version = "=1.26.0", features = ["v5"] } +uuid = { version = "=1.26.1", features = ["v5"] } zip = { version = "=8.6.0", default-features = false, features = ["deflate-flate2-zlib-rs"] } zeroize = { version = "=1.9.0", features = ["derive"] } @@ -121,7 +121,7 @@ windows-sys = { version = "=0.61.2", features = [ ] } [dev-dependencies] -jsonwebtoken = { version = "=11.0.0", default-features = false, features = ["aws_lc_rs", "use_pem"] } +jsonwebtoken = { version = "=11.1.0", default-features = false, features = ["aws_lc_rs", "use_pem"] } tokio = { version = "=1.53.1", features = ["test-util"] } # Deny also in test builds; only test-only scopes may relax ergonomics. Crate diff --git a/Dockerfile b/Dockerfile index bcd39c10..924cf329 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,7 @@ # Published flavors are built from the named final stages: bookworm, slim, # and alpine. The unqualified image uses the final `default` stage, which # intentionally aliases slim. -ARG RUST_VERSION=1.94.0 +ARG RUST_VERSION=1.99.0 ARG DEBIAN_SUITE=bookworm ARG ALPINE_VERSION=3.23 ARG VERSION=source diff --git a/README.md b/README.md index 08b72f09..11c0c5f4 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ USER kit ```sh git clone https://github.com/speakeasy-api/kit && cd kit -mise install # Rust 1.94 with rustfmt and clippy; Python and XcodeGen on macOS +mise install # Rust 1.99 with rustfmt and clippy; Python and XcodeGen on macOS mise run setup:linux # Debian/Ubuntu only: C/C++, CMake, pkg-config, ALSA/PulseAudio headers (sudo) mise run install # cargo install into ~/.cargo/bin mise run dev -- tui --root . # cargo run; arguments pass through diff --git a/mise.toml b/mise.toml index 0435bd12..07a0a911 100644 --- a/mise.toml +++ b/mise.toml @@ -1,7 +1,7 @@ min_version = "2026.7.0" [tools] -rust = { version = "1.94.0", profile = "minimal", components = "rustfmt,clippy" } +rust = { version = "1.99.0", profile = "minimal", components = "rustfmt,clippy" } python = { version = "3.13", os = ["macos"] } # Checksum-pinned release archive; scripts/generate-macos-project.sh also verifies the binary hash. "http:xcodegen" = { version = "2.45.4", os = ["macos"], url = "https://github.com/yonaskolb/XcodeGen/releases/download/2.45.4/xcodegen.zip", checksum = "sha256:090ec29491aad50aec10631bf6e62253fed733c50f3aab0f5ffc86bc170bdbef", bin_path = "xcodegen/bin" } diff --git a/src/managed_files.rs b/src/managed_files.rs index 4df5522f..ec26b636 100644 --- a/src/managed_files.rs +++ b/src/managed_files.rs @@ -480,7 +480,7 @@ impl Selection { return Err("compose return exceeds file-selection traversal budget".into()); } let mut entries = object.iter().collect::>(); - entries.sort_unstable_by(|(a, _), (b, _)| a.cmp(b)); + entries.sort_unstable_by_key(|(a, _)| *a); for (key, child) in entries { if key.len() > MAX_HEADER_BYTES { return Err("compose return key exceeds file-selection label budget".into()); diff --git a/src/plugins.rs b/src/plugins.rs index 9b25b608..d758c984 100644 --- a/src/plugins.rs +++ b/src/plugins.rs @@ -3328,7 +3328,7 @@ fn parse_sha256(value: &str) -> Result<[u8; 32], String> { return Err("plugin archive sha256 must contain exactly 64 hexadecimal characters".into()); } let mut digest = [0u8; 32]; - for (index, pair) in value.as_bytes().chunks_exact(2).enumerate() { + for (index, pair) in value.as_bytes().as_chunks::<2>().0.iter().enumerate() { let text = std::str::from_utf8(pair) .map_err(|error| format!("could not parse plugin archive sha256: {error}"))?; digest[index] = u8::from_str_radix(text, 16) diff --git a/src/protocols/acp.rs b/src/protocols/acp.rs index 157737c6..4ba0e85f 100644 --- a/src/protocols/acp.rs +++ b/src/protocols/acp.rs @@ -699,7 +699,7 @@ impl SessionRegistry { pub(super) fn next_token(&self) -> Result { self.inner .next_token - .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |token| { + .try_update(Ordering::Relaxed, Ordering::Relaxed, |token| { token.checked_add(1) }) .map_err(|_| AcpRuntimeError::Loop("ACP session registry token space exhausted".into())) diff --git a/src/tools/mcp.rs b/src/tools/mcp.rs index bc175739..5e89b06e 100644 --- a/src/tools/mcp.rs +++ b/src/tools/mcp.rs @@ -1872,7 +1872,7 @@ impl McpRuntime { let generation = self .inner .next_event_route - .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |next| { + .try_update(Ordering::Relaxed, Ordering::Relaxed, |next| { next.checked_add(1) }) .map_err(|_| "MCP event route generation space exhausted".to_string())?; diff --git a/src/tui/markdown.rs b/src/tui/markdown.rs index f6670e61..3f2237e2 100644 --- a/src/tui/markdown.rs +++ b/src/tui/markdown.rs @@ -892,10 +892,7 @@ fn next_link<'a>( let mut balance = source[start..end].bytes().fold(0isize, |balance, byte| { balance + isize::from(byte == b')') - isize::from(byte == b'(') }); - loop { - let Some(character) = source[..end].chars().next_back() else { - break; - }; + while let Some(character) = source[..end].chars().next_back() { let unmatched_close = character == ')' && balance > 0; if matches!( character, diff --git a/src/tui/ui.rs b/src/tui/ui.rs index 069fc55e..30a9dca7 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -907,11 +907,11 @@ fn cost_label(amount: f64, currency: &str) -> String { fn gauge_spans(used: u64, size: u64) -> Vec> { const CELLS: u64 = 10; const COMPACT_AT: u64 = 8; - let filled = if size == 0 { - 0 - } else { - (used.saturating_mul(CELLS) / size).min(CELLS) - }; + let filled = used + .saturating_mul(CELLS) + .checked_div(size) + .unwrap_or(0) + .min(CELLS); let fill = Style::default().fg(if filled >= COMPACT_AT { theme::warn_color() } else { @@ -2658,11 +2658,11 @@ fn agent_lines( /// Six-cell context gauge for an agent row, followed by a space. fn agent_gauge(used: u64, size: u64) -> Vec> { const CELLS: u64 = 6; - let filled = if size == 0 { - 0 - } else { - (used.saturating_mul(CELLS) / size).min(CELLS) - }; + let filled = used + .saturating_mul(CELLS) + .checked_div(size) + .unwrap_or(0) + .min(CELLS); let fill = Style::default().fg(if used.saturating_mul(10) >= size.saturating_mul(8) { theme::warn_color() } else { diff --git a/src/voice/native.rs b/src/voice/native.rs index 8d26ef1e..191b1ec9 100644 --- a/src/voice/native.rs +++ b/src/voice/native.rs @@ -1,9 +1,9 @@ //! Native, actor-owned WebRTC transport. The caller exchanges `offer` for an SDP //! answer, then calls `accept_answer`. No browser, subprocess, or signaling I/O. //! -//! API verified against str0m 0.23.1 (aws-lc-rs), cubeb 0.38.0 on Linux, +//! API verified against str0m 0.24.0 (aws-lc-rs), cubeb 0.38.0 on Linux, //! cpal 0.18.2 elsewhere, -//! and opus-pure 0.2.1, all with default features disabled. TUI availability is +//! and opus-pure 0.2.2, all with default features disabled. TUI availability is //! gated by the default-off experimental.voice startup setting. //! Supply a concrete local interface address; no STUN/TURN discovery is performed. //! The answer must contain reachable ICE candidates. Capture starts closed. @@ -176,7 +176,7 @@ fn negotiation(bind: SocketAddr) -> Result<(Rtc, Mid, ChannelId, String, SdpPend let mut rtc = Rtc::builder() .set_crypto_provider(str0m::crypto::from_feature_flags().into()) .clear_codecs() - .enable_opus(true) + .enable_opus(true, false) .set_reordering_size_audio(10) .set_send_buffer_audio(50) .build(Instant::now()); @@ -612,7 +612,7 @@ mod tests { let mut peer = Rtc::builder() .set_crypto_provider(str0m::crypto::from_feature_flags().into()) .clear_codecs() - .enable_opus(true) + .enable_opus(true, false) .build(Instant::now()); peer.add_local_candidate( Candidate::host("127.0.0.1:19003".parse().unwrap(), "udp").unwrap(),