diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 3456f9d731..db51679579 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -18,7 +18,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-core", "futures-sink", @@ -39,7 +39,7 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "bytestring", "derive_more 2.1.1", @@ -282,7 +282,7 @@ checksum = "fe233a377643e0fc1a56421d7c90acdec45c291b30345eb9f08e8d0ddce5a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -430,9 +430,9 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d03449bb8ca2cc2ef70869af31463d1ae5ccc8fa3e334b307203fbf815207e" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" dependencies = [ "rustversion", ] @@ -485,7 +485,7 @@ dependencies = [ "rustc-hash 2.1.1", "serde", "serde_derive", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -534,7 +534,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "synstructure", ] @@ -546,7 +546,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -586,12 +586,23 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "futures-core", "pin-project-lite", ] +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + [[package]] name = "async-channel" version = "2.5.0" @@ -606,14 +617,14 @@ dependencies = [ [[package]] name = "async-executor" -version = "1.13.3" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" dependencies = [ "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "fastrand 2.3.0", + "futures-lite 2.6.1", "pin-project-lite", "slab", ] @@ -626,7 +637,7 @@ checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" dependencies = [ "async-lock", "blocking", - "futures-lite", + "futures-lite 2.6.1", ] [[package]] @@ -639,7 +650,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "parking", "polling", "rustix 1.1.3", @@ -653,7 +664,7 @@ version = "3.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" dependencies = [ - "event-listener", + "event-listener 5.4.1", "event-listener-strategy", "pin-project-lite", ] @@ -664,15 +675,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ - "async-channel", + "async-channel 2.5.0", "async-io", "async-lock", "async-signal", "async-task", "blocking", "cfg-if", - "event-listener", - "futures-lite", + "event-listener 5.4.1", + "futures-lite 2.6.1", "rustix 1.1.3", ] @@ -684,7 +695,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -724,7 +735,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -741,7 +752,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -788,9 +799,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.0" +version = "0.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c34dda4df7017c8db52132f0f8a2e0f8161649d15723ed63fc00c82d0f2081a" +checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" dependencies = [ "cc", "cmake", @@ -850,6 +861,54 @@ dependencies = [ "tracing", ] +[[package]] +name = "azure_core" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b552ad43a45a746461ec3d3a51dfb6466b4759209414b439c165eb6a6b7729e" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "dyn-clone", + "futures", + "getrandom 0.2.17", + "http-types", + "once_cell", + "paste", + "pin-project", + "rand 0.8.5", + "reqwest", + "rustc_version", + "serde", + "serde_json", + "time", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "azure_identity" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ddd80344317c40c04b603807b63a5cefa532f1b43522e72f480a988141f744" +dependencies = [ + "async-lock", + "async-process", + "async-trait", + "azure_core", + "futures", + "oauth2 4.4.2", + "pin-project", + "serde", + "time", + "tracing", + "tz-rs", + "url", + "uuid", +] + [[package]] name = "backtrace" version = "0.3.76" @@ -865,6 +924,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -927,9 +992,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -967,10 +1032,10 @@ version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21" dependencies = [ - "async-channel", + "async-channel 2.5.0", "async-task", "futures-io", - "futures-lite", + "futures-lite 2.6.1", "piper", ] @@ -1090,7 +1155,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -1125,9 +1190,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.55" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -1227,9 +1292,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.56" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" +checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" dependencies = [ "clap_builder", "clap_derive", @@ -1237,9 +1302,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.56" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" +checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" dependencies = [ "anstream", "anstyle", @@ -1250,9 +1315,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.65" +version = "4.5.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "430b4dc2b5e3861848de79627b2bedc9f3342c7da5173a14eaa5d0f8dc18ae5d" +checksum = "c757a3b7e39161a4e56f9365141ada2a6c915a8622c408ab6bb4b5d047371031" dependencies = [ "clap", ] @@ -1266,14 +1331,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] name = "clap_lex" -version = "0.7.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "clipboard-win" @@ -1379,7 +1444,7 @@ dependencies = [ "time", "tokio", "tokio-tungstenite", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", "tracing", "tracing-subscriber", "uuid", @@ -1542,7 +1607,7 @@ dependencies = [ "supports-color 3.0.2", "tempfile", "tokio", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", "tracing", ] @@ -1588,7 +1653,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "tokio", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", "tracing", ] @@ -1653,7 +1718,7 @@ dependencies = [ "sha2", "thiserror 2.0.18", "tokio", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", ] [[package]] @@ -1665,8 +1730,10 @@ dependencies = [ "askama", "assert_cmd", "assert_matches", - "async-channel", + "async-channel 2.5.0", "async-trait", + "azure_core", + "azure_identity", "base64 0.22.1", "bm25", "chardetng", @@ -1747,8 +1814,8 @@ dependencies = [ "tokio", "tokio-tungstenite", "tokio-util", - "toml 0.9.11+spec-1.1.0", - "toml_edit 0.24.0+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", + "toml_edit 0.24.1+spec-1.1.0", "tracing", "tracing-subscriber", "tracing-test", @@ -1881,7 +1948,7 @@ version = "0.0.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -2174,7 +2241,7 @@ dependencies = [ "codex-utils-pty", "futures", "keyring", - "oauth2", + "oauth2 5.0.0", "pretty_assertions", "reqwest", "rmcp", @@ -2333,7 +2400,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", "tracing", "tracing-appender", "tracing-subscriber", @@ -2398,7 +2465,7 @@ dependencies = [ "codex-protocol", "pretty_assertions", "serde", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", ] [[package]] @@ -2436,7 +2503,7 @@ version = "0.0.0" dependencies = [ "pretty_assertions", "serde_json", - "toml 0.9.11+spec-1.1.0", + "toml 0.9.12+spec-1.1.0", ] [[package]] @@ -2638,6 +2705,12 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_fn" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8a2ca5ac02d09563609681103aada9e1777d54fc57a5acd7a41404f9c93b6e" + [[package]] name = "const_format" version = "0.2.35" @@ -2831,7 +2904,7 @@ name = "crossterm" version = "0.28.1" source = "git+https://github.com/nornagon/crossterm?branch=nornagon%2Fcolor-query#87db8bfa6dc99427fd3b071681b07fc31c6ce995" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crossterm_winapi", "futures-core", "mio", @@ -2937,7 +3010,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -2981,7 +3054,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -2995,7 +3068,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3008,7 +3081,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3019,7 +3092,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3030,7 +3103,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3041,7 +3114,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3071,7 +3144,7 @@ dependencies = [ "block-padding", "cbc", "dbus", - "fastrand", + "fastrand 2.3.0", "hkdf", "num", "once_cell", @@ -3151,9 +3224,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ "powerfmt", "serde_core", @@ -3178,7 +3251,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3208,7 +3281,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "unicode-xid", ] @@ -3222,7 +3295,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.114", + "syn 2.0.116", "unicode-xid", ] @@ -3313,7 +3386,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", ] @@ -3335,7 +3408,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3388,7 +3461,7 @@ checksum = "83e195b4945e88836d826124af44fdcb262ec01ef94d44f14f4fb5103f19892a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3408,9 +3481,9 @@ dependencies = [ [[package]] name = "ena" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" +checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1" dependencies = [ "log", ] @@ -3457,7 +3530,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3478,7 +3551,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3489,9 +3562,9 @@ checksum = "dbfd0e7fc632dec5e6c9396a27bc9f9975b4e039720e1fd3e34021d3ce28c415" [[package]] name = "env_filter" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", "regex", @@ -3505,9 +3578,9 @@ checksum = "c7f84e12ccf0a7ddc17a6c41c93326024c42920d7ee630d04950e6926645c0fe" [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "anstream", "anstyle", @@ -3558,6 +3631,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "event-listener" version = "5.4.1" @@ -3575,7 +3654,7 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" dependencies = [ - "event-listener", + "event-listener 5.4.1", "pin-project-lite", ] @@ -3612,6 +3691,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -3638,7 +3726,7 @@ checksum = "a0aca10fb742cb43f9e7bb8467c91aa9bcb8e3ffbc6a6f7389bb93ffc920577d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -3730,9 +3818,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.8" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "libz-sys", @@ -3809,7 +3897,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e139bc46ca777eb5efaf62df0ab8cc5fd400866427e56c68b22e414e53bd3be" dependencies = [ - "fastrand", + "fastrand 2.3.0", "futures-core", "futures-sink", "spin", @@ -3874,9 +3962,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -3889,9 +3977,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -3899,15 +3987,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -3927,9 +4015,24 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] [[package]] name = "futures-lite" @@ -3937,7 +4040,7 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand", + "fastrand 2.3.0", "futures-core", "futures-io", "parking", @@ -3946,32 +4049,32 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -3981,7 +4084,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -4038,6 +4140,17 @@ dependencies = [ "unicode-width 0.2.1", ] +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -4047,7 +4160,7 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -4065,6 +4178,19 @@ 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" @@ -4091,7 +4217,7 @@ dependencies = [ "bstr", "log", "regex-automata", - "regex-syntax 0.8.8", + "regex-syntax 0.8.9", ] [[package]] @@ -4347,6 +4473,26 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" +[[package]] +name = "http-types" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9b187a72d63adbfba487f48095306ac823049cb504ee195541e91c7775f5ad" +dependencies = [ + "anyhow", + "async-channel 1.9.0", + "base64 0.13.1", + "futures-lite 1.13.0", + "infer", + "pin-project-lite", + "rand 0.7.3", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] + [[package]] name = "httparse" version = "1.10.1" @@ -4397,7 +4543,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -4431,14 +4577,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http 1.4.0", "http-body", @@ -4504,7 +4649,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.114", + "syn 2.0.116", "unic-langid", ] @@ -4518,7 +4663,7 @@ dependencies = [ "i18n-config", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -4671,6 +4816,12 @@ 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" @@ -4806,13 +4957,19 @@ dependencies = [ "rustversion", ] +[[package]] +name = "infer" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" + [[package]] name = "inotify" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "inotify-sys", "libc", ] @@ -4858,7 +5015,16 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", ] [[package]] @@ -4981,9 +5147,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50" +checksum = "c867c356cc096b33f4981825ab281ecba3db0acefe60329f044c1789d94c6543" dependencies = [ "jiff-static", "log", @@ -4994,13 +5160,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.18" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78" +checksum = "f7946b4325269738f270bb55b3c19ab5c5040525f83fd625259422a9d25d9be5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -5057,7 +5223,7 @@ dependencies = [ "log", "secret-service", "security-framework 2.11.1", - "security-framework 3.5.1", + "security-framework 3.6.0", "windows-sys 0.60.2", "zbus", "zeroize", @@ -5140,6 +5306,12 @@ 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.180" @@ -5167,9 +5339,9 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.7.0", + "redox_syscall 0.7.1", ] [[package]] @@ -5200,7 +5372,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", ] @@ -5404,9 +5576,9 @@ checksum = "ae960838283323069879657ca3de837e9f7bbb4c7bf6ea7f1b290d5e9476d2e0" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memoffset" @@ -5466,7 +5638,7 @@ checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -5508,17 +5680,17 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "9d5d26952a508f321b4d3d2e80e78fc2603eaefcdf0c30783867f19586518bdc" dependencies = [ "libc", "log", "openssl", - "openssl-probe 0.1.6", + "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework 3.6.0", "security-framework-sys", "tempfile", ] @@ -5550,7 +5722,7 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases 0.1.1", "libc", @@ -5562,7 +5734,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "cfg_aliases 0.2.1", "libc", @@ -5575,7 +5747,19 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", + "cfg-if", + "cfg_aliases 0.2.1", + "libc", +] + +[[package]] +name = "nix" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "225e7cfe711e0ba79a68baeddb2982723e4235247aefce1482f2f16c27865b66" +dependencies = [ + "bitflags 2.11.0", "cfg-if", "cfg_aliases 0.2.1", "libc", @@ -5612,7 +5796,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "fsevent-sys", "inotify", "kqueue", @@ -5630,7 +5814,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -5776,6 +5960,25 @@ dependencies = [ "libc", ] +[[package]] +name = "oauth2" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f" +dependencies = [ + "base64 0.13.1", + "chrono", + "getrandom 0.2.17", + "http 0.2.12", + "rand 0.8.5", + "serde", + "serde_json", + "serde_path_to_error", + "sha2", + "thiserror 1.0.69", + "url", +] + [[package]] name = "oauth2" version = "5.0.0" @@ -5811,7 +6014,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-graphics", "objc2-foundation", @@ -5823,7 +6026,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-foundation", ] @@ -5844,7 +6047,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dispatch2", "objc2", ] @@ -5855,7 +6058,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "dispatch2", "objc2", "objc2-core-foundation", @@ -5888,7 +6091,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-core-graphics", @@ -5906,7 +6109,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "libc", "objc2", @@ -5919,7 +6122,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", ] @@ -5930,7 +6133,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "objc2", "objc2-core-foundation", "objc2-foundation", @@ -5942,7 +6145,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "block2", "objc2", "objc2-cloud-kit", @@ -6013,7 +6216,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "foreign-types", "libc", @@ -6030,15 +6233,9 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -6365,7 +6562,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -6387,7 +6584,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", - "fastrand", + "fastrand 2.3.0", "futures-io", ] @@ -6420,11 +6617,11 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "png" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "crc32fast", "fdeflate", "flate2", @@ -6526,9 +6723,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.1.3" +version = "3.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d19ee57562043d37e82899fade9a22ebab7be9cef5026b07fda9cdd4293573" +checksum = "ada8f2932f28a27ee7b70dd6c1c39ea0675c55a36879ab92f3a715eaa1e63cfe" dependencies = [ "anstyle", "difflib", @@ -6540,15 +6737,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727e462b119fe9c93fd0eb1429a5f7647394014cf3c04ab2c0350eeb09095ffa" +checksum = "cad38746f3166b4031b1a0d39ad9f954dd291e7854fcc0eed52ee41a0b50d144" [[package]] name = "predicates-tree" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dd2d6d381dfb73a193c7fca536518d7caee39fc8503f74e7dc0be0531b425c" +checksum = "d0de1b847b39c8131db0467e9df1ff60e6d0562ab8e9a16e568ad0fdb372e2f2" dependencies = [ "predicates-core", "termtree", @@ -6564,6 +6761,16 @@ 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.116", +] + [[package]] name = "proc-macro-crate" version = "3.4.0" @@ -6592,7 +6799,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -6606,13 +6813,13 @@ dependencies = [ [[package]] name = "process-wrap" -version = "9.0.1" +version = "9.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1395947e69c07400ef4d43db0051d6f773c21f647ad8b97382fc01f0204c60" +checksum = "ccd9713fe2c91c3c85ac388b31b89de339365d2c995146e630b5e0da9d06526a" dependencies = [ "futures", "indexmap 2.13.0", - "nix 0.30.1", + "nix 0.31.1", "tokio", "tracing", "windows 0.62.2", @@ -6620,16 +6827,16 @@ dependencies = [ [[package]] name = "proptest" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" +checksum = "37566cb3fdacef14c0737f9546df7cfeadbfbc9fef10991038bf5015d0c80532" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", "rand_xorshift", - "regex-syntax 0.8.8", + "regex-syntax 0.8.9", "unarray", ] @@ -6653,14 +6860,14 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] name = "psl" -version = "2.1.184" +version = "2.1.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dc6a90669f481b41cae3005c68efa36bef275b95aa9123a7af7f1c68c6e5b2" +checksum = "66fed3dc7578357ff12137c75eac73413b6aba9a7204916c19f2a0e9e1e920e0" dependencies = [ "psl-types", ] @@ -6677,7 +6884,7 @@ version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "getopts", "memchr", "pulldown-cmark-escape", @@ -6856,7 +7063,7 @@ checksum = "453d60af031e23af2d48995e41b17023f6150044738680508b63671f8d7417dd" dependencies = [ "ahash", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "chrono", "const_format", "csv", @@ -6989,7 +7196,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -7068,7 +7275,7 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", "x509-parser", ] @@ -7114,6 +7321,19 @@ dependencies = [ "wildcard", ] +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + [[package]] name = "rand" version = "0.8.5" @@ -7135,6 +7355,16 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -7155,6 +7385,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -7173,6 +7412,15 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + [[package]] name = "rand_xorshift" version = "0.4.0" @@ -7187,7 +7435,7 @@ name = "ratatui" version = "0.29.0" source = "git+https://github.com/nornagon/ratatui?branch=nornagon-v0.29.0-patch#9b2ad1298408c45918ee9f8241a6f95498cdbed2" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cassowary", "compact_str", "crossterm", @@ -7251,16 +7499,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -7302,7 +7550,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -7314,25 +7562,25 @@ dependencies = [ "aho-corasick", "memchr", "regex-automata", - "regex-syntax 0.8.8", + "regex-syntax 0.8.9", ] [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.8", + "regex-syntax 0.8.9", ] [[package]] name = "regex-lite" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da" +checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" @@ -7342,9 +7590,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" @@ -7392,7 +7640,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] @@ -7430,7 +7678,7 @@ dependencies = [ "http 1.4.0", "http-body", "http-body-util", - "oauth2", + "oauth2 5.0.0", "pastey", "pin-project-lite", "process-wrap", @@ -7461,7 +7709,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -7509,7 +7757,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.114", + "syn 2.0.116", "walkdir", ] @@ -7575,7 +7823,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -7588,7 +7836,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.11.0", @@ -7617,10 +7865,10 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework 3.6.0", ] [[package]] @@ -7657,7 +7905,7 @@ version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if", "clipboard-win", "fd-lock", @@ -7675,9 +7923,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "salsa20" @@ -7804,7 +8052,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -7816,7 +8064,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -7891,7 +8139,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -7900,11 +8148,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -7913,9 +8161,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" dependencies = [ "core-foundation-sys", "libc", @@ -7944,10 +8192,11 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "sentry" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f925d575b468e88b079faf590a8dd0c9c99e2ec29e9bab663ceb8b45056312f" +checksum = "d92d893ba7469d361a6958522fa440e4e2bc8bf4c5803cd1bf40b9af63f8f9a8" dependencies = [ + "cfg_aliases 0.2.1", "httpdate", "native-tls", "reqwest", @@ -7964,9 +8213,9 @@ dependencies = [ [[package]] name = "sentry-actix" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18bac0f6b8621fa0f85e298901e51161205788322e1a995e3764329020368058" +checksum = "56cb150fd6b55b3023714a3aaa1e3bdadfd44f164efc54fad69efc69aac36887" dependencies = [ "actix-http", "actix-web", @@ -7977,9 +8226,9 @@ dependencies = [ [[package]] name = "sentry-backtrace" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb1ef7534f583af20452b1b1bf610a60ed9c8dd2d8485e7bd064efc556a78fb" +checksum = "5f8784d0a27b5cd4b5f75769ffc84f0b7580e3c35e1af9cd83cb90b612d769cc" dependencies = [ "backtrace", "regex", @@ -7988,9 +8237,9 @@ dependencies = [ [[package]] name = "sentry-contexts" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd6be899d9938390b6d1ec71e2f53bd9e57b6a9d8b1d5b049e5c364e7da9078" +checksum = "0e5eb42f4cd4f9fdfec9e3b07b25a4c9769df83d218a7e846658984d5948ad3e" dependencies = [ "hostname", "libc", @@ -8002,9 +8251,9 @@ dependencies = [ [[package]] name = "sentry-core" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26ab054c34b87f96c3e4701bea1888317cde30cc7e4a6136d2c48454ab96661c" +checksum = "b0b1e7ca40f965db239da279bf278d87b7407469b98835f27f0c8e59ed189b06" dependencies = [ "rand 0.9.2", "sentry-types", @@ -8015,9 +8264,9 @@ dependencies = [ [[package]] name = "sentry-debug-images" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5637ec550dc6f8c49a711537950722d3fc4baa6fd433c371912104eaff31e2a5" +checksum = "002561e49ea3a9de316e2efadc40fae553921b8ff41448f02ea85fd135a778d6" dependencies = [ "findshlibs", "sentry-core", @@ -8025,9 +8274,9 @@ dependencies = [ [[package]] name = "sentry-panic" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f02c7162f7b69b8de872b439d4696dc1d65f80b13ddd3c3831723def4756b63" +checksum = "8906f8be87aea5ac7ef937323fb655d66607427f61007b99b7cb3504dc5a156c" dependencies = [ "sentry-backtrace", "sentry-core", @@ -8035,11 +8284,11 @@ dependencies = [ [[package]] name = "sentry-tracing" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1dd47df349a80025819f3d25c3d2f751df705d49c65a4cdc0f130f700972a48" +checksum = "5b07eefe04486316c57aba08ab53dd44753c25102d1d3fe05775cc93a13262d9" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "sentry-backtrace", "sentry-core", "tracing-core", @@ -8048,9 +8297,9 @@ dependencies = [ [[package]] name = "sentry-types" -version = "0.46.1" +version = "0.46.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eecbd63e9d15a26a40675ed180d376fcb434635d2e33de1c24003f61e3e2230d" +checksum = "567711f01f86a842057e1fc17779eba33a336004227e1a1e7e6cc2599e22e259" dependencies = [ "debugid", "hex", @@ -8090,7 +8339,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8101,7 +8350,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8142,6 +8391,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_qs" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7715380eec75f029a4ef7de39a9200e0a63823176b759d055b613f5a87df6a6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 1.0.69", +] + [[package]] name = "serde_repr" version = "0.1.20" @@ -8150,7 +8410,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8202,7 +8462,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8252,7 +8512,7 @@ checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8474,7 +8734,7 @@ dependencies = [ "crc", "crossbeam-queue", "either", - "event-listener", + "event-listener 5.4.1", "futures-core", "futures-intrusive", "futures-io", @@ -8511,7 +8771,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8534,7 +8794,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.114", + "syn 2.0.116", "tokio", "url", ] @@ -8547,7 +8807,7 @@ checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "bytes", "chrono", @@ -8592,7 +8852,7 @@ checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" dependencies = [ "atoi", "base64 0.22.1", - "bitflags 2.10.0", + "bitflags 2.11.0", "byteorder", "chrono", "crc", @@ -8719,7 +8979,7 @@ dependencies = [ "dupe", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8841,7 +9101,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8853,7 +9113,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8894,9 +9154,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.114" +version = "2.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" +checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" dependencies = [ "proc-macro2", "quote", @@ -8920,7 +9180,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -8934,11 +9194,11 @@ dependencies = [ [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -8961,12 +9221,12 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" [[package]] name = "tempfile" -version = "3.24.0" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ - "fastrand", - "getrandom 0.3.4", + "fastrand 2.3.0", + "getrandom 0.4.1", "once_cell", "rustix 1.1.3", "windows-sys 0.61.2", @@ -9026,7 +9286,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9037,7 +9297,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "test-case-core", ] @@ -9060,7 +9320,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9109,7 +9369,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9120,7 +9380,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9154,6 +9414,7 @@ checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", "itoa", + "js-sys", "libc", "num-conv", "num_threads", @@ -9264,7 +9525,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9351,9 +9612,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.11+spec-1.1.0" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ "indexmap 2.13.0", "serde_core", @@ -9387,9 +9648,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.24.0+spec-1.1.0" +version = "0.24.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c740b185920170a6d9191122cafef7010bd6270a3824594bff6784c04d7f09e" +checksum = "01f2eadbbc6b377a847be05f60791ef1058d9f696ecb51d2c07fe911d8569d8e" dependencies = [ "indexmap 2.13.0", "toml_datetime", @@ -9400,9 +9661,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" dependencies = [ "winnow", ] @@ -9415,9 +9676,9 @@ checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tonic" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a286e33f82f8a1ee2df63f4fa35c0becf4a85a0cb03091a15fd7bf0b402dc94a" +checksum = "7f32a6f80051a4111560201420c7885d0082ba9efe2ab61875c587bb6b18b9a0" dependencies = [ "async-trait", "base64 0.22.1", @@ -9443,9 +9704,9 @@ dependencies = [ [[package]] name = "tonic-prost" -version = "0.14.3" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c55a2d6a14174563de34409c9f92ff981d006f56da9c6ecd40d9d4a31500b0" +checksum = "9f86539c0089bfd09b1f8c0ab0239d80392af74c21bc9e0f15e1b4aca4c1647f" dependencies = [ "bytes", "prost", @@ -9477,7 +9738,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-util", "http 1.4.0", @@ -9533,7 +9794,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9603,9 +9864,9 @@ dependencies = [ [[package]] name = "tracing-test" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +checksum = "19a4c448db514d4f24c5ddb9f73f2ee71bfb24c526cf0c570ba142d1119e0051" dependencies = [ "tracing-core", "tracing-subscriber", @@ -9614,12 +9875,12 @@ dependencies = [ [[package]] name = "tracing-test-macro" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +checksum = "ad06847b7afb65c7866a36664b75c40b895e318cea4f71299f013fb22965329d" dependencies = [ "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -9630,7 +9891,7 @@ checksum = "78f873475d258561b06f1c595d93308a7ed124d9977cb26b148c2084a4a3cc87" dependencies = [ "cc", "regex", - "regex-syntax 0.8.8", + "regex-syntax 0.8.9", "serde_json", "streaming-iterator", "tree-sitter-language", @@ -9701,7 +9962,7 @@ checksum = "ee6ff59666c9cbaec3533964505d39154dc4e0a56151fdea30a09ed0301f62e2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "termcolor", ] @@ -9740,6 +10001,15 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "tz-rs" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33851b15c848fad2cf4b105c6bb66eb9512b6f6c44a4b13f57c53c73c707e2b4" +dependencies = [ + "const_fn", +] + [[package]] name = "uds_windows" version = "1.1.0" @@ -9799,9 +10069,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" [[package]] name = "unicode-linebreak" @@ -9889,9 +10159,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "3.1.4" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d39cb1dbab692d82a977c0392ffac19e188bd9186a9f32806f0aaa859d75585a" +checksum = "fdc97a28575b85cfedf2a7e7d3cc64b3e11bd8ac766666318003abbacc7a21fc" dependencies = [ "base64 0.22.1", "der", @@ -9955,11 +10225,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.20.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", "serde_core", "sha1_smol", @@ -10014,6 +10284,12 @@ dependencies = [ "libc", ] +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -10033,6 +10309,12 @@ dependencies = [ "try-lock", ] +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -10048,6 +10330,15 @@ 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" @@ -10100,7 +10391,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "wasm-bindgen-shared", ] @@ -10113,6 +10404,28 @@ 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" @@ -10126,6 +10439,18 @@ 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.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "wayland-backend" version = "0.3.12" @@ -10145,7 +10470,7 @@ version = "0.31.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8e6faa537fbb6c186cb9f1d41f2f811a4120d1b57ec61f50da451a0c5122bec" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "rustix 1.1.3", "wayland-backend", "wayland-scanner", @@ -10157,7 +10482,7 @@ version = "0.32.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baeda9ffbcfc8cd6ddaade385eaf2393bd2115a69523c735f12242353c3df4f3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -10169,7 +10494,7 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9597cdf02cf0c34cd5823786dce6b5ae8598f05c2daf5621b6e178d4f7345f3" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -10218,9 +10543,9 @@ dependencies = [ [[package]] name = "webbrowser" -version = "1.0.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97" +checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" dependencies = [ "core-foundation 0.10.1", "jni", @@ -10234,9 +10559,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36a29fc0408b113f68cf32637857ab740edfafdf460c326cd2afaa2d84cc05dc" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -10247,14 +10572,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.5", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -10414,7 +10739,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -10425,7 +10750,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -10436,7 +10761,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -10447,7 +10772,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -10897,6 +11222,88 @@ 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.116", + "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.116", + "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.11.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" @@ -11023,7 +11430,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "synstructure", ] @@ -11044,7 +11451,7 @@ dependencies = [ "async-trait", "blocking", "enumflags2", - "event-listener", + "event-listener 5.4.1", "futures-core", "futures-sink", "futures-util", @@ -11074,7 +11481,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "zvariant_utils", ] @@ -11091,22 +11498,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.37" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.37" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -11126,7 +11533,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "synstructure", ] @@ -11147,7 +11554,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -11181,7 +11588,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] [[package]] @@ -11216,9 +11623,9 @@ dependencies = [ [[package]] name = "zmij" -version = "1.0.19" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff05f8caa9038894637571ae6b9e29466c1f4f829d26c9b28f869a29cbe3445" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" [[package]] name = "zopfli" @@ -11312,7 +11719,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", "zvariant_utils", ] @@ -11324,5 +11731,5 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn 2.0.116", ] diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 75b3d18d3e..c425468870 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -151,7 +151,12 @@ assert_matches = "1.5.0" async-channel = "2.3.1" async-stream = "0.3.6" async-trait = "0.1.89" +aws-config = "1" +aws-sdk-s3 = "1" +aws-smithy-types = "1" axum = { version = "0.8", default-features = false } +azure_core = "0.21" +azure_identity = "0.21" base64 = "0.22.1" bm25 = "2.3.2" bytes = "1.10.1" diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 208ba1c3a6..23e39e092a 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -23,6 +23,8 @@ arc-swap = "1.8.0" async-channel = { workspace = true } async-trait = { workspace = true } askama = { workspace = true } +azure_core = { workspace = true } +azure_identity = { workspace = true } base64 = { workspace = true } bm25 = { workspace = true } chardetng = { workspace = true } diff --git a/codex-rs/core/config.schema.json b/codex-rs/core/config.schema.json index c9da5c688b..4935447074 100644 --- a/codex-rs/core/config.schema.json +++ b/codex-rs/core/config.schema.json @@ -1685,6 +1685,10 @@ ], "description": "Sandbox configuration to apply if `sandbox` is `WorkspaceWrite`." }, + "session_object_storage_url": { + "description": "Base URL for the object store used by /share (enterprise/self-hosted).", + "type": "string" + }, "shell_environment_policy": { "allOf": [ { diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index b83a17592c..e5533830b7 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -346,6 +346,9 @@ pub struct Config { /// Base URL for requests to ChatGPT (as opposed to the OpenAI API). pub chatgpt_base_url: String, + /// Optional base URL for storing shared session rollouts in an object store. + pub session_object_storage_url: Option, + /// When set, restricts ChatGPT login to a specific workspace identifier. pub forced_chatgpt_workspace_id: Option, @@ -947,6 +950,9 @@ pub struct ConfigToml { /// When unset, Codex will bind to an ephemeral port chosen by the OS. pub mcp_oauth_callback_port: Option, + /// Base URL for the object store used by /share (enterprise/self-hosted). + pub session_object_storage_url: Option, + /// User-defined provider entries that extend/override the built-in list. #[serde(default)] pub model_providers: HashMap, @@ -1629,6 +1635,16 @@ impl Config { } }); + let session_object_storage_url = + cfg.session_object_storage_url.as_ref().and_then(|value| { + let trimmed = value.trim(); + if trimmed.is_empty() { + None + } else { + Some(trimmed.to_string()) + } + }); + let forced_login_method = cfg.forced_login_method; let model = model.or(config_profile.model).or(cfg.model); @@ -1815,6 +1831,7 @@ impl Config { .chatgpt_base_url .or(cfg.chatgpt_base_url) .unwrap_or("https://chatgpt.com/backend-api/".to_string()), + session_object_storage_url, forced_chatgpt_workspace_id, forced_login_method, include_apply_patch_tool: include_apply_patch_tool_flag, diff --git a/codex-rs/core/src/lib.rs b/codex-rs/core/src/lib.rs index 91bbe042ef..93e2e4e462 100644 --- a/codex-rs/core/src/lib.rs +++ b/codex-rs/core/src/lib.rs @@ -57,6 +57,7 @@ mod proposed_plan_parser; mod sandbox_tags; pub mod sandboxing; mod session_prefix; +pub mod session_share; mod shell_detect; mod stream_events_utils; mod tagged_block_parser; diff --git a/codex-rs/core/src/session_share.rs b/codex-rs/core/src/session_share.rs new file mode 100644 index 0000000000..ac71cf0212 --- /dev/null +++ b/codex-rs/core/src/session_share.rs @@ -0,0 +1,641 @@ +use std::path::Path; +use std::sync::Arc; + +use anyhow::Context; +use aws_config::BehaviorVersion; +use aws_config::meta::region::RegionProviderChain; +use aws_sdk_s3::Client as S3Client; +use aws_sdk_s3::error::SdkError; +use aws_sdk_s3::primitives::ByteStream; +use aws_smithy_types::error::metadata::ProvideErrorMetadata; +use azure_core::auth::TokenCredential; +use azure_identity::AzureCliCredential; +use codex_protocol::ThreadId; +use reqwest::StatusCode; +use reqwest::Url; +use serde::Deserialize; +use serde::Serialize; +use time::OffsetDateTime; + +const SHARE_OBJECT_PREFIX: &str = "sessions"; +const SHARE_OBJECT_SUFFIX: &str = ".jsonl"; +const SHARE_META_SUFFIX: &str = ".meta.json"; +const AZURE_STORAGE_SCOPE: &str = "https://storage.azure.com/.default"; + +#[derive(Debug, Clone)] +pub struct SessionShareResult { + pub remote_id: ThreadId, + pub object_url: Url, +} + +#[derive(Debug, Clone)] +enum SessionObjectStore { + Http(HttpObjectStore), + S3(S3ObjectStore), + Azure(AzureObjectStore), +} + +#[derive(Debug, Clone)] +struct HttpObjectStore { + base_url: Url, + client: reqwest::Client, +} + +#[derive(Debug, Clone)] +struct S3ObjectStore { + client: S3Client, + bucket: String, + prefix: String, +} + +#[derive(Debug, Clone)] +struct AzureObjectStore { + endpoint: Url, + container: String, + prefix: String, + sas_query: Option, + client: reqwest::Client, + credential: Option>, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct SessionShareMeta { + owner: String, + created_at: i64, + updated_at: i64, +} + +impl SessionObjectStore { + pub async fn new(base_url: &str) -> anyhow::Result { + let mut url = Url::parse(base_url) + .with_context(|| format!("invalid session_object_storage_url: {base_url}"))?; + match url.scheme() { + "s3" => Ok(SessionObjectStore::S3(S3ObjectStore::new(&url).await?)), + "az" => Ok(SessionObjectStore::Azure(AzureObjectStore::new_from_az( + &url, + )?)), + "http" | "https" => { + if is_azure_blob_url(&url) { + Ok(SessionObjectStore::Azure(AzureObjectStore::new(&url)?)) + } else { + ensure_trailing_slash(&mut url); + Ok(SessionObjectStore::Http(HttpObjectStore { + base_url: url, + client: reqwest::Client::new(), + })) + } + } + other => Err(anyhow::anyhow!( + "unsupported session_object_storage_url scheme {other}" + )), + } + } + + fn object_url(&self, key: &str) -> anyhow::Result { + match self { + SessionObjectStore::Http(store) => store.object_url(key), + SessionObjectStore::S3(store) => store.object_url(key), + SessionObjectStore::Azure(store) => store.object_url(key), + } + } + + async fn object_exists(&self, key: &str) -> anyhow::Result { + match self { + SessionObjectStore::Http(store) => store.object_exists(key).await, + SessionObjectStore::S3(store) => store.object_exists(key).await, + SessionObjectStore::Azure(store) => store.object_exists(key).await, + } + } + + async fn put_object(&self, key: &str, data: Vec, content_type: &str) -> anyhow::Result<()> { + match self { + SessionObjectStore::Http(store) => store.put_object(key, data, content_type).await, + SessionObjectStore::S3(store) => store.put_object(key, data, content_type).await, + SessionObjectStore::Azure(store) => store.put_object(key, data, content_type).await, + } + } + + async fn get_object_bytes(&self, key: &str) -> anyhow::Result>> { + match self { + SessionObjectStore::Http(store) => store.get_object_bytes(key).await, + SessionObjectStore::S3(store) => store.get_object_bytes(key).await, + SessionObjectStore::Azure(store) => store.get_object_bytes(key).await, + } + } +} + +pub async fn upload_rollout_with_owner( + base_url: &str, + session_id: ThreadId, + owner: &str, + rollout_path: &Path, +) -> anyhow::Result { + let data = tokio::fs::read(rollout_path) + .await + .with_context(|| format!("failed to read rollout at {}", rollout_path.display()))?; + let store = SessionObjectStore::new(base_url).await?; + let key = object_key(session_id); + let meta_key = meta_key(session_id); + let exists = store.object_exists(&key).await?; + let now = OffsetDateTime::now_utc().unix_timestamp(); + + if exists { + let meta = fetch_meta(&store, &meta_key).await?; + let Some(meta) = meta else { + return Err(anyhow::anyhow!( + "remote session already exists without metadata; refusing to overwrite" + )); + }; + if meta.owner != owner { + return Err(anyhow::anyhow!( + "remote session already exists and belongs to another user" + )); + } + store + .put_object(&key, data, "application/x-ndjson") + .await + .with_context(|| format!("failed to upload rollout for id {session_id}"))?; + let updated = SessionShareMeta { + owner: meta.owner, + created_at: meta.created_at, + updated_at: now, + }; + upload_meta(&store, &meta_key, &updated).await?; + } else { + store + .put_object(&key, data, "application/x-ndjson") + .await + .with_context(|| format!("failed to upload rollout for id {session_id}"))?; + let meta = SessionShareMeta { + owner: owner.to_string(), + created_at: now, + updated_at: now, + }; + upload_meta(&store, &meta_key, &meta).await?; + } + + let object_url = store.object_url(&key)?; + Ok(SessionShareResult { + remote_id: session_id, + object_url, + }) +} + +fn object_key(id: ThreadId) -> String { + format!("{SHARE_OBJECT_PREFIX}/{id}{SHARE_OBJECT_SUFFIX}") +} + +fn meta_key(id: ThreadId) -> String { + format!("{SHARE_OBJECT_PREFIX}/{id}{SHARE_META_SUFFIX}") +} + +async fn fetch_meta( + store: &SessionObjectStore, + key: &str, +) -> anyhow::Result> { + let Some(bytes) = store.get_object_bytes(key).await? else { + return Ok(None); + }; + let meta: SessionShareMeta = + serde_json::from_slice(&bytes).with_context(|| "failed to parse session share metadata")?; + Ok(Some(meta)) +} + +async fn upload_meta( + store: &SessionObjectStore, + key: &str, + meta: &SessionShareMeta, +) -> anyhow::Result<()> { + let payload = serde_json::to_vec(meta).with_context(|| "failed to serialize metadata")?; + store.put_object(key, payload, "application/json").await?; + Ok(()) +} + +impl HttpObjectStore { + fn object_url(&self, key: &str) -> anyhow::Result { + self.base_url + .join(key) + .with_context(|| format!("failed to build object URL for key {key}")) + } + + async fn object_exists(&self, key: &str) -> anyhow::Result { + let url = self.object_url(key)?; + let response = self.client.head(url).send().await?; + match response.status() { + StatusCode::NOT_FOUND => Ok(false), + StatusCode::METHOD_NOT_ALLOWED | StatusCode::NOT_IMPLEMENTED => { + self.object_exists_via_get(key).await + } + status if status.is_success() => Ok(true), + status => Err(anyhow::anyhow!( + "object store HEAD failed with status {status}" + )), + } + } + + async fn object_exists_via_get(&self, key: &str) -> anyhow::Result { + let url = self.object_url(key)?; + let response = self + .client + .get(url) + .header(reqwest::header::RANGE, "bytes=0-0") + .send() + .await?; + match response.status() { + StatusCode::NOT_FOUND => Ok(false), + StatusCode::PARTIAL_CONTENT | StatusCode::OK => Ok(true), + status => Err(anyhow::anyhow!( + "object store GET probe failed with status {status}" + )), + } + } + + async fn put_object(&self, key: &str, data: Vec, content_type: &str) -> anyhow::Result<()> { + let url = self.object_url(key)?; + let response = self + .client + .put(url) + .header(reqwest::header::CONTENT_TYPE, content_type) + .body(data) + .send() + .await?; + if response.status().is_success() { + Ok(()) + } else { + Err(anyhow::anyhow!( + "object store PUT failed with status {}", + response.status() + )) + } + } + + async fn get_object_bytes(&self, key: &str) -> anyhow::Result>> { + let url = self.object_url(key)?; + let response = self.client.get(url).send().await?; + match response.status() { + StatusCode::NOT_FOUND => Ok(None), + status if status.is_success() => { + let bytes = response.bytes().await?; + Ok(Some(bytes.to_vec())) + } + status => Err(anyhow::anyhow!( + "object store GET failed with status {status}" + )), + } + } +} + +impl S3ObjectStore { + async fn new(url: &Url) -> anyhow::Result { + let bucket = url + .host_str() + .ok_or_else(|| anyhow::anyhow!("s3 url missing bucket"))? + .to_string(); + let prefix = url + .path() + .trim_start_matches('/') + .trim_end_matches('/') + .to_string(); + let region_provider = RegionProviderChain::default_provider(); + let shared_config = aws_config::defaults(BehaviorVersion::latest()) + .region(region_provider) + .load() + .await; + if shared_config.region().is_none() { + return Err(anyhow::anyhow!( + "AWS region not set. Set AWS_REGION or configure a default region." + )); + } + let client = S3Client::new(&shared_config); + Ok(Self { + client, + bucket, + prefix, + }) + } + + fn object_url(&self, key: &str) -> anyhow::Result { + let full_key = join_prefix(&self.prefix, key); + Url::parse(&format!("s3://{}/{}", self.bucket, full_key)) + .with_context(|| format!("failed to build s3 url for key {full_key}")) + } + + async fn object_exists(&self, key: &str) -> anyhow::Result { + let full_key = join_prefix(&self.prefix, key); + let response = self + .client + .head_object() + .bucket(&self.bucket) + .key(&full_key) + .send() + .await; + match response { + Ok(_) => Ok(true), + Err(err) => match err { + SdkError::ServiceError(service) => { + let code = service.err().code(); + if matches!(code, Some("NotFound") | Some("NoSuchKey")) { + Ok(false) + } else { + Err(anyhow::anyhow!( + "object store HEAD failed with status {:?}", + code + )) + } + } + other => Err(anyhow::anyhow!("object store HEAD failed: {other}")), + }, + } + } + + async fn put_object(&self, key: &str, data: Vec, content_type: &str) -> anyhow::Result<()> { + let full_key = join_prefix(&self.prefix, key); + self.client + .put_object() + .bucket(&self.bucket) + .key(&full_key) + .content_type(content_type) + .body(ByteStream::from(data)) + .send() + .await + .with_context(|| format!("failed to upload s3://{}/{}", self.bucket, full_key))?; + Ok(()) + } + + async fn get_object_bytes(&self, key: &str) -> anyhow::Result>> { + let full_key = join_prefix(&self.prefix, key); + let response = self + .client + .get_object() + .bucket(&self.bucket) + .key(&full_key) + .send() + .await; + match response { + Ok(output) => { + let bytes = output.body.collect().await?; + Ok(Some(bytes.into_bytes().to_vec())) + } + Err(err) => match err { + SdkError::ServiceError(service) => { + let code = service.err().code(); + if matches!(code, Some("NotFound") | Some("NoSuchKey")) { + Ok(None) + } else { + Err(anyhow::anyhow!( + "object store GET failed with status {:?}", + code + )) + } + } + other => Err(anyhow::anyhow!("object store GET failed: {other}")), + }, + } + } +} + +impl AzureObjectStore { + fn new(url: &Url) -> anyhow::Result { + let endpoint = azure_endpoint(url)?; + let (container, prefix) = azure_container_and_prefix(url)?; + let sas_query = url.query().map(str::to_string); + let credential = if sas_query.is_some() { + None + } else { + let credential: Arc = Arc::new(AzureCliCredential::new()); + Some(credential) + }; + Ok(Self { + endpoint, + container, + prefix, + sas_query, + client: reqwest::Client::new(), + credential, + }) + } + + fn new_from_az(url: &Url) -> anyhow::Result { + let account = url + .host_str() + .ok_or_else(|| anyhow::anyhow!("az url missing account name"))?; + let endpoint = azure_endpoint_for_account(account)?; + let (container, prefix) = azure_container_and_prefix(url)?; + let sas_query = url.query().map(str::to_string); + let credential = if sas_query.is_some() { + None + } else { + let credential: Arc = Arc::new(AzureCliCredential::new()); + Some(credential) + }; + Ok(Self { + endpoint, + container, + prefix, + sas_query, + client: reqwest::Client::new(), + credential, + }) + } + + fn object_url(&self, key: &str) -> anyhow::Result { + let full_key = join_prefix(&self.prefix, key); + let mut url = self.endpoint.clone(); + if full_key.is_empty() { + url.set_path(&format!("/{}", self.container)); + } else { + url.set_path(&format!("/{}/{}", self.container, full_key)); + } + if let Some(query) = &self.sas_query { + url.set_query(Some(query)); + } + Ok(url) + } + + async fn object_exists(&self, key: &str) -> anyhow::Result { + let url = self.object_url(key)?; + let response = self + .authorized_request(self.client.head(url)) + .await? + .send() + .await?; + match response.status() { + StatusCode::NOT_FOUND => Ok(false), + status if status.is_success() => Ok(true), + status => Err(anyhow::anyhow!( + "azure blob HEAD failed with status {status}{}", + azure_response_context(response.headers()) + )), + } + } + + async fn put_object(&self, key: &str, data: Vec, content_type: &str) -> anyhow::Result<()> { + let url = self.object_url(key)?; + let response = self + .authorized_request( + self.client + .put(url) + .header("x-ms-blob-type", "BlockBlob") + .header(reqwest::header::CONTENT_TYPE, content_type) + .body(data), + ) + .await? + .send() + .await?; + if response.status().is_success() { + Ok(()) + } else { + let status = response.status(); + let headers = azure_response_context(response.headers()); + let body = response.text().await.unwrap_or_default(); + let body_snippet = azure_response_body_snippet(&body); + Err(anyhow::anyhow!( + "azure blob PUT failed with status {status}{headers}{body_snippet}" + )) + } + } + + async fn get_object_bytes(&self, key: &str) -> anyhow::Result>> { + let url = self.object_url(key)?; + let response = self + .authorized_request(self.client.get(url)) + .await? + .send() + .await?; + match response.status() { + StatusCode::NOT_FOUND => Ok(None), + status if status.is_success() => { + let bytes = response.bytes().await?; + Ok(Some(bytes.to_vec())) + } + status => Err(anyhow::anyhow!( + "azure blob GET failed with status {status}{}", + azure_response_context(response.headers()) + )), + } + } +} + +fn ensure_trailing_slash(url: &mut Url) { + let path = url.path(); + if path.ends_with('/') { + return; + } + let trimmed = path.trim_end_matches('/'); + let new_path = if trimmed.is_empty() { + "/".to_string() + } else { + format!("{trimmed}/") + }; + url.set_path(&new_path); +} + +fn join_prefix(prefix: &str, key: &str) -> String { + if prefix.is_empty() { + key.to_string() + } else { + format!("{prefix}/{key}") + } +} + +fn is_azure_blob_url(url: &Url) -> bool { + let Some(host) = url.host_str() else { + return false; + }; + host.ends_with(".blob.core.windows.net") +} + +fn azure_endpoint(url: &Url) -> anyhow::Result { + let mut endpoint = url.clone(); + endpoint.set_path("/"); + endpoint.set_query(None); + endpoint.set_fragment(None); + Ok(endpoint) +} + +fn azure_container_and_prefix(url: &Url) -> anyhow::Result<(String, String)> { + let segments = url + .path_segments() + .map(|iter| { + iter.filter(|segment| !segment.is_empty()) + .collect::>() + }) + .unwrap_or_default(); + azure_container_and_prefix_from_segments(&segments) +} + +fn azure_container_and_prefix_from_segments(segments: &[&str]) -> anyhow::Result<(String, String)> { + if segments.is_empty() { + return Err(anyhow::anyhow!( + "azure blob url must include a container name" + )); + } + let container = segments[0].to_string(); + let prefix = segments[1..].join("/"); + Ok((container, prefix)) +} + +fn azure_request(builder: reqwest::RequestBuilder) -> reqwest::RequestBuilder { + builder.header("x-ms-version", "2021-08-06") +} + +fn azure_endpoint_for_account(account: &str) -> anyhow::Result { + let endpoint = format!("https://{account}.blob.core.windows.net/"); + Url::parse(&endpoint).with_context(|| "failed to build azure blob endpoint") +} + +impl AzureObjectStore { + async fn authorized_request( + &self, + builder: reqwest::RequestBuilder, + ) -> anyhow::Result { + let builder = azure_request(builder); + let Some(credential) = &self.credential else { + return Ok(builder); + }; + let token = credential + .get_token(&[AZURE_STORAGE_SCOPE]) + .await + .with_context(|| "failed to acquire azure blob access token")?; + Ok(builder.bearer_auth(token.token.secret())) + } +} + +fn azure_response_context(headers: &reqwest::header::HeaderMap) -> String { + let mut parts = Vec::new(); + if let Some(value) = azure_header_value(headers, "x-ms-error-code") { + parts.push(format!("x-ms-error-code={value}")); + } + if let Some(value) = azure_header_value(headers, "x-ms-request-id") { + parts.push(format!("x-ms-request-id={value}")); + } + if let Some(value) = azure_header_value(headers, "www-authenticate") { + parts.push(format!("www-authenticate={value}")); + } + if parts.is_empty() { + String::new() + } else { + format!(" ({})", parts.join(", ")) + } +} + +fn azure_header_value(headers: &reqwest::header::HeaderMap, name: &str) -> Option { + headers + .get(name) + .and_then(|value| value.to_str().ok()) + .map(|value| value.to_string()) +} + +fn azure_response_body_snippet(body: &str) -> String { + let trimmed = body.trim(); + if trimmed.is_empty() { + return String::new(); + } + let snippet = if trimmed.len() <= 512 { + trimmed.to_string() + } else { + let truncated: String = trimmed.chars().take(512).collect(); + format!("{truncated}...") + }; + format!(" (body={snippet})") +} diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index 7bd105695d..08fde9f5d5 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -1633,9 +1633,76 @@ impl App { AppEvent::FatalExitRequest(message) => { return Ok(AppRunControl::Exit(ExitReason::Fatal(message))); } - AppEvent::CodexOp(op) => { - self.chat_widget.submit_op(op); - } + AppEvent::CodexOp(op) => match op { + // Catch potential approvals coming from an external thread and treat them + // directly. This support both command and patch approval. In such case + // the approval get transferred to the corresponding thread and the external + // approval map (`external_approval_routes`) is updated. + Op::ExecApproval { id, decision } => { + if let Some((thread_id, original_id)) = + self.external_approval_routes.remove(&id) + { + // Approval of a sub-agent. + self.forward_external_op( + thread_id, + Op::ExecApproval { + id: original_id, + decision, + }, + ) + .await; + self.finish_external_approval(); + } else { + // This is an approval but not external. + self.chat_widget + .submit_op(Op::ExecApproval { id, decision }); + } + } + Op::PatchApproval { id, decision } => { + if let Some((thread_id, original_id)) = + self.external_approval_routes.remove(&id) + { + // Approval of a sub-agent. + self.forward_external_op( + thread_id, + Op::PatchApproval { + id: original_id, + decision, + }, + ) + .await; + self.finish_external_approval(); + } else { + // This is an approval but not external. + self.chat_widget + .submit_op(Op::PatchApproval { id, decision }); + } + } + Op::UserInputAnswer { id, response } => { + if crate::chatwidget::ChatWidget::is_share_request_id(&id) { + self.chat_widget.handle_share_response(response); + return Ok(AppRunControl::Continue); + } + if let Some((thread_id, original_id)) = + self.external_approval_routes.remove(&id) + { + self.forward_external_op( + thread_id, + Op::UserInputAnswer { + id: original_id, + response, + }, + ) + .await; + self.finish_external_approval(); + } else { + self.chat_widget + .submit_op(Op::UserInputAnswer { id, response }); + } + } + // Standard path where this is not an external approval response. + _ => self.chat_widget.submit_op(op), + }, AppEvent::DiffResult(text) => { // Clear the in-progress state in the bottom pane self.chat_widget.on_diff_complete(); diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index dcbee999bc..e42fee2bdd 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -128,7 +128,11 @@ use codex_protocol::items::AgentMessageItem; use codex_protocol::models::MessagePhase; use codex_protocol::models::local_image_label_text; use codex_protocol::parse_command::ParsedCommand; +use codex_protocol::request_user_input::RequestUserInputAnswer; use codex_protocol::request_user_input::RequestUserInputEvent; +use codex_protocol::request_user_input::RequestUserInputQuestion; +use codex_protocol::request_user_input::RequestUserInputQuestionOption; +use codex_protocol::request_user_input::RequestUserInputResponse; use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; use codex_utils_sleep_inhibitor::SleepInhibitor; @@ -157,6 +161,11 @@ const PLAN_IMPLEMENTATION_YES: &str = "Yes, implement this plan"; const PLAN_IMPLEMENTATION_NO: &str = "No, stay in Plan mode"; const PLAN_IMPLEMENTATION_CODING_MESSAGE: &str = "Implement the plan."; const CONNECTORS_SELECTION_VIEW_ID: &str = "connectors-selection"; +const SHARE_REQUEST_PREFIX: &str = "share:"; +const SHARE_SCOPE_QUESTION_ID: &str = "share_scope"; +const SHARE_EMAILS_QUESTION_ID: &str = "share_emails"; +const SHARE_SCOPE_EVERYONE_LABEL: &str = "Everyone using the same blob store"; +const SHARE_SCOPE_EMAIL_LABEL: &str = "Specific emails"; use crate::app_event::AppEvent; use crate::app_event::ConnectorsSnapshot; @@ -404,6 +413,95 @@ pub(crate) fn get_limits_duration(windows_minutes: i64) -> String { } } +#[derive(Debug, Clone, Copy)] +enum ShareScope { + Everyone, + Emails, +} + +impl ShareScope { + fn label(self) -> &'static str { + match self { + ShareScope::Everyone => SHARE_SCOPE_EVERYONE_LABEL, + ShareScope::Emails => SHARE_SCOPE_EMAIL_LABEL, + } + } +} + +fn parse_share_scope(response: &RequestUserInputResponse) -> ShareScope { + response + .answers + .get(SHARE_SCOPE_QUESTION_ID) + .and_then(|answer| selected_label(answer)) + .map(|label| { + if label == SHARE_SCOPE_EMAIL_LABEL { + ShareScope::Emails + } else { + ShareScope::Everyone + } + }) + .unwrap_or(ShareScope::Everyone) +} + +fn parse_share_emails(response: &RequestUserInputResponse) -> Vec { + let note = response + .answers + .get(SHARE_EMAILS_QUESTION_ID) + .and_then(extract_user_note); + let Some(note) = note else { + return Vec::new(); + }; + note.split(',') + .map(|entry| entry.trim()) + .filter(|entry| !entry.is_empty()) + .map(ToString::to_string) + .collect() +} + +fn selected_label(answer: &RequestUserInputAnswer) -> Option { + answer + .answers + .iter() + .find(|entry| !entry.starts_with("user_note: ")) + .cloned() +} + +fn extract_user_note(answer: &RequestUserInputAnswer) -> Option { + answer + .answers + .iter() + .find_map(|entry| entry.strip_prefix("user_note: ").map(ToString::to_string)) +} + +fn share_success_lines( + remote_id: ThreadId, + scope: ShareScope, + emails: &[String], +) -> Vec> { + let mut lines: Vec> = Vec::new(); + lines.push(vec!["• ".dim(), "Session shared.".into()].into()); + lines.push(vec![" ".into(), "Access: ".dim(), scope.label().into()].into()); + if matches!(scope, ShareScope::Emails) { + let email_list = if emails.is_empty() { + "(none provided)".to_string() + } else { + emails.join(", ") + }; + lines.push(vec![" ".into(), "Emails: ".dim(), email_list.into()].into()); + } + let fork_command = format!("codex fork {remote_id}"); + lines.push(vec![" ".into(), "Fork with: ".dim(), fork_command.cyan()].into()); + lines.push( + vec![ + " ".into(), + "Remote session id: ".dim(), + remote_id.to_string().cyan(), + ] + .into(), + ); + lines +} + /// Common initialization parameters shared by all `ChatWidget` constructors. pub(crate) struct ChatWidgetInit { pub(crate) config: Config, @@ -3262,6 +3360,9 @@ impl ChatWidget { SlashCommand::Fork => { self.app_event_tx.send(AppEvent::ForkCurrentSession); } + SlashCommand::Share => { + self.start_share_flow(); + } SlashCommand::Init => { let init_target = self.config.cwd.join(DEFAULT_PROJECT_DOC_FILENAME); if init_target.exists() { @@ -3632,6 +3733,115 @@ impl ChatWidget { self.bottom_pane.show_view(Box::new(view)); } + fn start_share_flow(&mut self) { + let Some(thread_id) = self.thread_id else { + self.add_error_message("Current session is not ready to share yet.".to_string()); + return; + }; + if self.rollout_path().is_none() { + self.add_error_message("Current session is not ready to share yet.".to_string()); + return; + } + if self.config.session_object_storage_url.is_none() { + self.add_error_message( + "Sharing requires `session_object_storage_url` in config.toml.".to_string(), + ); + return; + } + + let request_id = format!("{SHARE_REQUEST_PREFIX}{thread_id}"); + let questions = vec![ + RequestUserInputQuestion { + id: SHARE_SCOPE_QUESTION_ID.to_string(), + header: "Share".to_string(), + question: "Who should be able to open this shared session?".to_string(), + options: Some(vec![ + RequestUserInputQuestionOption { + label: SHARE_SCOPE_EVERYONE_LABEL.to_string(), + description: "Anyone with access to the same object store.".to_string(), + }, + RequestUserInputQuestionOption { + label: SHARE_SCOPE_EMAIL_LABEL.to_string(), + description: "Restrict to a list of emails (not enforced yet).".to_string(), + }, + ]), + }, + RequestUserInputQuestion { + id: SHARE_EMAILS_QUESTION_ID.to_string(), + header: "Emails".to_string(), + question: "If sharing with specific emails, list them (comma-separated)." + .to_string(), + options: None, + }, + ]; + self.bottom_pane + .push_user_input_request(RequestUserInputEvent { + call_id: request_id.clone(), + turn_id: request_id, + questions, + }); + self.request_redraw(); + } + + pub(crate) fn is_share_request_id(id: &str) -> bool { + id.starts_with(SHARE_REQUEST_PREFIX) + } + + pub(crate) fn handle_share_response(&mut self, response: RequestUserInputResponse) { + let scope = parse_share_scope(&response); + let emails = parse_share_emails(&response); + + // TODO: Enforce email-based access once we have a server-side auth check. + + let Some(storage_url) = self.config.session_object_storage_url.clone() else { + self.add_error_message( + "Sharing requires `session_object_storage_url` in config.toml.".to_string(), + ); + return; + }; + let owner = self + .auth_manager + .auth_cached() + .and_then(|auth| auth.get_account_email()); + let Some(owner) = owner else { + self.add_error_message( + "Sharing requires a signed-in ChatGPT account with an email.".to_string(), + ); + return; + }; + let Some(thread_id) = self.thread_id else { + self.add_error_message("Current session is not ready to share yet.".to_string()); + return; + }; + let Some(rollout_path) = self.rollout_path() else { + self.add_error_message("Current session is not ready to share yet.".to_string()); + return; + }; + + self.add_info_message("Sharing current session…".to_string(), None); + + let app_event_tx = self.app_event_tx.clone(); + tokio::spawn(async move { + let result = codex_core::session_share::upload_rollout_with_owner( + &storage_url, + thread_id, + &owner, + &rollout_path, + ) + .await; + let cell = match result { + Ok(result) => { + let lines = share_success_lines(result.remote_id, scope, &emails); + PlainHistoryCell::new(lines) + } + Err(err) => { + history_cell::new_error_event(format!("Failed to share session: {err}")) + } + }; + app_event_tx.send(AppEvent::InsertHistoryCell(Box::new(cell))); + }); + } + pub(crate) fn handle_paste(&mut self, text: String) { self.bottom_pane.handle_paste(text); } diff --git a/codex-rs/tui/src/slash_command.rs b/codex-rs/tui/src/slash_command.rs index 16e767f802..05ec90867e 100644 --- a/codex-rs/tui/src/slash_command.rs +++ b/codex-rs/tui/src/slash_command.rs @@ -26,6 +26,7 @@ pub enum SlashCommand { New, Resume, Fork, + Share, Init, Compact, Plan, @@ -67,6 +68,7 @@ impl SlashCommand { SlashCommand::Rename => "rename the current thread", SlashCommand::Resume => "resume a saved chat", SlashCommand::Fork => "fork the current chat", + SlashCommand::Share => "share the current chat via object storage", // SlashCommand::Undo => "ask Codex to undo a turn", SlashCommand::Quit | SlashCommand::Exit => "exit Codex", SlashCommand::Diff => "show git diff (including untracked files)", @@ -122,6 +124,7 @@ impl SlashCommand { SlashCommand::New | SlashCommand::Resume | SlashCommand::Fork + | SlashCommand::Share | SlashCommand::Init | SlashCommand::Compact // | SlashCommand::Undo diff --git a/docs/config.md b/docs/config.md index 9d53538cae..0fe11f47ce 100644 --- a/docs/config.md +++ b/docs/config.md @@ -24,6 +24,38 @@ Codex can run a notification hook when the agent finishes a turn. See the config - https://developers.openai.com/codex/config-reference +## Session sharing (enterprise) + +To enable `/share` for enterprise or self-hosted storage, configure: + +``` +session_object_storage_url = "https://your-object-store.example.com/codex-sessions/" +``` + +You can also use AWS S3 with authenticated requests: + +``` +session_object_storage_url = "s3://your-bucket/codex-sessions" +``` + +For S3, Codex uses the default AWS credential chain (env vars, shared config, instance roles, etc.) and requires a region (e.g., `AWS_REGION` or a profile default). + +You can also use Azure Blob Storage with a SAS URL, either as a standard HTTPS URL or the shorthand `az://` form: + +``` +session_object_storage_url = "https://.blob.core.windows.net//codex-sessions?" +``` + +``` +session_object_storage_url = "az:////codex-sessions?" +``` + +For Azure, the SAS token must allow read and write access to blob objects under the prefix. Listing is not required. + +If you omit the SAS token, Codex will try Azure CLI authentication (`az login`) and request storage scope tokens for the blob API. + +For HTTP/HTTPS URLs, the endpoint should support `HEAD`/`PUT` for individual objects. Codex will upload the session rollout (`.jsonl`) under this prefix when sharing. + ## JSON Schema The generated JSON Schema for `config.toml` lives at `codex-rs/core/config.schema.json`.