diff --git a/.github/workflows/rust-release.yml b/.github/workflows/rust-release.yml index d3e44e270f..b9eab3e0fd 100644 --- a/.github/workflows/rust-release.yml +++ b/.github/workflows/rust-release.yml @@ -84,11 +84,13 @@ jobs: shell: bash run: | set -euo pipefail + cpu_model="$(lscpu | awk -F: '/Model name/ {gsub(/^[ \t]+/, "", $2); print $2; exit}')" + total_ram="$(awk '/MemTotal/ {printf "%.1f GiB\n", $2 / 1024 / 1024}' /proc/meminfo)" echo "Runner: ${RUNNER_NAME:-unknown}" echo "OS: $(uname -a)" - echo "CPU model: $(lscpu | awk -F: '/Model name/ {gsub(/^[ \t]+/,\"\",$2); print $2; exit}')" + echo "CPU model: ${cpu_model}" echo "Logical CPUs: $(nproc)" - echo "Total RAM: $(awk '/MemTotal/ {printf \"%.1f GiB\\n\", $2 / 1024 / 1024}' /proc/meminfo)" + echo "Total RAM: ${total_ram}" echo "Disk usage:" df -h . - name: Print runner specs (macOS) @@ -96,13 +98,14 @@ jobs: shell: bash run: | set -euo pipefail + total_ram="$(sysctl -n hw.memsize | awk '{printf "%.1f GiB\n", $1 / 1024 / 1024 / 1024}')" echo "Runner: ${RUNNER_NAME:-unknown}" echo "OS: $(sw_vers -productName) $(sw_vers -productVersion)" echo "Hardware model: $(sysctl -n hw.model)" echo "CPU architecture: $(uname -m)" echo "Logical CPUs: $(sysctl -n hw.logicalcpu)" echo "Physical CPUs: $(sysctl -n hw.physicalcpu)" - echo "Total RAM: $(sysctl -n hw.memsize | awk '{printf \"%.1f GiB\\n\", $1 / 1024 / 1024 / 1024}')" + echo "Total RAM: ${total_ram}" echo "Disk usage:" df -h . - name: Install Linux bwrap build dependencies diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index e33b2f2a83..16616e334f 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -430,9 +430,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ded5f9a03ac8f24d1b8a25101ee812cd32cdc8c50a4c50237de2c4915850e73" +checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" dependencies = [ "rustversion", ] @@ -1227,9 +1227,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.57" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" +checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" dependencies = [ "clap_builder", "clap_derive", @@ -1237,9 +1237,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.57" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", @@ -1379,7 +1379,7 @@ dependencies = [ "time", "tokio", "tokio-tungstenite", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", "tracing", "tracing-subscriber", "uuid", @@ -1539,7 +1539,7 @@ dependencies = [ "supports-color 3.0.2", "tempfile", "tokio", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", "tracing", ] @@ -1585,7 +1585,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "tokio", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", "tracing", ] @@ -1650,7 +1650,7 @@ dependencies = [ "sha2", "thiserror 2.0.18", "tokio", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", ] [[package]] @@ -1743,8 +1743,8 @@ dependencies = [ "tokio", "tokio-tungstenite", "tokio-util", - "toml 0.9.12+spec-1.1.0", - "toml_edit 0.24.1+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", + "toml_edit 0.24.0+spec-1.1.0", "tracing", "tracing-subscriber", "tracing-test", @@ -2327,7 +2327,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -2392,7 +2392,7 @@ dependencies = [ "codex-protocol", "pretty_assertions", "serde", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", ] [[package]] @@ -2430,7 +2430,7 @@ version = "0.0.0" dependencies = [ "pretty_assertions", "serde_json", - "toml 0.9.12+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", ] [[package]] @@ -3386,9 +3386,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.4" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" +checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" dependencies = [ "log", ] @@ -3708,9 +3708,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.9" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" dependencies = [ "crc32fast", "libz-sys", @@ -4043,19 +4043,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "getrandom" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasip2", - "wasip3", -] - [[package]] name = "gif" version = "0.14.1" @@ -4082,7 +4069,7 @@ dependencies = [ "bstr", "log", "regex-automata", - "regex-syntax 0.8.9", + "regex-syntax 0.8.8", ] [[package]] @@ -4388,7 +4375,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.6", + "webpki-roots 1.0.5", ] [[package]] @@ -4422,13 +4409,14 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.20" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", + "futures-core", "futures-util", "http 1.4.0", "http-body", @@ -4661,12 +4649,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -4977,9 +4959,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.19" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89a5b5e10d5a9ad6e5d1f4bd58225f655d6fe9767575a5e8ac5a6fe64e04495" +checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50" dependencies = [ "jiff-static", "log", @@ -4990,9 +4972,9 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.19" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff7a39c8862fc1369215ccf0a8f12dd4598c7f6484704359f0351bd617034dbf" +checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78" dependencies = [ "proc-macro2", "quote", @@ -5136,17 +5118,11 @@ dependencies = [ "spin", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" -version = "0.2.181" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libdbus-sys" @@ -5406,9 +5382,9 @@ checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "memchr" -version = "2.8.0" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memoffset" @@ -6566,16 +6542,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.114", -] - [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -6632,16 +6598,16 @@ dependencies = [ [[package]] name = "proptest" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bitflags 2.10.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax 0.8.9", + "regex-syntax 0.8.8", "unarray", ] @@ -6670,9 +6636,9 @@ dependencies = [ [[package]] name = "psl" -version = "2.1.188" +version = "2.1.184" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d75bca9da25cfdcd9528de22ed7870d1695b9e1c3ce55b7127a4a2b16fac" +checksum = "81dc6a90669f481b41cae3005c68efa36bef275b95aa9123a7af7f1c68c6e5b2" dependencies = [ "psl-types", ] @@ -7080,7 +7046,7 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls", - "webpki-roots 1.0.6", + "webpki-roots 1.0.5", "x509-parser", ] @@ -7326,25 +7292,25 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.9", + "regex-syntax 0.8.8", ] [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.9", + "regex-syntax 0.8.8", ] [[package]] name = "regex-lite" -version = "0.1.9" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" +checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" [[package]] name = "regex-syntax" @@ -7354,9 +7320,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "reqwest" @@ -7404,7 +7370,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.6", + "webpki-roots 1.0.5", ] [[package]] @@ -7687,9 +7653,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "salsa20" @@ -7956,11 +7922,10 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "sentry" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92d893ba7469d361a6958522fa440e4e2bc8bf4c5803cd1bf40b9af63f8f9a8" +checksum = "2f925d575b468e88b079faf590a8dd0c9c99e2ec29e9bab663ceb8b45056312f" dependencies = [ - "cfg_aliases 0.2.1", "httpdate", "native-tls", "reqwest", @@ -7977,9 +7942,9 @@ dependencies = [ [[package]] name = "sentry-actix" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56cb150fd6b55b3023714a3aaa1e3bdadfd44f164efc54fad69efc69aac36887" +checksum = "18bac0f6b8621fa0f85e298901e51161205788322e1a995e3764329020368058" dependencies = [ "actix-http", "actix-web", @@ -7990,9 +7955,9 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f8784d0a27b5cd4b5f75769ffc84f0b7580e3c35e1af9cd83cb90b612d769cc" +checksum = "6cb1ef7534f583af20452b1b1bf610a60ed9c8dd2d8485e7bd064efc556a78fb" dependencies = [ "backtrace", "regex", @@ -8001,9 +7966,9 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e5eb42f4cd4f9fdfec9e3b07b25a4c9769df83d218a7e846658984d5948ad3e" +checksum = "ebd6be899d9938390b6d1ec71e2f53bd9e57b6a9d8b1d5b049e5c364e7da9078" dependencies = [ "hostname", "libc", @@ -8015,9 +7980,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0b1e7ca40f965db239da279bf278d87b7407469b98835f27f0c8e59ed189b06" +checksum = "26ab054c34b87f96c3e4701bea1888317cde30cc7e4a6136d2c48454ab96661c" dependencies = [ "rand 0.9.2", "sentry-types", @@ -8028,9 +7993,9 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002561e49ea3a9de316e2efadc40fae553921b8ff41448f02ea85fd135a778d6" +checksum = "5637ec550dc6f8c49a711537950722d3fc4baa6fd433c371912104eaff31e2a5" dependencies = [ "findshlibs", "sentry-core", @@ -8038,9 +8003,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8906f8be87aea5ac7ef937323fb655d66607427f61007b99b7cb3504dc5a156c" +checksum = "3f02c7162f7b69b8de872b439d4696dc1d65f80b13ddd3c3831723def4756b63" dependencies = [ "sentry-backtrace", "sentry-core", @@ -8048,9 +8013,9 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b07eefe04486316c57aba08ab53dd44753c25102d1d3fe05775cc93a13262d9" +checksum = "e1dd47df349a80025819f3d25c3d2f751df705d49c65a4cdc0f130f700972a48" dependencies = [ "bitflags 2.10.0", "sentry-backtrace", @@ -8061,9 +8026,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.46.2" +version = "0.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567711f01f86a842057e1fc17779eba33a336004227e1a1e7e6cc2599e22e259" +checksum = "eecbd63e9d15a26a40675ed180d376fcb434635d2e33de1c24003f61e3e2230d" dependencies = [ "debugid", "hex", @@ -8947,9 +8912,9 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.7.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.10.0", "core-foundation 0.9.4", @@ -8974,12 +8939,12 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.25.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.3.4", "once_cell", "rustix 1.1.3", "windows-sys 0.61.2", @@ -9364,9 +9329,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.12+spec-1.1.0" +version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ "indexmap 2.13.0", "serde_core", @@ -9400,9 +9365,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.24.1+spec-1.1.0" +version = "0.24.0+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01f2eadbbc6b377a847be05f60791ef1058d9f696ecb51d2c07fe911d8569d8e" +checksum = "8c740b185920170a6d9191122cafef7010bd6270a3824594bff6784c04d7f09e" dependencies = [ "indexmap 2.13.0", "toml_datetime", @@ -9413,9 +9378,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.7+spec-1.1.0" +version = "1.0.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "247eaa3197818b831697600aadf81514e577e0cba5eab10f7e064e78ae154df1" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" dependencies = [ "winnow", ] @@ -9616,9 +9581,9 @@ dependencies = [ [[package]] name = "tracing-test" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19a4c448db514d4f24c5ddb9f73f2ee71bfb24c526cf0c570ba142d1119e0051" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" dependencies = [ "tracing-core", "tracing-subscriber", @@ -9627,9 +9592,9 @@ dependencies = [ [[package]] name = "tracing-test-macro" -version = "0.2.6" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad06847b7afb65c7866a36664b75c40b895e318cea4f71299f013fb22965329d" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", "syn 2.0.114", @@ -9643,7 +9608,7 @@ checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" dependencies = [ "cc", "regex", - "regex-syntax 0.8.9", + "regex-syntax 0.8.8", "serde_json", "streaming-iterator", "tree-sitter-language", @@ -9812,9 +9777,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.23" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] name = "unicode-linebreak" @@ -9902,9 +9867,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.2.0" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" +checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" dependencies = [ "base64 0.22.1", "der", @@ -10061,15 +10026,6 @@ dependencies = [ "wit-bindgen", ] -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen", -] - [[package]] name = "wasite" version = "0.1.0" @@ -10135,28 +10091,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap 2.13.0", - "wasm-encoder", - "wasmparser", -] - [[package]] name = "wasm-streams" version = "0.4.2" @@ -10170,18 +10104,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.10.0", - "hashbrown 0.15.5", - "indexmap 2.13.0", - "semver", -] - [[package]] name = "wayland-backend" version = "0.3.12" @@ -10274,9 +10196,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.1.0" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" +checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" dependencies = [ "core-foundation 0.10.1", "jni", @@ -10290,9 +10212,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" dependencies = [ "rustls-pki-types", ] @@ -10303,14 +10225,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.6", + "webpki-roots 1.0.5", ] [[package]] name = "webpki-roots" -version = "1.0.6" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -10953,88 +10875,6 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap 2.13.0", - "prettyplease", - "syn 2.0.114", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.114", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.10.0", - "indexmap 2.13.0", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap 2.13.0", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] [[package]] name = "wl-clipboard-rs" @@ -11229,18 +11069,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" dependencies = [ "proc-macro2", "quote", @@ -11354,9 +11194,9 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.20" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4de98dfa5d5b7fef4ee834d0073d560c9ca7b6c46a71d058c48db7960f8cfaf7" +checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" [[package]] name = "zopfli" diff --git a/codex-rs/app-server-protocol/schema/json/EventMsg.json b/codex-rs/app-server-protocol/schema/json/EventMsg.json index e3e9a6e1ea..bdeb06b7b2 100644 --- a/codex-rs/app-server-protocol/schema/json/EventMsg.json +++ b/codex-rs/app-server-protocol/schema/json/EventMsg.json @@ -175,6 +175,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -184,35 +185,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index e90b50b47c..351e0e24f6 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -373,6 +373,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -382,35 +383,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { @@ -515,6 +487,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -524,35 +497,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo2", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index f3f1f57f39..76368ef194 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -1884,6 +1884,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -1893,35 +1894,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { @@ -10346,6 +10318,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -10355,35 +10328,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json index 2122dcf189..9c9b52d4ed 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ForkConversationResponse.json @@ -175,6 +175,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -184,35 +185,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json index 1610c21b5c..01bb2bbc20 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v1/ResumeConversationResponse.json @@ -175,6 +175,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -184,35 +185,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json index aef20e2ead..f68ec3331c 100644 --- a/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v1/SessionConfiguredNotification.json @@ -175,6 +175,7 @@ "enum": [ "context_window_exceeded", "usage_limit_exceeded", + "server_overloaded", "internal_server_error", "unauthorized", "bad_request", @@ -184,35 +185,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "model_cap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "model_cap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ErrorNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ErrorNotification.json index 17991ebaed..264a901c0f 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ErrorNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ErrorNotification.json @@ -8,6 +8,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -17,35 +18,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json index 3187f75f77..6194557811 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ReviewStartResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json index 06d4c9cffa..10b9d50007 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadForkResponse.json @@ -40,6 +40,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -49,35 +50,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json index dcac91e0dd..6fe793cc19 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadListResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json index 5760be15cb..444db89431 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadReadResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json index 8977c048a3..9b2fb74003 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadResumeResponse.json @@ -40,6 +40,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -49,35 +50,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json index 6c6f2d1eff..b6ec97be10 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadRollbackResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json index f2dbee3ca3..0d22e08810 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartResponse.json @@ -40,6 +40,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -49,35 +50,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json index 86d1e2940b..6a9324409e 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadStartedNotification.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json index 86f9f65925..2c1c9950fe 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ThreadUnarchiveResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json index 99d1f569c1..9fe3517e95 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnCompletedNotification.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json index 19bf47db87..116ded84cb 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartResponse.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json index c70f6f7cdf..276ab3b46b 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/TurnStartedNotification.json @@ -27,6 +27,7 @@ "enum": [ "contextWindowExceeded", "usageLimitExceeded", + "serverOverloaded", "internalServerError", "unauthorized", "badRequest", @@ -36,35 +37,6 @@ ], "type": "string" }, - { - "additionalProperties": false, - "properties": { - "modelCap": { - "properties": { - "model": { - "type": "string" - }, - "reset_after_seconds": { - "format": "uint64", - "minimum": 0.0, - "type": [ - "integer", - "null" - ] - } - }, - "required": [ - "model" - ], - "type": "object" - } - }, - "required": [ - "modelCap" - ], - "title": "ModelCapCodexErrorInfo", - "type": "object" - }, { "additionalProperties": false, "properties": { diff --git a/codex-rs/app-server-protocol/schema/typescript/CodexErrorInfo.ts b/codex-rs/app-server-protocol/schema/typescript/CodexErrorInfo.ts index 20dd2414bb..522b91ce20 100644 --- a/codex-rs/app-server-protocol/schema/typescript/CodexErrorInfo.ts +++ b/codex-rs/app-server-protocol/schema/typescript/CodexErrorInfo.ts @@ -5,4 +5,4 @@ /** * Codex errors that we expose to clients. */ -export type CodexErrorInfo = "context_window_exceeded" | "usage_limit_exceeded" | { "model_cap": { model: string, reset_after_seconds: bigint | null, } } | { "http_connection_failed": { http_status_code: number | null, } } | { "response_stream_connection_failed": { http_status_code: number | null, } } | "internal_server_error" | "unauthorized" | "bad_request" | "sandbox_error" | { "response_stream_disconnected": { http_status_code: number | null, } } | { "response_too_many_failed_attempts": { http_status_code: number | null, } } | "thread_rollback_failed" | "other"; +export type CodexErrorInfo = "context_window_exceeded" | "usage_limit_exceeded" | "server_overloaded" | { "http_connection_failed": { http_status_code: number | null, } } | { "response_stream_connection_failed": { http_status_code: number | null, } } | "internal_server_error" | "unauthorized" | "bad_request" | "sandbox_error" | { "response_stream_disconnected": { http_status_code: number | null, } } | { "response_too_many_failed_attempts": { http_status_code: number | null, } } | "thread_rollback_failed" | "other"; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/CodexErrorInfo.ts b/codex-rs/app-server-protocol/schema/typescript/v2/CodexErrorInfo.ts index a1e65c30c0..1ff409a41a 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/CodexErrorInfo.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/CodexErrorInfo.ts @@ -8,4 +8,4 @@ * When an upstream HTTP status is available (for example, from the Responses API or a provider), * it is forwarded in `httpStatusCode` on the relevant `codexErrorInfo` variant. */ -export type CodexErrorInfo = "contextWindowExceeded" | "usageLimitExceeded" | { "modelCap": { model: string, reset_after_seconds: bigint | null, } } | { "httpConnectionFailed": { httpStatusCode: number | null, } } | { "responseStreamConnectionFailed": { httpStatusCode: number | null, } } | "internalServerError" | "unauthorized" | "badRequest" | "threadRollbackFailed" | "sandboxError" | { "responseStreamDisconnected": { httpStatusCode: number | null, } } | { "responseTooManyFailedAttempts": { httpStatusCode: number | null, } } | "other"; +export type CodexErrorInfo = "contextWindowExceeded" | "usageLimitExceeded" | "serverOverloaded" | { "httpConnectionFailed": { httpStatusCode: number | null, } } | { "responseStreamConnectionFailed": { httpStatusCode: number | null, } } | "internalServerError" | "unauthorized" | "badRequest" | "threadRollbackFailed" | "sandboxError" | { "responseStreamDisconnected": { httpStatusCode: number | null, } } | { "responseTooManyFailedAttempts": { httpStatusCode: number | null, } } | "other"; diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index c1060bde48..69510df9f2 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -89,10 +89,7 @@ macro_rules! v2_enum_from_core { pub enum CodexErrorInfo { ContextWindowExceeded, UsageLimitExceeded, - ModelCap { - model: String, - reset_after_seconds: Option, - }, + ServerOverloaded, HttpConnectionFailed { #[serde(rename = "httpStatusCode")] #[ts(rename = "httpStatusCode")] @@ -129,13 +126,7 @@ impl From for CodexErrorInfo { match value { CoreCodexErrorInfo::ContextWindowExceeded => CodexErrorInfo::ContextWindowExceeded, CoreCodexErrorInfo::UsageLimitExceeded => CodexErrorInfo::UsageLimitExceeded, - CoreCodexErrorInfo::ModelCap { - model, - reset_after_seconds, - } => CodexErrorInfo::ModelCap { - model, - reset_after_seconds, - }, + CoreCodexErrorInfo::ServerOverloaded => CodexErrorInfo::ServerOverloaded, CoreCodexErrorInfo::HttpConnectionFailed { http_status_code } => { CodexErrorInfo::HttpConnectionFailed { http_status_code } } diff --git a/codex-rs/app-server/tests/suite/v2/app_list.rs b/codex-rs/app-server/tests/suite/v2/app_list.rs index 9290bae29c..6fce729084 100644 --- a/codex-rs/app-server/tests/suite/v2/app_list.rs +++ b/codex-rs/app-server/tests/suite/v2/app_list.rs @@ -120,6 +120,7 @@ async fn list_apps_uses_thread_feature_flag_when_thread_id_is_provided() -> Resu format!( r#" chatgpt_base_url = "{server_url}" +mcp_oauth_credentials_store = "file" [features] connectors = false @@ -791,6 +792,7 @@ fn write_connectors_config(codex_home: &std::path::Path, base_url: &str) -> std: format!( r#" chatgpt_base_url = "{base_url}" +mcp_oauth_credentials_store = "file" [features] connectors = true diff --git a/codex-rs/codex-api/src/error.rs b/codex-rs/codex-api/src/error.rs index e7fbd14543..c0a1719481 100644 --- a/codex-rs/codex-api/src/error.rs +++ b/codex-rs/codex-api/src/error.rs @@ -27,6 +27,8 @@ pub enum ApiError { RateLimit(String), #[error("invalid request: {message}")] InvalidRequest { message: String }, + #[error("server overloaded")] + ServerOverloaded, } impl From for ApiError { diff --git a/codex-rs/codex-api/src/sse/responses.rs b/codex-rs/codex-api/src/sse/responses.rs index c73c2bbf8e..d7ba3383b7 100644 --- a/codex-rs/codex-api/src/sse/responses.rs +++ b/codex-rs/codex-api/src/sse/responses.rs @@ -239,6 +239,8 @@ pub fn process_responses_event( .message .unwrap_or_else(|| "Invalid request.".to_string()); response_error = ApiError::InvalidRequest { message }; + } else if is_server_overloaded_error(&error) { + response_error = ApiError::ServerOverloaded; } else { let delay = try_parse_retry_after(&error); let message = error.message.unwrap_or_default(); @@ -425,6 +427,11 @@ fn is_invalid_prompt_error(error: &Error) -> bool { error.code.as_deref() == Some("invalid_prompt") } +fn is_server_overloaded_error(error: &Error) -> bool { + error.code.as_deref() == Some("server_is_overloaded") + || error.code.as_deref() == Some("slow_down") +} + fn rate_limit_regex() -> &'static regex_lite::Regex { static RE: std::sync::OnceLock = std::sync::OnceLock::new(); #[expect(clippy::unwrap_used)] diff --git a/codex-rs/core/src/api_bridge.rs b/codex-rs/core/src/api_bridge.rs index af45182c13..b461ac4ad9 100644 --- a/codex-rs/core/src/api_bridge.rs +++ b/codex-rs/core/src/api_bridge.rs @@ -10,7 +10,6 @@ use serde::Deserialize; use crate::auth::CodexAuth; use crate::error::CodexErr; -use crate::error::ModelCapError; use crate::error::RetryLimitReachedError; use crate::error::UnexpectedResponseError; use crate::error::UsageLimitReachedError; @@ -24,6 +23,7 @@ pub(crate) fn map_api_error(err: ApiError) -> CodexErr { ApiError::UsageNotIncluded => CodexErr::UsageNotIncluded, ApiError::Retryable { message, delay } => CodexErr::Stream(message, delay), ApiError::Stream(msg) => CodexErr::Stream(msg, None), + ApiError::ServerOverloaded => CodexErr::ServerOverloaded, ApiError::Api { status, message } => CodexErr::UnexpectedStatus(UnexpectedResponseError { status, body: message, @@ -41,6 +41,19 @@ pub(crate) fn map_api_error(err: ApiError) -> CodexErr { } => { let body_text = body.unwrap_or_default(); + if status == http::StatusCode::SERVICE_UNAVAILABLE + && let Ok(value) = serde_json::from_str::(&body_text) + && matches!( + value + .get("error") + .and_then(|error| error.get("code")) + .and_then(serde_json::Value::as_str), + Some("server_is_overloaded" | "slow_down") + ) + { + return CodexErr::ServerOverloaded; + } + if status == http::StatusCode::BAD_REQUEST { if body_text .contains("The image data you provided does not represent a valid image") @@ -52,23 +65,6 @@ pub(crate) fn map_api_error(err: ApiError) -> CodexErr { } else if status == http::StatusCode::INTERNAL_SERVER_ERROR { CodexErr::InternalServerError } else if status == http::StatusCode::TOO_MANY_REQUESTS { - if let Some(model) = headers - .as_ref() - .and_then(|map| map.get(MODEL_CAP_MODEL_HEADER)) - .and_then(|value| value.to_str().ok()) - .map(str::to_string) - { - let reset_after_seconds = headers - .as_ref() - .and_then(|map| map.get(MODEL_CAP_RESET_AFTER_HEADER)) - .and_then(|value| value.to_str().ok()) - .and_then(|value| value.parse::().ok()); - return CodexErr::ModelCap(ModelCapError { - model, - reset_after_seconds, - }); - } - if let Ok(err) = serde_json::from_str::(&body_text) { if err.error.error_type.as_deref() == Some("usage_limit_reached") { let limit_id = extract_header(headers.as_ref(), ACTIVE_LIMIT_HEADER); @@ -119,8 +115,6 @@ pub(crate) fn map_api_error(err: ApiError) -> CodexErr { } } -const MODEL_CAP_MODEL_HEADER: &str = "x-codex-model-cap-model"; -const MODEL_CAP_RESET_AFTER_HEADER: &str = "x-codex-model-cap-reset-after-seconds"; const ACTIVE_LIMIT_HEADER: &str = "x-codex-active-limit"; const REQUEST_ID_HEADER: &str = "x-request-id"; const OAI_REQUEST_ID_HEADER: &str = "x-oai-request-id"; @@ -129,33 +123,30 @@ const CF_RAY_HEADER: &str = "cf-ray"; #[cfg(test)] mod tests { use super::*; - use codex_api::TransportError; - use http::HeaderMap; - use http::StatusCode; + use pretty_assertions::assert_eq; #[test] - fn map_api_error_maps_model_cap_headers() { - let mut headers = HeaderMap::new(); - headers.insert( - MODEL_CAP_MODEL_HEADER, - http::HeaderValue::from_static("boomslang"), - ); - headers.insert( - MODEL_CAP_RESET_AFTER_HEADER, - http::HeaderValue::from_static("120"), - ); + fn map_api_error_maps_server_overloaded() { + let err = map_api_error(ApiError::ServerOverloaded); + assert!(matches!(err, CodexErr::ServerOverloaded)); + } + + #[test] + fn map_api_error_maps_server_overloaded_from_503_body() { + let body = serde_json::json!({ + "error": { + "code": "server_is_overloaded" + } + }) + .to_string(); let err = map_api_error(ApiError::Transport(TransportError::Http { - status: StatusCode::TOO_MANY_REQUESTS, + status: http::StatusCode::SERVICE_UNAVAILABLE, url: Some("http://example.com/v1/responses".to_string()), - headers: Some(headers), - body: Some(String::new()), + headers: None, + body: Some(body), })); - let CodexErr::ModelCap(model_cap) = err else { - panic!("expected CodexErr::ModelCap, got {err:?}"); - }; - assert_eq!(model_cap.model, "boomslang"); - assert_eq!(model_cap.reset_after_seconds, Some(120)); + assert!(matches!(err, CodexErr::ServerOverloaded)); } #[test] @@ -173,7 +164,7 @@ mod tests { }) .to_string(); let err = map_api_error(ApiError::Transport(TransportError::Http { - status: StatusCode::TOO_MANY_REQUESTS, + status: http::StatusCode::TOO_MANY_REQUESTS, url: Some("http://example.com/v1/responses".to_string()), headers: Some(headers), body: Some(body), diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 4696d9d15e..c57d831213 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -564,6 +564,80 @@ impl TurnContext { }) } + pub(crate) async fn with_model(&self, model: String, models_manager: &ModelsManager) -> Self { + let mut config = (*self.config).clone(); + config.model = Some(model.clone()); + let model_info = models_manager.get_model_info(model.as_str(), &config).await; + let truncation_policy = model_info.truncation_policy.into(); + let supported_reasoning_levels = model_info + .supported_reasoning_levels + .iter() + .map(|preset| preset.effort) + .collect::>(); + let reasoning_effort = if let Some(current_reasoning_effort) = self.reasoning_effort { + if supported_reasoning_levels.contains(¤t_reasoning_effort) { + Some(current_reasoning_effort) + } else { + supported_reasoning_levels + .get(supported_reasoning_levels.len().saturating_sub(1) / 2) + .copied() + .or(model_info.default_reasoning_level) + } + } else { + supported_reasoning_levels + .get(supported_reasoning_levels.len().saturating_sub(1) / 2) + .copied() + .or(model_info.default_reasoning_level) + }; + config.model_reasoning_effort = reasoning_effort; + + let collaboration_mode = + self.collaboration_mode + .with_updates(Some(model.clone()), Some(reasoning_effort), None); + let features = self.features.clone(); + let tools_config = ToolsConfig::new(&ToolsConfigParams { + model_info: &model_info, + features: &features, + web_search_mode: self.tools_config.web_search_mode, + }); + + Self { + sub_id: self.sub_id.clone(), + config: Arc::new(config), + auth_manager: self.auth_manager.clone(), + model_info: model_info.clone(), + otel_manager: self + .otel_manager + .clone() + .with_model(model.as_str(), model_info.slug.as_str()), + provider: self.provider.clone(), + reasoning_effort, + reasoning_summary: self.reasoning_summary, + session_source: self.session_source.clone(), + cwd: self.cwd.clone(), + developer_instructions: self.developer_instructions.clone(), + compact_prompt: self.compact_prompt.clone(), + user_instructions: self.user_instructions.clone(), + collaboration_mode, + personality: self.personality, + approval_policy: self.approval_policy, + sandbox_policy: self.sandbox_policy.clone(), + network: self.network.clone(), + windows_sandbox_level: self.windows_sandbox_level, + shell_environment_policy: self.shell_environment_policy.clone(), + tools_config, + features, + ghost_snapshot: self.ghost_snapshot.clone(), + final_output_json_schema: self.final_output_json_schema.clone(), + codex_linux_sandbox_exe: self.codex_linux_sandbox_exe.clone(), + tool_call_gate: Arc::new(ReadinessFlag::new()), + truncation_policy, + js_repl: Arc::clone(&self.js_repl), + dynamic_tools: self.dynamic_tools.clone(), + turn_metadata_header: self.turn_metadata_header.clone(), + } + } + pub(crate) fn resolve_path(&self, path: Option) -> PathBuf { path.as_ref() .map(PathBuf::from) @@ -3892,7 +3966,6 @@ pub(crate) async fn run_turn( let model_info = turn_context.model_info.clone(); let auto_compact_limit = model_info.auto_compact_token_limit().unwrap_or(i64::MAX); - let total_usage_tokens = sess.get_total_token_usage().await; let event = EventMsg::TurnStarted(TurnStartedEvent { turn_id: turn_context.sub_id.clone(), @@ -3900,9 +3973,11 @@ pub(crate) async fn run_turn( collaboration_mode_kind: turn_context.collaboration_mode.mode, }); sess.send_event(&turn_context, event).await; - if total_usage_tokens >= auto_compact_limit - && run_auto_compact(&sess, &turn_context).await.is_err() + if run_pre_sampling_compact(&sess, &turn_context) + .await + .is_err() { + error!("Failed to run pre-sampling compact"); return None; } @@ -4141,6 +4216,62 @@ pub(crate) async fn run_turn( last_agent_message } +async fn run_pre_sampling_compact( + sess: &Arc, + turn_context: &Arc, +) -> CodexResult<()> { + let total_usage_tokens_before_compaction = sess.get_total_token_usage().await; + maybe_run_previous_model_inline_compact( + sess, + turn_context, + total_usage_tokens_before_compaction, + ) + .await?; + let total_usage_tokens = sess.get_total_token_usage().await; + let auto_compact_limit = turn_context + .model_info + .auto_compact_token_limit() + .unwrap_or(i64::MAX); + // Compact if the total usage tokens are greater than the auto compact limit + if total_usage_tokens >= auto_compact_limit { + run_auto_compact(sess, turn_context).await?; + } + Ok(()) +} + +async fn maybe_run_previous_model_inline_compact( + sess: &Arc, + turn_context: &Arc, + total_usage_tokens: i64, +) -> CodexResult<()> { + let Some(previous_model) = sess.previous_model().await else { + return Ok(()); + }; + let previous_turn_context = Arc::new( + turn_context + .with_model(previous_model, &sess.services.models_manager) + .await, + ); + + let Some(old_context_window) = previous_turn_context.model_context_window() else { + return Ok(()); + }; + let Some(new_context_window) = turn_context.model_context_window() else { + return Ok(()); + }; + let new_auto_compact_limit = turn_context + .model_info + .auto_compact_token_limit() + .unwrap_or(i64::MAX); + let should_run = total_usage_tokens > new_auto_compact_limit + && previous_turn_context.model_info.slug != turn_context.model_info.slug + && old_context_window > new_context_window; + if should_run { + run_auto_compact(sess, &previous_turn_context).await?; + } + Ok(()) +} + async fn run_auto_compact(sess: &Arc, turn_context: &Arc) -> CodexResult<()> { if should_use_remote_compact_task(&turn_context.provider) { run_inline_remote_auto_compact_task(Arc::clone(sess), Arc::clone(turn_context)).await?; @@ -4400,7 +4531,7 @@ async fn built_tools( None }; - if turn_context.config.features.enabled(Feature::SearchTool) { + if turn_context.config.features.enabled(Feature::Apps) { let mut selected_mcp_tools = if let Some(selected_tools) = sess.get_mcp_tool_selection().await { filter_mcp_tools_by_name(mcp_tools.clone(), &selected_tools) @@ -6112,6 +6243,44 @@ mod tests { ); } + #[tokio::test] + async fn turn_context_with_model_updates_model_fields() { + let (session, mut turn_context) = make_session_and_context().await; + turn_context.reasoning_effort = Some(ReasoningEffortConfig::Minimal); + let updated = turn_context + .with_model("gpt-5.1".to_string(), &session.services.models_manager) + .await; + let expected_model_info = session + .services + .models_manager + .get_model_info("gpt-5.1", updated.config.as_ref()) + .await; + + assert_eq!(updated.config.model.as_deref(), Some("gpt-5.1")); + assert_eq!(updated.collaboration_mode.model(), "gpt-5.1"); + assert_eq!(updated.model_info, expected_model_info); + assert_eq!( + updated.reasoning_effort, + Some(ReasoningEffortConfig::Medium) + ); + assert_eq!( + updated.collaboration_mode.reasoning_effort(), + Some(ReasoningEffortConfig::Medium) + ); + assert_eq!( + updated.config.model_reasoning_effort, + Some(ReasoningEffortConfig::Medium) + ); + assert_eq!( + updated.truncation_policy, + expected_model_info.truncation_policy.into() + ); + assert!(!Arc::ptr_eq( + &updated.tool_call_gate, + &turn_context.tool_call_gate + )); + } + #[test] fn falls_back_to_content_when_structured_is_null() { let ctr = McpCallToolResult { diff --git a/codex-rs/core/src/error.rs b/codex-rs/core/src/error.rs index c284134d97..c7d9ffb82d 100644 --- a/codex-rs/core/src/error.rs +++ b/codex-rs/core/src/error.rs @@ -113,8 +113,8 @@ pub enum CodexErr { #[error("{0}")] UsageLimitReached(UsageLimitReachedError), - #[error("{0}")] - ModelCap(ModelCapError), + #[error("Selected model is at capacity. Please try a different model.")] + ServerOverloaded, #[error("{0}")] ResponseStreamFailed(ResponseStreamFailed), @@ -209,7 +209,7 @@ impl CodexErr { | CodexErr::Spawn | CodexErr::SessionConfiguredNotFirstEvent | CodexErr::UsageLimitReached(_) - | CodexErr::ModelCap(_) => false, + | CodexErr::ServerOverloaded => false, CodexErr::Stream(..) | CodexErr::Timeout | CodexErr::UnexpectedStatus(_) @@ -470,30 +470,6 @@ impl std::fmt::Display for UsageLimitReachedError { } } -#[derive(Debug)] -pub struct ModelCapError { - pub(crate) model: String, - pub(crate) reset_after_seconds: Option, -} - -impl std::fmt::Display for ModelCapError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut message = format!( - "Model {} is at capacity. Please try a different model.", - self.model - ); - if let Some(seconds) = self.reset_after_seconds { - message.push_str(&format!( - " Try again in {}.", - format_duration_short(seconds) - )); - } else { - message.push_str(" Try again later."); - } - write!(f, "{message}") - } -} - fn retry_suffix(resets_at: Option<&DateTime>) -> String { if let Some(resets_at) = resets_at { let formatted = format_retry_timestamp(resets_at); @@ -525,18 +501,6 @@ fn format_retry_timestamp(resets_at: &DateTime) -> String { } } -fn format_duration_short(seconds: u64) -> String { - if seconds < 60 { - "less than a minute".to_string() - } else if seconds < 3600 { - format!("{}m", seconds / 60) - } else if seconds < 86_400 { - format!("{}h", seconds / 3600) - } else { - format!("{}d", seconds / 86_400) - } -} - fn day_suffix(day: u32) -> &'static str { match day { 11..=13 => "th", @@ -600,10 +564,7 @@ impl CodexErr { CodexErr::UsageLimitReached(_) | CodexErr::QuotaExceeded | CodexErr::UsageNotIncluded => CodexErrorInfo::UsageLimitExceeded, - CodexErr::ModelCap(err) => CodexErrorInfo::ModelCap { - model: err.model.clone(), - reset_after_seconds: err.reset_after_seconds, - }, + CodexErr::ServerOverloaded => CodexErrorInfo::ServerOverloaded, CodexErr::RetryLimit(_) => CodexErrorInfo::ResponseTooManyFailedAttempts { http_status_code: self.http_status_code_value(), }, @@ -752,41 +713,11 @@ mod tests { } #[test] - fn model_cap_error_formats_message() { - let err = ModelCapError { - model: "boomslang".to_string(), - reset_after_seconds: Some(120), - }; - assert_eq!( - err.to_string(), - "Model boomslang is at capacity. Please try a different model. Try again in 2m." - ); - } - - #[test] - fn model_cap_error_formats_message_without_reset() { - let err = ModelCapError { - model: "boomslang".to_string(), - reset_after_seconds: None, - }; - assert_eq!( - err.to_string(), - "Model boomslang is at capacity. Please try a different model. Try again later." - ); - } - - #[test] - fn model_cap_error_maps_to_protocol() { - let err = CodexErr::ModelCap(ModelCapError { - model: "boomslang".to_string(), - reset_after_seconds: Some(30), - }); + fn server_overloaded_maps_to_protocol() { + let err = CodexErr::ServerOverloaded; assert_eq!( err.to_codex_protocol_error(), - CodexErrorInfo::ModelCap { - model: "boomslang".to_string(), - reset_after_seconds: Some(30), - } + CodexErrorInfo::ServerOverloaded ); } diff --git a/codex-rs/core/src/features.rs b/codex-rs/core/src/features.rs index 56aa288133..4a64d81f89 100644 --- a/codex-rs/core/src/features.rs +++ b/codex-rs/core/src/features.rs @@ -89,7 +89,7 @@ pub enum Feature { /// Allow the model to request web searches that fetch cached content. /// Takes precedence over `WebSearchRequest`. WebSearchCached, - /// Allow the model to search MCP tools via BM25 before exposing them. + /// Legacy search-tool feature flag kept for backward compatibility. SearchTool, /// Use the bubblewrap-based Linux sandbox pipeline. UseLinuxSandboxBwrap, @@ -445,7 +445,7 @@ pub const FEATURES: &[FeatureSpec] = &[ FeatureSpec { id: Feature::SearchTool, key: "search_tool", - stage: Stage::UnderDevelopment, + stage: Stage::Removed, default_enabled: false, }, // Experimental program. Rendered in the `/experimental` menu for users. diff --git a/codex-rs/core/src/tasks/mod.rs b/codex-rs/core/src/tasks/mod.rs index 1066402519..3d4528da2d 100644 --- a/codex-rs/core/src/tasks/mod.rs +++ b/codex-rs/core/src/tasks/mod.rs @@ -153,7 +153,7 @@ impl Session { if !task_cancellation_token.is_cancelled() { // Emit completion uniformly from spawn site so all tasks share the same lifecycle. let sess = session_ctx.clone_session(); - sess.on_task_finished(ctx_for_finish, last_agent_message) + sess.on_task_finished(Arc::clone(&ctx_for_finish), last_agent_message) .await; } // Set previous model regardless of completion or interruption for model-switch handling. diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index 80fd103b2f..098f640690 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -58,7 +58,7 @@ impl ToolsConfig { let include_collab_tools = features.enabled(Feature::Collab); let include_collaboration_modes_tools = features.enabled(Feature::CollaborationModes); let request_rule_enabled = features.enabled(Feature::RequestRule); - let include_search_tool = features.enabled(Feature::SearchTool); + let include_search_tool = features.enabled(Feature::Apps); let shell_type = if !features.enabled(Feature::ShellTool) { ConfigShellToolType::Disabled diff --git a/codex-rs/core/tests/suite/compact.rs b/codex-rs/core/tests/suite/compact.rs index 183732f0a4..6106369c31 100644 --- a/codex-rs/core/tests/suite/compact.rs +++ b/codex-rs/core/tests/suite/compact.rs @@ -5,6 +5,7 @@ use codex_core::built_in_model_providers; use codex_core::compact::SUMMARIZATION_PROMPT; use codex_core::compact::SUMMARY_PREFIX; use codex_core::config::Config; +use codex_core::features::Feature; use codex_core::protocol::AskForApproval; use codex_core::protocol::EventMsg; use codex_core::protocol::ItemCompletedEvent; @@ -16,9 +17,12 @@ use codex_core::protocol::SandboxPolicy; use codex_core::protocol::WarningEvent; use codex_protocol::config_types::ReasoningSummary; use codex_protocol::items::TurnItem; +use codex_protocol::openai_models::ModelInfo; +use codex_protocol::openai_models::ModelsResponse; use codex_protocol::user_input::UserInput; use core_test_support::responses::ev_local_shell_call; use core_test_support::responses::ev_reasoning_item; +use core_test_support::responses::mount_models_once; use core_test_support::skip_if_no_network; use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; @@ -110,6 +114,78 @@ fn non_openai_model_provider(server: &MockServer) -> ModelProviderInfo { provider } +fn model_info_with_context_window(slug: &str, context_window: i64) -> ModelInfo { + let models_response: ModelsResponse = + serde_json::from_str(include_str!("../../models.json")).expect("valid models.json"); + let mut model_info = models_response + .models + .into_iter() + .find(|model| model.slug == slug) + .unwrap_or_else(|| panic!("model `{slug}` missing from models.json")); + model_info.context_window = Some(context_window); + model_info +} + +fn assert_pre_sampling_switch_compaction_requests( + first: &serde_json::Value, + compact: &serde_json::Value, + follow_up: &serde_json::Value, + previous_model: &str, + next_model: &str, +) { + assert_eq!(first["model"].as_str(), Some(previous_model)); + assert_eq!(compact["model"].as_str(), Some(previous_model)); + assert_eq!(follow_up["model"].as_str(), Some(next_model)); + + let compact_body = compact.to_string(); + assert!( + body_contains_text(&compact_body, SUMMARIZATION_PROMPT), + "pre-sampling compact request should include summarization prompt" + ); +} + +async fn assert_compaction_uses_turn_lifecycle_id(codex: &std::sync::Arc) { + let mut turn_started_id = None; + let mut turn_completed_id = None; + let mut compact_started_id = None; + let mut compact_completed_id = None; + + while turn_completed_id.is_none() { + let event = codex.next_event().await.expect("next event"); + match event.msg { + EventMsg::TurnStarted(_) => turn_started_id = Some(event.id.clone()), + EventMsg::ItemStarted(ItemStartedEvent { + item: TurnItem::ContextCompaction(_), + .. + }) => compact_started_id = Some(event.id.clone()), + EventMsg::ItemCompleted(ItemCompletedEvent { + item: TurnItem::ContextCompaction(_), + .. + }) => compact_completed_id = Some(event.id.clone()), + EventMsg::TurnComplete(_) => turn_completed_id = Some(event.id.clone()), + _ => {} + } + } + + let turn_started_id = turn_started_id.expect("turn started id"); + let turn_completed_id = turn_completed_id.expect("turn complete id"); + + assert_eq!( + turn_completed_id, turn_started_id, + "turn start and complete should use the same event id" + ); + assert_eq!( + compact_started_id, + Some(turn_started_id.clone()), + "compaction item start should use the turn event id" + ); + assert_eq!( + compact_completed_id, + Some(turn_started_id), + "compaction item completion should use the turn event id" + ); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn summarize_context_three_requests_and_instructions() { skip_if_no_network!(); @@ -1551,6 +1627,257 @@ async fn auto_compact_runs_after_resume_when_token_usage_is_over_limit() { ); } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn pre_sampling_compact_runs_on_switch_to_smaller_context_model() { + skip_if_no_network!(); + + let server = MockServer::start().await; + let previous_model = "gpt-5.2-codex"; + let next_model = "gpt-5.1-codex-max"; + + let models_mock = mount_models_once( + &server, + ModelsResponse { + models: vec![ + model_info_with_context_window(previous_model, 273_000), + model_info_with_context_window(next_model, 125_000), + ], + }, + ) + .await; + + let request_log = mount_sse_sequence( + &server, + vec![ + sse(vec![ + ev_assistant_message("m1", "before switch"), + ev_completed_with_tokens("r1", 120_000), + ]), + sse(vec![ + ev_assistant_message("m2", "PRE_SAMPLING_SUMMARY"), + ev_completed_with_tokens("r2", 10), + ]), + sse(vec![ + ev_assistant_message("m3", "after switch"), + ev_completed_with_tokens("r3", 100), + ]), + ], + ) + .await; + + let model_provider = non_openai_model_provider(&server); + let mut builder = test_codex() + .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) + .with_model(previous_model) + .with_config(move |config| { + config.model_provider = model_provider; + set_test_compact_prompt(config); + config.features.enable(Feature::RemoteModels); + }); + let test = builder.build(&server).await.expect("build test codex"); + + test.codex + .submit(Op::UserTurn { + items: vec![UserInput::Text { + text: "before switch".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + cwd: test.cwd.path().to_path_buf(), + approval_policy: AskForApproval::Never, + sandbox_policy: SandboxPolicy::DangerFullAccess, + model: previous_model.to_string(), + effort: None, + summary: ReasoningSummary::Auto, + collaboration_mode: None, + personality: None, + }) + .await + .expect("submit first user turn"); + wait_for_event(&test.codex, |event| { + matches!(event, EventMsg::TurnComplete(_)) + }) + .await; + + test.codex + .submit(Op::UserTurn { + items: vec![UserInput::Text { + text: "after switch".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + cwd: test.cwd.path().to_path_buf(), + approval_policy: AskForApproval::Never, + sandbox_policy: SandboxPolicy::DangerFullAccess, + model: next_model.to_string(), + effort: None, + summary: ReasoningSummary::Auto, + collaboration_mode: None, + personality: None, + }) + .await + .expect("submit second user turn"); + assert_compaction_uses_turn_lifecycle_id(&test.codex).await; + + let requests = request_log.requests(); + assert_eq!(models_mock.requests().len(), 1); + assert_eq!( + requests.len(), + 3, + "expected user, compact, and follow-up requests" + ); + assert_pre_sampling_switch_compaction_requests( + &requests[0].body_json(), + &requests[1].body_json(), + &requests[2].body_json(), + previous_model, + next_model, + ); +} + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn pre_sampling_compact_runs_after_resume_and_switch_to_smaller_model() { + skip_if_no_network!(); + + let server = MockServer::start().await; + let previous_model = "gpt-5.2-codex"; + let next_model = "gpt-5.1-codex-max"; + + let models_mock = mount_models_once( + &server, + ModelsResponse { + models: vec![ + model_info_with_context_window(previous_model, 273_000), + model_info_with_context_window(next_model, 125_000), + ], + }, + ) + .await; + + let request_log = mount_sse_sequence( + &server, + vec![ + sse(vec![ + ev_assistant_message("m1", "before resume"), + ev_completed_with_tokens("r1", 120_000), + ]), + sse(vec![ + ev_assistant_message("m2", "PRE_SAMPLING_SUMMARY"), + ev_completed_with_tokens("r2", 10), + ]), + sse(vec![ + ev_assistant_message("m3", "after resume"), + ev_completed_with_tokens("r3", 100), + ]), + ], + ) + .await; + + let model_provider = non_openai_model_provider(&server); + let mut initial_builder = test_codex() + .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) + .with_model(previous_model) + .with_config(move |config| { + config.model_provider = model_provider; + set_test_compact_prompt(config); + config.features.enable(Feature::RemoteModels); + }); + let initial = initial_builder + .build(&server) + .await + .expect("build initial test codex"); + let home = initial.home.clone(); + let rollout_path = initial + .session_configured + .rollout_path + .clone() + .expect("rollout path"); + + initial + .codex + .submit(Op::UserTurn { + items: vec![UserInput::Text { + text: "before resume".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + cwd: initial.cwd.path().to_path_buf(), + approval_policy: AskForApproval::Never, + sandbox_policy: SandboxPolicy::DangerFullAccess, + model: previous_model.to_string(), + effort: None, + summary: ReasoningSummary::Auto, + collaboration_mode: None, + personality: None, + }) + .await + .expect("submit pre-resume turn"); + wait_for_event(&initial.codex, |event| { + matches!(event, EventMsg::TurnComplete(_)) + }) + .await; + + initial + .codex + .submit(Op::Shutdown) + .await + .expect("shutdown initial session"); + wait_for_event(&initial.codex, |event| { + matches!(event, EventMsg::ShutdownComplete) + }) + .await; + + let model_provider = non_openai_model_provider(&server); + let mut resumed_builder = test_codex() + .with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing()) + .with_model(previous_model) + .with_config(move |config| { + config.model_provider = model_provider; + set_test_compact_prompt(config); + config.features.enable(Feature::RemoteModels); + }); + let resumed = resumed_builder + .resume(&server, home, rollout_path) + .await + .expect("resume codex"); + + resumed + .codex + .submit(Op::UserTurn { + items: vec![UserInput::Text { + text: "after resume".into(), + text_elements: Vec::new(), + }], + final_output_json_schema: None, + cwd: resumed.cwd.path().to_path_buf(), + approval_policy: AskForApproval::Never, + sandbox_policy: SandboxPolicy::DangerFullAccess, + model: next_model.to_string(), + effort: None, + summary: ReasoningSummary::Auto, + collaboration_mode: None, + personality: None, + }) + .await + .expect("submit resumed user turn"); + assert_compaction_uses_turn_lifecycle_id(&resumed.codex).await; + + let requests = request_log.requests(); + assert_eq!(models_mock.requests().len(), 1); + assert_eq!( + requests.len(), + 3, + "expected user, compact, and follow-up requests" + ); + assert_pre_sampling_switch_compaction_requests( + &requests[0].body_json(), + &requests[1].body_json(), + &requests[2].body_json(), + previous_model, + next_model, + ); +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn auto_compact_persists_rollout_entries() { skip_if_no_network!(); diff --git a/codex-rs/core/tests/suite/search_tool.rs b/codex-rs/core/tests/suite/search_tool.rs index fae5956168..c819c03b25 100644 --- a/codex-rs/core/tests/suite/search_tool.rs +++ b/codex-rs/core/tests/suite/search_tool.rs @@ -111,7 +111,7 @@ async fn search_tool_flag_adds_tool() -> Result<()> { .await; let mut builder = test_codex().with_config(|config| { - config.features.enable(Feature::SearchTool); + config.features.enable(Feature::Apps); }); let test = builder.build(&server).await?; @@ -148,7 +148,7 @@ async fn search_tool_adds_developer_instructions() -> Result<()> { .await; let mut builder = test_codex().with_config(|config| { - config.features.enable(Feature::SearchTool); + config.features.enable(Feature::Apps); }); let test = builder.build(&server).await?; @@ -190,7 +190,7 @@ async fn search_tool_hides_mcp_tools_without_search() -> Result<()> { let rmcp_test_server_bin = stdio_server_bin()?; let mut builder = test_codex().with_config(move |config| { - config.features.enable(Feature::SearchTool); + config.features.enable(Feature::Apps); let mut servers = config.mcp_servers.get().clone(); servers.insert( "rmcp".to_string(), @@ -273,7 +273,7 @@ async fn search_tool_selection_persists_within_turn_and_resets_next_turn() -> Re let rmcp_test_server_bin = stdio_server_bin()?; let mut builder = test_codex().with_config(move |config| { - config.features.enable(Feature::SearchTool); + config.features.enable(Feature::Apps); let mut servers = config.mcp_servers.get().clone(); servers.insert( "rmcp".to_string(), @@ -401,7 +401,7 @@ async fn search_tool_selection_unions_results_within_turn() -> Result<()> { let rmcp_test_server_bin = stdio_server_bin()?; let mut builder = test_codex().with_config(move |config| { - config.features.enable(Feature::SearchTool); + config.features.enable(Feature::Apps); let mut servers = config.mcp_servers.get().clone(); servers.insert( "rmcp".to_string(), diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index dbab8edc29..695ac3bb87 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -1130,10 +1130,7 @@ pub enum AgentStatus { pub enum CodexErrorInfo { ContextWindowExceeded, UsageLimitExceeded, - ModelCap { - model: String, - reset_after_seconds: Option, - }, + ServerOverloaded, HttpConnectionFailed { http_status_code: Option, }, diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index eeac3a3504..329a6c313a 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -441,23 +441,14 @@ enum ConnectorsCacheState { #[derive(Debug)] enum RateLimitErrorKind { - ModelCap { - model: String, - reset_after_seconds: Option, - }, + ServerOverloaded, UsageLimit, Generic, } fn rate_limit_error_kind(info: &CodexErrorInfo) -> Option { match info { - CodexErrorInfo::ModelCap { - model, - reset_after_seconds, - } => Some(RateLimitErrorKind::ModelCap { - model: model.clone(), - reset_after_seconds: *reset_after_seconds, - }), + CodexErrorInfo::ServerOverloaded => Some(RateLimitErrorKind::ServerOverloaded), CodexErrorInfo::UsageLimitExceeded => Some(RateLimitErrorKind::UsageLimit), CodexErrorInfo::ResponseTooManyFailedAttempts { http_status_code: Some(429), @@ -1605,18 +1596,14 @@ impl ChatWidget { self.maybe_show_pending_rate_limit_prompt(); } - fn on_model_cap_error(&mut self, model: String, reset_after_seconds: Option) { + fn on_server_overloaded_error(&mut self, message: String) { self.finalize_turn(); - let mut message = format!("Model {model} is at capacity. Please try a different model."); - if let Some(seconds) = reset_after_seconds { - message.push_str(&format!( - " Try again in {}.", - format_duration_short(seconds) - )); + let message = if message.trim().is_empty() { + "Codex is currently experiencing high load.".to_string() } else { - message.push_str(" Try again later."); - } + message + }; self.add_to_history(history_cell::new_warning_event(message)); self.request_redraw(); @@ -3964,10 +3951,9 @@ impl ChatWidget { && let Some(kind) = rate_limit_error_kind(&info) { match kind { - RateLimitErrorKind::ModelCap { - model, - reset_after_seconds, - } => self.on_model_cap_error(model, reset_after_seconds), + RateLimitErrorKind::ServerOverloaded => { + self.on_server_overloaded_error(message) + } RateLimitErrorKind::UsageLimit | RateLimitErrorKind::Generic => { self.on_error(message) } @@ -7162,17 +7148,5 @@ pub(crate) fn show_review_commit_picker_with_entries( }); } -fn format_duration_short(seconds: u64) -> String { - if seconds < 60 { - "less than a minute".to_string() - } else if seconds < 3600 { - format!("{}m", seconds / 60) - } else if seconds < 86_400 { - format!("{}h", seconds / 3600) - } else { - format!("{}d", seconds / 86_400) - } -} - #[cfg(test)] pub(crate) mod tests; diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 08471bdb65..6c6e9ccde9 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -4096,7 +4096,7 @@ async fn model_picker_hides_show_in_picker_false_models_from_cache() { } #[tokio::test] -async fn model_cap_error_does_not_switch_models() { +async fn server_overloaded_error_does_not_switch_models() { let (mut chat, mut rx, mut op_rx) = make_chatwidget_manual(Some("boomslang")).await; chat.set_model("boomslang"); while rx.try_recv().is_ok() {} @@ -4105,11 +4105,8 @@ async fn model_cap_error_does_not_switch_models() { chat.handle_codex_event(Event { id: "err-1".to_string(), msg: EventMsg::Error(ErrorEvent { - message: "model cap".to_string(), - codex_error_info: Some(CodexErrorInfo::ModelCap { - model: "boomslang".to_string(), - reset_after_seconds: Some(120), - }), + message: "server overloaded".to_string(), + codex_error_info: Some(CodexErrorInfo::ServerOverloaded), }), }); @@ -4117,7 +4114,7 @@ async fn model_cap_error_does_not_switch_models() { if let AppEvent::UpdateModel(model) = event { assert_eq!( model, "boomslang", - "did not expect model switch on model-cap error" + "did not expect model switch on server-overloaded error" ); } } @@ -4126,7 +4123,7 @@ async fn model_cap_error_does_not_switch_models() { if let Op::OverrideTurnContext { model, .. } = event { assert!( model.is_none(), - "did not expect OverrideTurnContext model update on model-cap error" + "did not expect OverrideTurnContext model update on server-overloaded error" ); } }