From 47c31fc4a6f226e5ba22b90f914a9cad0aac57a3 Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Wed, 28 Oct 2026 22:58:28 +0800 Subject: [PATCH 1/6] Validate daemon against the direct SDK API --- bt-daemon/Cargo.lock | 304 ++++++------------------------------------- bt-daemon/Cargo.toml | 2 +- 2 files changed, 40 insertions(+), 266 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index 4699e9ae..d8d0f262 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -124,29 +124,6 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" -[[package]] -name = "aws-lc-rs" -version = "1.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc" -dependencies = [ - "cc", - "cmake", - "dunce", - "fs_extra", - "pkg-config", -] - [[package]] name = "axum" version = "0.8.9" @@ -219,12 +196,6 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" - [[package]] name = "bitflags" version = "2.13.1" @@ -268,13 +239,13 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=45a2c88ca9d9ccc393ec0338ac438199fc3c5df2#45a2c88ca9d9ccc393ec0338ac438199fc3c5df2" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=63b446b21e0f1b22dccb3e6343a86038dd1b761c#63b446b21e0f1b22dccb3e6343a86038dd1b761c" dependencies = [ "anyhow", "arc-swap", "async-trait", "backoff", - "base64 0.23.1", + "base64", "bon", "bytes", "chrono", @@ -282,11 +253,11 @@ dependencies = [ "futures", "indexmap", "regex", - "reqwest 0.13.5", + "reqwest", "serde", "serde_json", "serde_repr", - "thiserror", + "thiserror 1.0.69", "tokio", "tracing", "url", @@ -300,7 +271,7 @@ dependencies = [ "anyhow", "async-trait", "axum", - "base64 0.22.1", + "base64", "braintrust-sdk-rust", "bytes", "chrono", @@ -310,7 +281,7 @@ dependencies = [ "muse-code-sdk", "parking_lot", "regex", - "reqwest 0.12.28", + "reqwest", "rquickjs", "rquickjs-serde", "rusqlite", @@ -320,7 +291,7 @@ dependencies = [ "sha2", "sysinfo", "tempfile", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "tracing-subscriber", @@ -437,31 +408,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" -[[package]] -name = "cmake" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" -dependencies = [ - "cc", -] - [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" -[[package]] -name = "combine" -version = "4.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4356eba6976435498d05a311ee9fc486da3bc81c200d3f0d7dd9703b41913f92" -dependencies = [ - "bytes", - "memchr", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -635,12 +587,6 @@ dependencies = [ "syn 2.0.119", ] -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - [[package]] name = "equivalent" version = "1.0.2" @@ -718,12 +664,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - [[package]] name = "futures" version = "0.3.33" @@ -986,6 +926,7 @@ dependencies = [ "hyper", "hyper-util", "rustls", + "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -997,7 +938,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64 0.22.1", + "base64", "bytes", "futures-channel", "futures-util", @@ -1184,55 +1125,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" -[[package]] -name = "jni" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" -dependencies = [ - "cfg-if", - "combine", - "jni-macros", - "jni-sys", - "log", - "simd_cesu8", - "thiserror", - "walkdir", - "windows-link", -] - -[[package]] -name = "jni-macros" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" -dependencies = [ - "proc-macro2", - "quote", - "rustc_version", - "simd_cesu8", - "syn 2.0.119", -] - -[[package]] -name = "jni-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" -dependencies = [ - "jni-sys-macros", -] - -[[package]] -name = "jni-sys-macros" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" -dependencies = [ - "quote", - "syn 2.0.119", -] - [[package]] name = "jobserver" version = "0.1.35" @@ -1367,7 +1259,7 @@ dependencies = [ "nix", "serde", "serde_json", - "thiserror", + "thiserror 2.0.19", "tokio", ] @@ -1530,7 +1422,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror", + "thiserror 2.0.19", "tokio", "tracing", "web-time", @@ -1542,7 +1434,6 @@ version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ - "aws-lc-rs", "bytes", "getrandom 0.4.3", "lru-slab", @@ -1553,7 +1444,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror", + "thiserror 2.0.19", "tinyvec", "tracing", "web-time", @@ -1697,42 +1588,7 @@ version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ - "base64 0.22.1", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "js-sys", - "log", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-util", - "tower", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams 0.4.2", - "web-sys", -] - -[[package]] -name = "reqwest" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" -dependencies = [ - "base64 0.23.1", + "base64", "bytes", "futures-core", "futures-util", @@ -1749,10 +1605,11 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", + "rustls-native-certs", "rustls-pki-types", - "rustls-platform-verifier", "serde", "serde_json", + "serde_urlencoded", "sync_wrapper", "tokio", "tokio-rustls", @@ -1763,7 +1620,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams 0.5.0", + "wasm-streams", "web-sys", ] @@ -1840,15 +1697,6 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" -[[package]] -name = "rustc_version" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - [[package]] name = "rustix" version = "1.1.4" @@ -1868,8 +1716,8 @@ version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ - "aws-lc-rs", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1898,40 +1746,12 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-platform-verifier" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" -dependencies = [ - "core-foundation", - "core-foundation-sys", - "jni", - "log", - "once_cell", - "rustls", - "rustls-native-certs", - "rustls-platform-verifier-android", - "rustls-webpki", - "security-framework", - "security-framework-sys", - "webpki-root-certs", - "windows-sys 0.61.2", -] - -[[package]] -name = "rustls-platform-verifier-android" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" - [[package]] name = "rustls-webpki" version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ - "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1949,15 +1769,6 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "schannel" version = "0.1.29" @@ -2121,22 +1932,6 @@ dependencies = [ "libc", ] -[[package]] -name = "simd_cesu8" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" -dependencies = [ - "rustc_version", - "simdutf8", -] - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - [[package]] name = "slab" version = "0.4.12" @@ -2245,13 +2040,33 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + [[package]] name = "thiserror" version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl", + "thiserror-impl 2.0.19", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -2543,16 +2358,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "walkdir" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" -dependencies = [ - "same-file", - "winapi-util", -] - [[package]] name = "want" version = "0.3.1" @@ -2636,19 +2441,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasm-streams" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "web-sys" version = "0.3.103" @@ -2669,15 +2461,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-root-certs" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ec80e73fd8baf57bf0d9615554c75348bda990d6d5bbeab964dd068319fecb" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi" version = "0.3.9" @@ -2694,15 +2477,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" -dependencies = [ - "windows-sys 0.61.2", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2857,7 +2631,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" dependencies = [ "assert-json-diff", - "base64 0.22.1", + "base64", "deadpool", "futures", "http", diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index d38f914c..251cf04f 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "45a2c88ca9d9ccc393ec0338ac438199fc3c5df2" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "63b446b21e0f1b22dccb3e6343a86038dd1b761c" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" From 6232ffa9cef0a8d518a9b0d27543a851e3ad64d6 Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Thu, 29 Oct 2026 02:41:41 +0800 Subject: [PATCH 2/6] Validate daemon against extensible SDK API --- bt-daemon/Cargo.lock | 303 +++++++++++++++++++++++++++++++++++++------ bt-daemon/Cargo.toml | 2 +- 2 files changed, 266 insertions(+), 39 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index d8d0f262..e1c1ae98 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -124,6 +124,29 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "048006790404103c488e6c5616b3e7e702a71292aadda08e8f7698a9e0d2eb53" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bfbe32ac36b3c428696ce315464181bc4029d689fd58e3f2a4e58c252242f52" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + [[package]] name = "axum" version = "0.8.9" @@ -196,6 +219,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "bitflags" version = "2.13.1" @@ -239,13 +268,13 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=63b446b21e0f1b22dccb3e6343a86038dd1b761c#63b446b21e0f1b22dccb3e6343a86038dd1b761c" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=821bf4d331193e2c40abce5c22eefca794c91f25#821bf4d331193e2c40abce5c22eefca794c91f25" dependencies = [ "anyhow", "arc-swap", "async-trait", "backoff", - "base64", + "base64 0.23.1", "bon", "bytes", "chrono", @@ -253,11 +282,11 @@ dependencies = [ "futures", "indexmap", "regex", - "reqwest", + "reqwest 0.13.5", "serde", "serde_json", "serde_repr", - "thiserror 1.0.69", + "thiserror", "tokio", "tracing", "url", @@ -271,7 +300,7 @@ dependencies = [ "anyhow", "async-trait", "axum", - "base64", + "base64 0.22.1", "braintrust-sdk-rust", "bytes", "chrono", @@ -281,7 +310,7 @@ dependencies = [ "muse-code-sdk", "parking_lot", "regex", - "reqwest", + "reqwest 0.12.28", "rquickjs", "rquickjs-serde", "rusqlite", @@ -291,7 +320,7 @@ dependencies = [ "sha2", "sysinfo", "tempfile", - "thiserror 2.0.19", + "thiserror", "tokio", "tracing", "tracing-subscriber", @@ -408,12 +437,31 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "combine" +version = "4.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4356eba6976435498d05a311ee9fc486da3bc81c200d3f0d7dd9703b41913f92" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "core-foundation" version = "0.10.1" @@ -587,6 +635,12 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "equivalent" version = "1.0.2" @@ -664,6 +718,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures" version = "0.3.33" @@ -926,7 +986,6 @@ dependencies = [ "hyper", "hyper-util", "rustls", - "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -938,7 +997,7 @@ version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-util", @@ -1125,6 +1184,55 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + [[package]] name = "jobserver" version = "0.1.35" @@ -1259,7 +1367,7 @@ dependencies = [ "nix", "serde", "serde_json", - "thiserror 2.0.19", + "thiserror", "tokio", ] @@ -1422,7 +1530,7 @@ dependencies = [ "rustc-hash", "rustls", "socket2", - "thiserror 2.0.19", + "thiserror", "tokio", "tracing", "web-time", @@ -1434,6 +1542,7 @@ version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" dependencies = [ + "aws-lc-rs", "bytes", "getrandom 0.4.3", "lru-slab", @@ -1444,7 +1553,7 @@ dependencies = [ "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.19", + "thiserror", "tinyvec", "tracing", "web-time", @@ -1588,7 +1697,42 @@ version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ - "base64", + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", +] + +[[package]] +name = "reqwest" +version = "0.13.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" +dependencies = [ + "base64 0.23.1", "bytes", "futures-core", "futures-util", @@ -1605,8 +1749,8 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", @@ -1620,7 +1764,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", "web-sys", ] @@ -1697,6 +1841,15 @@ version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b1e7f9a428571be2dc5bc0505c13fb6bf936822b894ec87abf8a08a4e51742d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1716,8 +1869,8 @@ version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ + "aws-lc-rs", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki", "subtle", @@ -1746,12 +1899,40 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f" + [[package]] name = "rustls-webpki" version = "0.103.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -1769,6 +1950,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.29" @@ -1932,6 +2122,22 @@ dependencies = [ "libc", ] +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "slab" version = "0.4.12" @@ -2040,33 +2246,13 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - [[package]] name = "thiserror" version = "2.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" dependencies = [ - "thiserror-impl 2.0.19", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "thiserror-impl", ] [[package]] @@ -2358,6 +2544,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -2441,6 +2637,19 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "web-sys" version = "0.3.103" @@ -2461,6 +2670,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2477,6 +2695,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2631,7 +2858,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08db1edfb05d9b3c1542e521aea074442088292f00b5f28e435c714a98f85031" dependencies = [ "assert-json-diff", - "base64", + "base64 0.22.1", "deadpool", "futures", "http", diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index 251cf04f..627690fd 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "63b446b21e0f1b22dccb3e6343a86038dd1b761c" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "821bf4d331193e2c40abce5c22eefca794c91f25" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" From f4f58fdbffefc31c830dbf24622ae0f5e0cb7f3e Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Thu, 29 Oct 2026 17:32:14 +0800 Subject: [PATCH 3/6] Update Rust SDK revision --- bt-daemon/Cargo.lock | 6 +++--- bt-daemon/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index e1c1ae98..8d46d312 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=821bf4d331193e2c40abce5c22eefca794c91f25#821bf4d331193e2c40abce5c22eefca794c91f25" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=d8ada65116de28ea4300cc934b45495e268b622d#d8ada65116de28ea4300cc934b45495e268b622d" dependencies = [ "anyhow", "arc-swap", @@ -1917,7 +1917,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] @@ -2701,7 +2701,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index 627690fd..c9f23297 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "821bf4d331193e2c40abce5c22eefca794c91f25" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "d8ada65116de28ea4300cc934b45495e268b622d" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" From 079ea92c7cd88ac3a06fc7a7c5e4d74b5338c563 Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Thu, 29 Oct 2026 17:38:56 +0800 Subject: [PATCH 4/6] Update Rust SDK revision --- bt-daemon/Cargo.lock | 2 +- bt-daemon/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index 8d46d312..1209ec96 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=d8ada65116de28ea4300cc934b45495e268b622d#d8ada65116de28ea4300cc934b45495e268b622d" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=5655b087a3991b5d278366d1a45aaaceafcfe303#5655b087a3991b5d278366d1a45aaaceafcfe303" dependencies = [ "anyhow", "arc-swap", diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index c9f23297..9b4cd107 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "d8ada65116de28ea4300cc934b45495e268b622d" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "5655b087a3991b5d278366d1a45aaaceafcfe303" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" From 84a340ad1bbc683fe1371bb4d6dc5128cf150490 Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Thu, 29 Oct 2026 18:07:15 +0800 Subject: [PATCH 5/6] Validate Rust SDK retry and ingestion changes --- bt-daemon/Cargo.lock | 2 +- bt-daemon/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index 1209ec96..6568085c 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=5655b087a3991b5d278366d1a45aaaceafcfe303#5655b087a3991b5d278366d1a45aaaceafcfe303" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=019b888019939e2a4ccb87e039a2d676da641d64#019b888019939e2a4ccb87e039a2d676da641d64" dependencies = [ "anyhow", "arc-swap", diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index 9b4cd107..06ecb993 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "5655b087a3991b5d278366d1a45aaaceafcfe303" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "019b888019939e2a4ccb87e039a2d676da641d64" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" From e49b08442c75c6514c8f622577625f12077f46ac Mon Sep 17 00:00:00 2001 From: Stephen Belanger Date: Thu, 29 Oct 2026 19:36:48 +0800 Subject: [PATCH 6/6] Track Rust SDK delivery completions --- bt-daemon/Cargo.lock | 78 ++++++------------- bt-daemon/Cargo.toml | 2 +- bt-daemon/src/pipeline/submission.rs | 64 +++++++++++++++- bt-daemon/src/sink/braintrust.rs | 110 +++++++++++++++++++++------ 4 files changed, 171 insertions(+), 83 deletions(-) diff --git a/bt-daemon/Cargo.lock b/bt-daemon/Cargo.lock index 6568085c..9cfaf31c 100644 --- a/bt-daemon/Cargo.lock +++ b/bt-daemon/Cargo.lock @@ -84,9 +84,9 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "arc-swap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +checksum = "380962b3d93b99642e50b9febf72c071e97e8b32d86eae9cf4ef582bb960ae6e" dependencies = [ "rustversion", ] @@ -268,7 +268,7 @@ dependencies = [ [[package]] name = "braintrust-sdk-rust" version = "0.1.0-alpha.2" -source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=019b888019939e2a4ccb87e039a2d676da641d64#019b888019939e2a4ccb87e039a2d676da641d64" +source = "git+https://github.com/braintrustdata/braintrust-sdk-rust?rev=1e4f901fe44b028f9a3ea59a204d7651cc38acfc#1e4f901fe44b028f9a3ea59a204d7651cc38acfc" dependencies = [ "anyhow", "arc-swap", @@ -278,11 +278,12 @@ dependencies = [ "bon", "bytes", "chrono", - "crossbeam", + "crossbeam-utils", "futures", "indexmap", "regex", "reqwest 0.13.5", + "sdd", "serde", "serde_json", "serde_repr", @@ -496,61 +497,11 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" -dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-common" @@ -1950,6 +1901,12 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "saa" +version = "5.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd85992a680de788217d9c70b74aa7685b108cf1aba02f728fb27f1b27199ad1" + [[package]] name = "same-file" version = "1.0.6" @@ -1974,6 +1931,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sdd" +version = "4.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31877eee03686b905845993b5d9809a220c9dd5a10e9d6021d7ca67384c9070" +dependencies = [ + "saa", +] + [[package]] name = "security-framework" version = "3.7.0" diff --git a/bt-daemon/Cargo.toml b/bt-daemon/Cargo.toml index 06ecb993..0817618d 100644 --- a/bt-daemon/Cargo.toml +++ b/bt-daemon/Cargo.toml @@ -23,7 +23,7 @@ expect_used = "deny" [dependencies] # Keep this pinned exactly, matching the dependency policy used by `bt`. -braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "019b888019939e2a4ccb87e039a2d676da641d64" } +braintrust-sdk-rust = { git = "https://github.com/braintrustdata/braintrust-sdk-rust", rev = "1e4f901fe44b028f9a3ea59a204d7651cc38acfc" } base64 = "0.22" anyhow = "1" muse-code-sdk = "=1.4.12" diff --git a/bt-daemon/src/pipeline/submission.rs b/bt-daemon/src/pipeline/submission.rs index 634cb26f..6fc401c2 100644 --- a/bt-daemon/src/pipeline/submission.rs +++ b/bt-daemon/src/pipeline/submission.rs @@ -54,7 +54,25 @@ impl std::error::Error for Failure { impl Failure { fn classify(cause: anyhow::Error) -> Self { - let retry = match cause.downcast_ref::() { + let sdk_error = cause + .downcast_ref::() + .or_else( + || match cause.downcast_ref::() { + Some(braintrust_sdk_rust::FlushError::Delivery(failure)) => { + failure.cause().cause().downcast_ref() + } + _ => None, + }, + ) + .or_else( + || match cause.downcast_ref::() { + Some(braintrust_sdk_rust::WriteError::Delivery(failure)) => { + failure.cause().downcast_ref() + } + _ => None, + }, + ); + let retry = match sdk_error { Some(braintrust_sdk_rust::BraintrustError::Api { status: 401, .. }) => { RetryCondition::Credentials } @@ -121,3 +139,47 @@ impl Stage for Submission { } } } + +#[cfg(test)] +mod tests { + use super::*; + use braintrust_sdk_rust::{BraintrustClient, ParentSpanInfo, SpanLog}; + use wiremock::{ + matchers::{method, path}, + Mock, MockServer, ResponseTemplate, + }; + + #[tokio::test] + async fn classifies_delivery_errors_from_both_flush_and_write() { + let server = MockServer::start().await; + Mock::given(method("POST")) + .and(path("/logs3")) + .respond_with( + ResponseTemplate::new(400).set_delay(std::time::Duration::from_millis(50)), + ) + .mount(&server) + .await; + let client = BraintrustClient::builder() + .skip_login(true) + .api_url(server.uri()) + .app_url(server.uri()) + .build() + .await + .unwrap(); + let span = client + .span_builder_with_credentials("token", "org") + .parent_info(ParentSpanInfo::ProjectLogs { + object_id: "project".into(), + }) + .build(); + let write = span.log(SpanLog::builder().build().unwrap()); + let flush = client.flush().await.unwrap_err(); + let write = write.await.unwrap_err(); + for error in [anyhow::Error::new(flush), anyhow::Error::new(write)] { + assert!(matches!( + Failure::classify(error).retry, + RetryCondition::Configuration { recheck: false } + )); + } + } +} diff --git a/bt-daemon/src/sink/braintrust.rs b/bt-daemon/src/sink/braintrust.rs index 4f036eba..8b019dfb 100644 --- a/bt-daemon/src/sink/braintrust.rs +++ b/bt-daemon/src/sink/braintrust.rs @@ -1,6 +1,6 @@ //! The Braintrust sink: maps sink-neutral [`SpanOp`]s onto `braintrust-sdk-rust`. //! -//! Each routing branch owns its checked SDK queue. Clients are built lazily +//! Each routing branch owns its SDK queue and write completions. Clients are built lazily //! using its configured backend URLs; flush results cannot include another //! branch's rejected operations. Within a client, each //! session's token/org travel per span (`span_builder_with_credentials`) and @@ -12,8 +12,8 @@ use super::{Sink, SinkFactory}; use crate::translate::{SpanOp, SpanRow, SpanType}; use crate::wire::{SessionConfig, TraceDestination}; use braintrust_sdk_rust::{ - BraintrustClient, ParentSpanInfo, SpanComponents, SpanHandle, SpanLog, SpanObjectType, - SpanType as SdkSpanType, DEFAULT_API_URL, DEFAULT_APP_URL, + BraintrustClient, Completion, DeliveryReceipt, ParentSpanInfo, SpanComponents, SpanHandle, + SpanLog, SpanObjectType, SpanType as SdkSpanType, WriteError, DEFAULT_API_URL, DEFAULT_APP_URL, }; use serde_json::{json, Map, Value}; use std::collections::{HashMap, VecDeque}; @@ -37,6 +37,7 @@ struct ClientCache { const CLIENT_CACHE_CAPACITY: usize = 16; const QUEUE_FLUSH_BYTE_BUDGET: usize = 8 * 1024 * 1024; +const MAX_PENDING_COMPLETIONS: usize = 1024; #[derive(Default)] struct ClientCacheState { @@ -50,15 +51,10 @@ struct CachedClient { } impl CachedClient { - async fn account_and_flush(&self, bytes: usize) -> anyhow::Result<()> { + async fn account(&self, bytes: usize) -> bool { let mut queued_bytes = self.queued_bytes.lock().await; *queued_bytes = queued_bytes.saturating_add(bytes); - if *queued_bytes < QUEUE_FLUSH_BYTE_BUDGET { - return Ok(()); - } - self.client.flush().await.map_err(anyhow::Error::new)?; - *queued_bytes = 0; - Ok(()) + *queued_bytes >= QUEUE_FLUSH_BYTE_BUDGET } async fn flush(&self) -> anyhow::Result<()> { @@ -115,7 +111,6 @@ impl ClientCache { } let client = BraintrustClient::builder() .skip_login(true) - .checked_delivery(true) .api_url(api_url.to_string()) .app_url(app_url.to_string()) .build() @@ -161,6 +156,7 @@ impl SinkFactory for BraintrustSinkFactory { client: None, open: HashMap::new(), pending_roots: HashMap::new(), + pending_completions: Vec::new(), delivered_root: None, })) } @@ -200,6 +196,8 @@ struct BraintrustSink { /// Roots marked by translators as provisional, keyed by their local span /// id. Each is exported only once direct descendant work arrives. pending_roots: HashMap>, + /// Retain acknowledgements even when automatic delivery finishes before flush. + pending_completions: Vec>, /// Root span id of the trace that most recently received a row, which /// is also that root's deterministic row id in Braintrust. delivered_root: Option, @@ -285,9 +283,13 @@ impl BraintrustSink { let handle = self.open.get(&row.span_id).ok_or_else(|| { anyhow::anyhow!("span handle was not initialized for {}", row.span_id) })?; - handle.log(build_log(row, &self.source, false)?); - if let Some(end) = row.end_ms { - handle.end_with_time(ms_to_secs(end)); + let completion = handle.log(build_log(row, &self.source, false)?); + if let Err(error) = completion.submission() { + return Err(anyhow::anyhow!("braintrust span admission failed: {error}")); + } + self.pending_completions.push(completion); + if row.end_ms.is_some() { + // build_log includes the end metric in this tracked write. // SpanHandle retains the complete accumulated input/output. Once a // span is terminal, use stateless SDK merges for any unusually late // update instead of pinning that payload for the session lifetime. @@ -296,7 +298,7 @@ impl BraintrustSink { Ok(()) } - fn merge_closed(&self, client: &BraintrustClient, row: &SpanRow) -> anyhow::Result<()> { + fn merge_closed(&mut self, client: &BraintrustClient, row: &SpanRow) -> anyhow::Result<()> { let creds = self .creds .as_ref() @@ -315,14 +317,16 @@ impl BraintrustSink { context.remove("span_origin"); } } - client - .update_span_with_credentials( + let completion = client + .update_span_with_credentials_tracked( creds.token.clone(), creds.org_id.clone(), &components.to_str(), build_log(row, &self.source, true)?, ) - .map_err(|error| anyhow::anyhow!("braintrust span merge failed: {error}")) + .map_err(|error| anyhow::anyhow!("braintrust span merge failed: {error}"))?; + self.pending_completions.push(completion); + Ok(()) } fn span_components(&self, row: &SpanRow, creds: &Creds, project: &str) -> SpanComponents { @@ -361,9 +365,11 @@ impl BraintrustSink { } SpanOp::Merge(row) => self.merge_closed(&client.client, row)?, } - client - .account_and_flush(serialized_len(op).unwrap_or(0)) - .await + let over_budget = client.account(serialized_len(op).unwrap_or(0)).await; + if over_budget || self.pending_completions.len() >= MAX_PENDING_COMPLETIONS { + self.flush().await?; + } + Ok(()) } } @@ -451,10 +457,18 @@ impl Sink for BraintrustSink { } async fn flush(&mut self) -> anyhow::Result<()> { - match &self.client { - Some(client) => client.flush().await, - None => Ok(()), + let mut failure = match &self.client { + Some(client) => client.flush().await.err(), + None => None, + }; + for completion in self.pending_completions.drain(..) { + if let Err(error) = completion.await { + if failure.is_none() { + failure = Some(anyhow::Error::new(error)); + } + } } + failure.map_or(Ok(()), Err) } fn has_pending_delivery(&self) -> bool { @@ -771,6 +785,53 @@ mod tests { use wiremock::matchers::{method, path}; use wiremock::{Mock, MockServer, ResponseTemplate}; + #[tokio::test] + async fn sink_flush_observes_failure_already_retired_by_sdk() { + let server = MockServer::start().await; + Mock::given(method("POST")) + .and(path("/logs3")) + .respond_with(ResponseTemplate::new(401)) + .mount(&server) + .await; + let client = BraintrustClient::builder() + .skip_login(true) + .api_url(server.uri()) + .app_url(server.uri()) + .build() + .await + .unwrap(); + let handle = client + .span_builder_with_credentials("token", "org") + .parent_info(ParentSpanInfo::ProjectLogs { + object_id: "project".into(), + }) + .build(); + let completion = handle.log(SpanLog::builder().input(json!("value")).build().unwrap()); + // Complete and retire the failed batch before the sink issues its flush. + // Depending on scheduling, the automatic worker may already have + // retired the failure, in which case this barrier succeeds. + let _ = client.flush().await; + let cached = Arc::new(CachedClient { + client, + queued_bytes: AsyncMutex::new(0), + }); + let mut sink = BraintrustSink { + cache: Arc::new(ClientCache::new()), + default_api_url: None, + default_app_url: None, + source: "codex".into(), + creds: None, + urls: None, + client: Some(cached), + open: HashMap::new(), + pending_roots: HashMap::new(), + pending_completions: vec![completion], + delivered_root: None, + }; + assert!(sink.flush().await.is_err()); + assert!(sink.flush().await.is_ok()); + } + #[tokio::test] async fn root_context_retains_sdk_environment_on_insert_and_stateless_merge() { let server = MockServer::start().await; @@ -786,7 +847,6 @@ mod tests { .await; let client = BraintrustClient::builder() .skip_login(true) - .checked_delivery(true) .api_url(server.uri()) .app_url(server.uri()) .environment("test", Some("sink-test"))