diff --git a/Cargo.lock b/Cargo.lock index b51d0f1881e6..861de1f71b50 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "agent-client-protocol-schema" -version = "0.10.5" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6903a00e8ac822f9bacac59a1932754d7387c72ebb7c9c7439ad021505591da4" +checksum = "5a871245e59daecd6abf45f516d35445466294ae987dc685106e1676685bfdce" dependencies = [ "anyhow", "derive_more", @@ -199,13 +199,12 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ec5f6c2f8bc326c994cb9e241cc257ddaba9afa8555a43cffbb5dd86efaa37" +checksum = "d10e4f991a553474232bc0a31799f6d24b034a84c0971d80d2e2f78b2e576e40" dependencies = [ "compression-codecs", "compression-core", - "futures-core", "pin-project-lite", "tokio", ] @@ -229,7 +228,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -240,7 +239,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -494,9 +493,9 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.7" +version = "1.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee19095c7c4dda59f1697d028ce704c24b2d33c6718790c7f1d5a3015b4107c" +checksum = "4e0e99800414b0c4cae85ed775a1559f8992f4e69f5ebafe9c936e29609eae78" dependencies = [ "futures-util", "pin-project-lite", @@ -546,7 +545,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "h2 0.3.27", - "h2 0.4.12", + "h2 0.4.13", "http 0.2.12", "http 1.4.0", "http-body 0.4.6", @@ -562,7 +561,7 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls 0.26.4", - "tower 0.5.2", + "tower 0.5.3", "tracing", ] @@ -706,7 +705,7 @@ dependencies = [ "rustversion", "serde", "sync_wrapper 1.0.2", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", ] @@ -742,7 +741,7 @@ dependencies = [ "sync_wrapper 1.0.2", "tokio", "tokio-tungstenite", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -795,7 +794,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -822,9 +821,9 @@ dependencies = [ [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bat" @@ -848,7 +847,7 @@ dependencies = [ "globset", "grep-cli", "home", - "indexmap 2.12.1", + "indexmap 2.13.0", "itertools 0.13.0", "nu-ansi-term", "once_cell", @@ -898,7 +897,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.111", + "syn 2.0.114", "which 4.4.2", ] @@ -1003,7 +1002,7 @@ dependencies = [ "boa_interner", "boa_macros", "boa_string", - "indexmap 2.12.1", + "indexmap 2.13.0", "num-bigint", "rustc-hash 2.1.1", ] @@ -1035,7 +1034,7 @@ dependencies = [ "futures-lite", "hashbrown 0.16.1", "icu_normalizer", - "indexmap 2.12.1", + "indexmap 2.13.0", "intrusive-collections", "itertools 0.14.0", "num-bigint", @@ -1055,7 +1054,7 @@ dependencies = [ "tag_ptr", "tap", "thin-vec", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "xsum", ] @@ -1081,7 +1080,7 @@ dependencies = [ "boa_gc", "boa_macros", "hashbrown 0.16.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "once_cell", "phf", "rustc-hash 2.1.1", @@ -1098,7 +1097,7 @@ dependencies = [ "cow-utils", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] @@ -1218,7 +1217,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1335,9 +1334,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.42" +version = "0.4.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" dependencies = [ "iana-time-zone", "js-sys", @@ -1370,9 +1369,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.53" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e340e012a1bf4935f5282ed1436d1489548e8f72308207ea5df0e23d2d03f8" +checksum = "a75ca66430e33a14957acc24c5077b503e7d374151b2b4b3a10c83b4ceb4be0e" dependencies = [ "clap_builder", "clap_derive", @@ -1380,9 +1379,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.53" +version = "4.5.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76b5d13eaa18c901fd2f7fca939fefe3a0727a953561fefdf3b2922b8569d00" +checksum = "793207c7fa6300a0608d1080b858e5fdbe713cdc1c8db9fb17777d8a13e63df0" dependencies = [ "anstream", "anstyle", @@ -1393,36 +1392,36 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.64" +version = "4.5.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c0da80818b2d95eca9aa614a30783e42f62bf5fdfee24e68cfb960b071ba8d1" +checksum = "430b4dc2b5e3861848de79627b2bedc9f3342c7da5173a14eaa5d0f8dc18ae5d" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.49" +version = "4.5.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" +checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "clap_lex" -version = "0.7.6" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "cliclack" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2381872509dfa50d8b92b92a5da8367ba68458ab9494be4134b57ad6ca26295f" +checksum = "aa510b739c618c679375ea9c5af44ce9f591289546e874ad5910e7ce7df79844" dependencies = [ "console 0.15.11", "indicatif", @@ -1494,9 +1493,9 @@ dependencies = [ [[package]] name = "compression-codecs" -version = "0.4.35" +version = "0.4.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f7ac3e5b97fdce45e8922fb05cae2c37f7bbd63d30dd94821dacfd8f3f2bf2" +checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" dependencies = [ "brotli", "compression-core", @@ -1536,7 +1535,7 @@ dependencies = [ "serde-untagged", "serde_core", "serde_json", - "toml 0.9.10+spec-1.1.0", + "toml 0.9.11+spec-1.1.0", "winnow", "yaml-rust2", ] @@ -1588,7 +1587,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] @@ -1661,16 +1660,6 @@ dependencies = [ "url", ] -[[package]] -name = "cordyceps" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" -dependencies = [ - "loom", - "tracing", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -1811,7 +1800,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1855,7 +1844,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1869,7 +1858,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1882,7 +1871,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1893,7 +1882,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1904,7 +1893,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1915,7 +1904,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -1934,9 +1923,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "dbus" @@ -2006,7 +1995,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2027,7 +2016,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2037,7 +2026,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2059,7 +2048,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.111", + "syn 2.0.114", "unicode-xid", ] @@ -2073,12 +2062,6 @@ dependencies = [ "tree-sitter", ] -[[package]] -name = "diatomic-waker" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" - [[package]] name = "digest" version = "0.10.7" @@ -2164,7 +2147,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2247,7 +2230,7 @@ checksum = "1ec431cd708430d5029356535259c5d645d60edd3d39c54e5eea9782d46caa7d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2300,9 +2283,9 @@ checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" [[package]] name = "env-lock" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2afbd3cff67810192b5bdb76b77feff72775314d41195c1d779bc92e0e83285d" +checksum = "bcb71a32ab9582e2756554e84b24aee90d7187034049c35921ec3296b70c13ad" [[package]] name = "env_filter" @@ -2350,7 +2333,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2489,14 +2472,13 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "f98844151eee8917efc50bd9e8318cb963ae8b297431495d3f758616ea5c57db" dependencies = [ "cfg-if", "libc", "libredox", - "windows-sys 0.60.2", ] [[package]] @@ -2507,9 +2489,9 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369" dependencies = [ "crc32fast", "miniz_oxide", @@ -2544,7 +2526,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", ] [[package]] @@ -2645,19 +2627,6 @@ dependencies = [ "futures-util", ] -[[package]] -name = "futures-buffered" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd" -dependencies = [ - "cordyceps", - "diatomic-waker", - "futures-core", - "pin-project-lite", - "spin 0.10.0", -] - [[package]] name = "futures-channel" version = "0.3.31" @@ -2670,16 +2639,14 @@ dependencies = [ [[package]] name = "futures-concurrency" -version = "7.6.3" +version = "7.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" +checksum = "175cd8cca9e1d45b87f18ffa75088f2099e3c4fe5e2f83e42de112560bea8ea6" dependencies = [ "fixedbitset", - "futures-buffered", "futures-core", "futures-lite", "pin-project", - "slab", "smallvec", ] @@ -2738,7 +2705,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2780,21 +2747,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generator" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f04ae4152da20c76fe800fa48659201d5cf627c5149ca0b707b69d7eef6cf9" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -2807,9 +2759,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -2859,7 +2811,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -2923,7 +2875,7 @@ dependencies = [ "goose-mcp", "ignore", "include_dir", - "indexmap 2.12.1", + "indexmap 2.13.0", "indoc", "insta", "jsonschema", @@ -2986,20 +2938,27 @@ version = "1.22.0" dependencies = [ "anyhow", "assert-json-diff", + "async-stream", "async-trait", "axum 0.8.8", + "bytes", + "clap", "fs-err", "futures", "goose", + "http-body-util", "regex", "rmcp 0.14.0", "sacp", + "serde", "serde_json", "tempfile", "test-case", "tokio", "tokio-util", + "tower-http", "tracing", + "tracing-subscriber", "url", "wiremock", ] @@ -3149,13 +3108,13 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_yaml", - "socket2 0.6.1", + "socket2 0.6.2", "thiserror 1.0.69", "tokio", "tokio-stream", "tokio-tungstenite", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-http", "tracing", "tracing-appender", @@ -3201,7 +3160,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -3210,9 +3169,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -3220,7 +3179,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap 2.12.1", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -3459,7 +3418,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -3502,7 +3461,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tower-service", - "webpki-roots 1.0.4", + "webpki-roots 1.0.5", ] [[package]] @@ -3536,7 +3495,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2 0.6.2", "tokio", "tower-service", "tracing", @@ -3544,9 +3503,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3766,9 +3725,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -3810,9 +3769,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.45.1" +version = "1.46.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "983e3b24350c84ab8a65151f537d67afbbf7153bb9f1110e03e9fa9b07f67a5c" +checksum = "248b42847813a1550dafd15296fd9748c651d0c32194559dbc05d804d54b21e8" dependencies = [ "console 0.15.11", "once_cell", @@ -3905,9 +3864,9 @@ checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "jiff" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a87d9b8105c23642f50cbbae03d1f75d8422c5cb98ce7ee9271f7ff7505be6b8" +checksum = "e67e8da4c49d6d9909fe03361f9b620f58898859f5c7aded68351e85e71ecf50" dependencies = [ "jiff-static", "jiff-tzdb-platform", @@ -3920,13 +3879,13 @@ dependencies = [ [[package]] name = "jiff-static" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b787bebb543f8969132630c51fd0afab173a86c6abae56ff3b9e5e3e3f9f6e58" +checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -3987,9 +3946,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" dependencies = [ "once_cell", "wasm-bindgen", @@ -4080,7 +4039,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.9.8", + "spin", ] [[package]] @@ -4097,9 +4056,9 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libdbus-sys" @@ -4135,9 +4094,9 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" @@ -4218,19 +4177,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - [[package]] name = "lopdf" version = "0.36.0" @@ -4244,7 +4190,7 @@ dependencies = [ "ecb", "encoding_rs", "flate2", - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "jiff", "log", @@ -4256,7 +4202,7 @@ dependencies = [ "rayon", "sha2", "stringprep", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "weezl", ] @@ -4346,9 +4292,9 @@ dependencies = [ [[package]] name = "minijinja" -version = "2.14.0" +version = "2.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ea9ac0a51fb5112607099560fdf0f90366ab088a2a9e6e8ae176794e9806aa" +checksum = "b479616bb6f0779fb0f3964246beda02d4b01144e1b0d5519616e012ccc2a245" dependencies = [ "memo-map", "self_cell", @@ -4405,7 +4351,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4587,9 +4533,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] name = "num-derive" @@ -4599,7 +4545,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4672,7 +4618,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -4692,7 +4638,7 @@ checksum = "51e219e79014df21a225b1860a479e2dcd7cbd9130f4defd4bd0e191ea31d67d" dependencies = [ "base64 0.22.1", "chrono", - "getrandom 0.2.16", + "getrandom 0.2.17", "http 1.4.0", "rand 0.8.5", "reqwest 0.12.28", @@ -5035,20 +4981,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "openssl-probe" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f50d9b3dabb09ecd771ad0aa242ca6894994c130308ca3d7684634df8037391" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.5.4+3.5.4" +version = "300.5.5+3.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507b3792995dae9b0df8a1c1e3771e8418b7c2d9f0baeba32e6fe8b06c7cb72" +checksum = "3f1787d533e03597a7934fd0a765f0d28e94ecc5fb7789f8053b1e699a56f709" dependencies = [ "cc", ] @@ -5287,9 +5233,9 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbcfd20a6d4eeba40179f05735784ad32bdaef05ce8e8af05f180d45bb3e7e22" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" dependencies = [ "memchr", "ucd-trie", @@ -5297,9 +5243,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51f72981ade67b1ca6adc26ec221be9f463f2b5839c7508998daa17c23d94d7f" +checksum = "68f9dbced329c441fa79d80472764b1a2c7e57123553b8519b36663a2fb234ed" dependencies = [ "pest", "pest_generator", @@ -5307,22 +5253,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee9efd8cdb50d719a80088b76f81aec7c41ed6d522ee750178f83883d271625" +checksum = "3bb96d5051a78f44f43c8f712d8e810adb0ebf923fc9ed2655a7f66f63ba8ee5" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "pest_meta" -version = "2.8.4" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf1d70880e76bdc13ba52eafa6239ce793d85c8e43896507e43dd8984ff05b82" +checksum = "602113b5b5e8621770cfd490cfd90b9f84ab29bd2b0e49ad83eb6d186cef2365" dependencies = [ "pest", "sha2", @@ -5358,7 +5304,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5387,7 +5333,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5436,7 +5382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" dependencies = [ "base64 0.22.1", - "indexmap 2.12.1", + "indexmap 2.13.0", "quick-xml 0.38.4", "serde", "time", @@ -5555,7 +5501,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5593,25 +5539,25 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.104" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9695f8df41bb4f3d222c95a67532365f569318332d03d5f3f67f37b20e6ebdf0" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "process-wrap" -version = "9.0.0" +version = "9.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5fd83ab7fa55fd06f5e665e3fc52b8bca451c0486b8ea60ad649cd1c10a5da" +checksum = "fd1395947e69c07400ef4d43db0051d6f773c21f647ad8b97382fc01f0204c60" dependencies = [ "futures", - "indexmap 2.12.1", + "indexmap 2.13.0", "nix 0.30.1", "tokio", "tracing", - "windows 0.61.3", + "windows 0.62.2", ] [[package]] @@ -5634,7 +5580,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -5712,8 +5658,8 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls 0.23.31", - "socket2 0.6.1", - "thiserror 2.0.17", + "socket2 0.6.2", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -5734,7 +5680,7 @@ dependencies = [ "rustls 0.23.31", "rustls-pki-types", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -5749,16 +5695,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.2", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -5797,7 +5743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -5817,7 +5763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -5826,14 +5772,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] @@ -5888,7 +5834,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] @@ -5899,9 +5845,9 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -5921,7 +5867,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6038,7 +5984,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -6062,7 +6008,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.4", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-http", "tower-service", "url", @@ -6070,7 +6016,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 1.0.4", + "webpki-roots 1.0.5", ] [[package]] @@ -6090,7 +6036,7 @@ checksum = "e75ec5e92c4d8aede845126adc388046234541629e76029599ed35a003c7ed24" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", @@ -6112,7 +6058,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -6144,7 +6090,7 @@ dependencies = [ "serde", "serde_json", "sse-stream", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-stream", "tokio-util", @@ -6164,7 +6110,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6177,7 +6123,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6331,9 +6277,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.2" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -6419,7 +6365,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tokio-util", "tracing", @@ -6434,7 +6380,7 @@ checksum = "92150f9246c01d501855e34469810a82adc27c416c8d8e21665567f8cd966f29" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6487,15 +6433,9 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.111", + "syn 2.0.114", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -6556,9 +6496,9 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c2f82143577edb4921b71ede051dac62ca3c16084e918bf7b40c96ae10eb33" +checksum = "b12e76d157a900eb52e81bc6e9f3069344290341720e9178cde2407113ac8d89" [[package]] name = "semver" @@ -6620,7 +6560,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6631,16 +6571,16 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.148" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "memchr", "serde", @@ -6708,7 +6648,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6717,7 +6657,7 @@ version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "itoa", "ryu", "serde", @@ -6726,11 +6666,12 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b258109f244e1d6891bf1053a55d63a5cd4f8f4c30cf9a1280989f80e7a1fa9" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" dependencies = [ - "futures", + "futures-executor", + "futures-util", "log", "once_cell", "parking_lot", @@ -6740,13 +6681,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.2.0" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -6847,15 +6788,15 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "slab" @@ -6899,9 +6840,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", @@ -6916,12 +6857,6 @@ dependencies = [ "lock_api", ] -[[package]] -name = "spin" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" - [[package]] name = "spki" version = "0.7.3" @@ -6977,7 +6912,7 @@ dependencies = [ "hashbrown 0.14.5", "hashlink 0.9.1", "hex", - "indexmap 2.12.1", + "indexmap 2.13.0", "log", "memchr", "once_cell", @@ -7008,7 +6943,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7031,7 +6966,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.111", + "syn 2.0.114", "tempfile", "tokio", "url", @@ -7209,7 +7144,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7230,9 +7165,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -7262,7 +7197,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7281,7 +7216,7 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "thiserror 2.0.17", + "thiserror 2.0.18", "walkdir", "yaml-rust", ] @@ -7436,7 +7371,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7447,7 +7382,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "test-case-core", ] @@ -7479,11 +7414,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -7494,18 +7429,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7552,9 +7487,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.44" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" +checksum = "9da98b7d9b7dad93488a84b8248efc35352b0b2657397d4167e7ad67e5d535e5" dependencies = [ "deranged", "itoa", @@ -7563,22 +7498,22 @@ dependencies = [ "num-conv", "num_threads", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "78cc610bac2dcee56805c99642447d4c5dbde4d01f752ffea0199aee1f601dc4" dependencies = [ "num-conv", "time-core", @@ -7631,7 +7566,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.2", "tokio-macros", "windows-sys 0.61.2", ] @@ -7659,7 +7594,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -7684,9 +7619,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -7730,7 +7665,7 @@ version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -7739,9 +7674,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.10+spec-1.1.0" +version = "0.9.11+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" +checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" dependencies = [ "serde_core", "serde_spanned 1.0.4", @@ -7774,7 +7709,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", @@ -7788,7 +7723,7 @@ version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "winnow", @@ -7820,7 +7755,7 @@ dependencies = [ "axum 0.7.9", "base64 0.22.1", "bytes", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "http-body-util", @@ -7861,9 +7796,9 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -7899,7 +7834,7 @@ dependencies = [ "pin-project-lite", "tokio", "tokio-util", - "tower 0.5.2", + "tower 0.5.3", "tower-layer", "tower-service", "tracing", @@ -7936,7 +7871,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "786d480bce6247ab75f005b14ae1624ad978d3029d9113f0a22fa1ac773faeaf" dependencies = [ "crossbeam-channel", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tracing-subscriber", ] @@ -7949,7 +7884,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8124,7 +8059,7 @@ dependencies = [ "rustls 0.23.31", "rustls-pki-types", "sha1", - "thiserror 2.0.17", + "thiserror 2.0.18", "utf-8", ] @@ -8161,7 +8096,7 @@ dependencies = [ "chrono", "encoding_rs", "fancy-regex 0.14.0", - "getrandom 0.2.16", + "getrandom 0.2.17", "hmac", "html_parser", "imagesize", @@ -8189,9 +8124,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-bidi" @@ -8323,7 +8258,7 @@ version = "4.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" dependencies = [ - "indexmap 2.12.1", + "indexmap 2.13.0", "serde", "serde_json", "utoipa-gen", @@ -8339,14 +8274,14 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] name = "uuid" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ "getrandom 0.3.4", "js-sys", @@ -8422,9 +8357,9 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" dependencies = [ "wit-bindgen", ] @@ -8437,9 +8372,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -8450,11 +8385,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -8463,9 +8399,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8473,22 +8409,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -8508,9 +8444,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -8550,9 +8486,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "12bed680863276c63889429bfd6cab3b99943659923822de1c8a39c49e4d722c" dependencies = [ "rustls-pki-types", ] @@ -8674,24 +8610,23 @@ dependencies = [ [[package]] name = "windows" -version = "0.61.3" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ "windows-collections", - "windows-core 0.61.2", + "windows-core 0.62.2", "windows-future", - "windows-link 0.1.3", "windows-numerics", ] [[package]] name = "windows-collections" -version = "0.2.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -8731,19 +8666,6 @@ dependencies = [ "windows-targets 0.53.5", ] -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement 0.60.2", - "windows-interface 0.59.3", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - [[package]] name = "windows-core" version = "0.62.2" @@ -8759,12 +8681,12 @@ dependencies = [ [[package]] name = "windows-future" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", + "windows-core 0.62.2", + "windows-link 0.2.1", "windows-threading", ] @@ -8776,7 +8698,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8787,7 +8709,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8798,7 +8720,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8809,7 +8731,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8820,7 +8742,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8831,7 +8753,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8842,7 +8764,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -8859,12 +8781,12 @@ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-numerics" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", + "windows-core 0.62.2", + "windows-link 0.2.1", ] [[package]] @@ -8903,15 +8825,6 @@ dependencies = [ "windows-link 0.1.3", ] -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-strings" version = "0.5.1" @@ -9040,11 +8953,11 @@ dependencies = [ [[package]] name = "windows-threading" -version = "0.1.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link 0.1.3", + "windows-link 0.2.1", ] [[package]] @@ -9287,9 +9200,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "write16" @@ -9334,7 +9247,7 @@ dependencies = [ "objc2-foundation", "percent-encoding", "scopeguard", - "thiserror 2.0.17", + "thiserror 2.0.18", "widestring", "windows 0.59.0", "xcb", @@ -9342,9 +9255,9 @@ dependencies = [ [[package]] name = "xcb" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f07c123b796139bfe0603e654eaf08e132e52387ba95b252c78bad3640ba37ea" +checksum = "ee4c580d8205abb0a5cf4eb7e927bd664e425b6c3263f9c5310583da96970cf6" dependencies = [ "bitflags 1.3.2", "libc", @@ -9414,28 +9327,28 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "dafd85c832c1b68bbb4ec0c72c7f6f4fc5179627d2bc7c26b30e4c0cc11e76cc" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "7cb7e4e8436d9db52fbd6625dbf2f45243ab84994a72882ec8227b99e72b439a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -9455,7 +9368,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", "synstructure", ] @@ -9476,7 +9389,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -9510,7 +9423,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.114", ] [[package]] @@ -9544,17 +9457,17 @@ dependencies = [ "crossbeam-utils", "displaydoc", "flate2", - "indexmap 2.12.1", + "indexmap 2.13.0", "memchr", - "thiserror 2.0.17", + "thiserror 2.0.18", "zopfli", ] [[package]] name = "zmij" -version = "1.0.3" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9747e91771f56fd7893e1164abd78febd14a670ceec257caad15e051de35f06" +checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" [[package]] name = "zopfli" diff --git a/crates/goose-acp/Cargo.toml b/crates/goose-acp/Cargo.toml index ab8f3ce64cc0..ed2d9abed105 100644 --- a/crates/goose-acp/Cargo.toml +++ b/crates/goose-acp/Cargo.toml @@ -7,6 +7,10 @@ license.workspace = true repository.workspace = true description.workspace = true +[[bin]] +name = "goose-acp-server" +path = "src/bin/server.rs" + [lints] workspace = true @@ -24,6 +28,16 @@ regex = { workspace = true } fs-err = "3" url = { workspace = true } +# HTTP server dependencies +axum = "0.8" +clap = { version = "4", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } +tower-http = { version = "0.6", features = ["cors"] } +tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] } +async-stream = "0.3.6" +bytes = "1.11.0" +http-body-util = "0.1.3" + [dev-dependencies] assert-json-diff = "2.0.2" async-trait = "0.1.89" diff --git a/crates/goose-acp/src/bin/server.rs b/crates/goose-acp/src/bin/server.rs new file mode 100644 index 000000000000..dcfda549c3e8 --- /dev/null +++ b/crates/goose-acp/src/bin/server.rs @@ -0,0 +1,56 @@ +use anyhow::Result; +use clap::Parser; +use goose_acp::{ + http::{self, HttpState}, + server_factory::{AcpServer, AcpServerFactoryConfig}, +}; +use std::net::SocketAddr; +use std::sync::Arc; +use tracing::info; +use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter}; + +#[derive(Parser)] +#[command(name = "goose-acp-server")] +#[command(about = "ACP server for goose over streamable HTTP")] +struct Cli { + #[arg(long, default_value = "127.0.0.1")] + host: String, + + #[arg(long, default_value = "3284")] + port: u16, + + #[arg(long = "builtin", action = clap::ArgAction::Append)] + builtins: Vec, +} + +#[tokio::main] +async fn main() -> Result<()> { + let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info")); + tracing_subscriber::registry() + .with(filter) + .with(tracing_subscriber::fmt::layer().with_target(true)) + .init(); + + let cli = Cli::parse(); + + let builtins = if cli.builtins.is_empty() { + vec!["developer".to_string()] + } else { + cli.builtins + }; + + let config = AcpServerFactoryConfig { + builtins, + ..Default::default() + }; + + let server = Arc::new(AcpServer::new(config)); + let state = Arc::new(HttpState::new(server)); + + let addr: SocketAddr = format!("{}:{}", cli.host, cli.port).parse()?; + info!("Starting goose-acp-server on {}", addr); + + http::serve(state, addr).await?; + + Ok(()) +} diff --git a/crates/goose-acp/src/http.rs b/crates/goose-acp/src/http.rs new file mode 100644 index 000000000000..5583bfa56d36 --- /dev/null +++ b/crates/goose-acp/src/http.rs @@ -0,0 +1,530 @@ +use anyhow::Result; +use axum::{ + body::Body, + extract::State, + http::{header, Method, Request, StatusCode}, + response::{IntoResponse, Response, Sse}, + routing::{delete, get, post}, + Router, +}; +use http_body_util::BodyExt; +use serde_json::Value; +use std::{ + collections::HashMap, + convert::Infallible, + pin::Pin, + sync::Arc, + task::{Context, Poll}, + time::Duration, +}; +use tokio::sync::{mpsc, Mutex, RwLock}; +use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; +use tower_http::cors::{Any, CorsLayer}; +use tracing::{error, info}; + +use crate::server_factory::AcpServer; + +// ACP header constants +const HEADER_SESSION_ID: &str = "Acp-Session-Id"; +const EVENT_STREAM_MIME_TYPE: &str = "text/event-stream"; +const JSON_MIME_TYPE: &str = "application/json"; + +struct HttpSession { + to_agent_tx: mpsc::Sender, + from_agent_rx: Arc>>, + handle: tokio::task::JoinHandle<()>, +} + +pub struct HttpState { + server: Arc, + sessions: RwLock>, +} + +impl HttpState { + pub fn new(server: Arc) -> Self { + Self { + server, + sessions: RwLock::new(HashMap::new()), + } + } + + async fn create_session(&self) -> Result { + let (to_agent_tx, to_agent_rx) = mpsc::channel::(256); + let (from_agent_tx, from_agent_rx) = mpsc::channel::(256); + + let agent = self.server.create_agent().await.map_err(|e| { + error!("Failed to create agent: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + let session_id = agent.create_session().await.map_err(|e| { + error!("Failed to create ACP session: {}", e); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + let handle = tokio::spawn(async move { + let read_stream = ReceiverToAsyncRead::new(to_agent_rx); + let write_stream = SenderToAsyncWrite::new(from_agent_tx); + + if let Err(e) = + crate::server::serve(agent, read_stream.compat(), write_stream.compat_write()).await + { + error!("ACP session error: {}", e); + } + }); + + self.sessions.write().await.insert( + session_id.clone(), + HttpSession { + to_agent_tx, + from_agent_rx: Arc::new(Mutex::new(from_agent_rx)), + handle, + }, + ); + + info!(session_id = %session_id, "Session created"); + Ok(session_id) + } + + async fn has_session(&self, session_id: &str) -> bool { + self.sessions.read().await.contains_key(session_id) + } + + async fn remove_session(&self, session_id: &str) { + if let Some(session) = self.sessions.write().await.remove(session_id) { + session.handle.abort(); + info!(session_id = %session_id, "Session removed"); + } + } + + async fn send_message(&self, session_id: &str, message: String) -> Result<(), StatusCode> { + let sessions = self.sessions.read().await; + let session = sessions.get(session_id).ok_or(StatusCode::NOT_FOUND)?; + session + .to_agent_tx + .send(message) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR) + } + + async fn get_receiver( + &self, + session_id: &str, + ) -> Result>>, StatusCode> { + let sessions = self.sessions.read().await; + let session = sessions.get(session_id).ok_or(StatusCode::NOT_FOUND)?; + Ok(session.from_agent_rx.clone()) + } +} + +struct ReceiverToAsyncRead { + rx: mpsc::Receiver, + buffer: Vec, + pos: usize, +} + +impl ReceiverToAsyncRead { + fn new(rx: mpsc::Receiver) -> Self { + Self { + rx, + buffer: Vec::new(), + pos: 0, + } + } +} + +impl tokio::io::AsyncRead for ReceiverToAsyncRead { + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut tokio::io::ReadBuf<'_>, + ) -> Poll> { + if self.pos < self.buffer.len() { + let remaining = &self.buffer[self.pos..]; + let to_copy = remaining.len().min(buf.remaining()); + buf.put_slice(&remaining[..to_copy]); + self.pos += to_copy; + if self.pos >= self.buffer.len() { + self.buffer.clear(); + self.pos = 0; + } + return Poll::Ready(Ok(())); + } + + match Pin::new(&mut self.rx).poll_recv(cx) { + Poll::Ready(Some(msg)) => { + let bytes = format!("{}\n", msg).into_bytes(); + let to_copy = bytes.len().min(buf.remaining()); + buf.put_slice(&bytes[..to_copy]); + if to_copy < bytes.len() { + self.buffer = bytes[to_copy..].to_vec(); + self.pos = 0; + } + Poll::Ready(Ok(())) + } + Poll::Ready(None) => Poll::Ready(Ok(())), + Poll::Pending => Poll::Pending, + } + } +} + +struct SenderToAsyncWrite { + tx: mpsc::Sender, + buffer: Vec, +} + +impl SenderToAsyncWrite { + fn new(tx: mpsc::Sender) -> Self { + Self { + tx, + buffer: Vec::new(), + } + } +} + +impl tokio::io::AsyncWrite for SenderToAsyncWrite { + fn poll_write( + mut self: Pin<&mut Self>, + _cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + self.buffer.extend_from_slice(buf); + + while let Some(pos) = self.buffer.iter().position(|&b| b == b'\n') { + let line = String::from_utf8_lossy(&self.buffer[..pos]).to_string(); + self.buffer.drain(..=pos); + + if !line.is_empty() { + if let Err(e) = self.tx.try_send(line.clone()) { + match e { + mpsc::error::TrySendError::Full(_) => { + let truncated: String = line.chars().take(100).collect(); + error!( + "Channel full, dropping message (backpressure): {}", + truncated + ); + } + mpsc::error::TrySendError::Closed(_) => { + return Poll::Ready(Err(std::io::Error::new( + std::io::ErrorKind::BrokenPipe, + "Channel closed", + ))); + } + } + } + } + } + + Poll::Ready(Ok(buf.len())) + } + + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } +} + +fn accepts_mime_type(request: &Request, mime_type: &str) -> bool { + request + .headers() + .get(header::ACCEPT) + .and_then(|v| v.to_str().ok()) + .is_some_and(|accept| accept.contains(mime_type)) +} + +fn accepts_json_and_sse(request: &Request) -> bool { + request + .headers() + .get(header::ACCEPT) + .and_then(|v| v.to_str().ok()) + .is_some_and(|accept| { + accept.contains(JSON_MIME_TYPE) && accept.contains(EVENT_STREAM_MIME_TYPE) + }) +} + +fn content_type_is_json(request: &Request) -> bool { + request + .headers() + .get(header::CONTENT_TYPE) + .and_then(|v| v.to_str().ok()) + .is_some_and(|ct| ct.starts_with(JSON_MIME_TYPE)) +} + +fn get_session_id(request: &Request) -> Option { + request + .headers() + .get(HEADER_SESSION_ID) + .and_then(|v| v.to_str().ok()) + .map(|s| s.to_string()) +} + +fn is_jsonrpc_request(value: &Value) -> bool { + value.get("method").is_some() && value.get("id").is_some() +} + +fn is_jsonrpc_notification(value: &Value) -> bool { + value.get("method").is_some() && value.get("id").is_none() +} + +fn is_jsonrpc_response(value: &Value) -> bool { + value.get("id").is_some() && (value.get("result").is_some() || value.get("error").is_some()) +} + +fn is_initialize_request(value: &Value) -> bool { + value.get("method").is_some_and(|m| m == "initialize") && value.get("id").is_some() +} + +fn create_sse_stream( + receiver: Arc>>, + cleanup: Option<(Arc, String)>, +) -> Sse>> { + let stream = async_stream::stream! { + let mut rx = receiver.lock().await; + while let Some(msg) = rx.recv().await { + yield Ok::<_, Infallible>(axum::response::sse::Event::default().data(msg)); + } + if let Some((state, session_id)) = cleanup { + state.remove_session(&session_id).await; + } + }; + + Sse::new(stream).keep_alive( + axum::response::sse::KeepAlive::new() + .interval(Duration::from_secs(15)) + .text(""), + ) +} + +async fn handle_initialize(state: Arc, json_message: &Value) -> Response { + let new_session_id = match state.create_session().await { + Ok(id) => id, + Err(status) => return status.into_response(), + }; + + let message_str = serde_json::to_string(json_message).unwrap(); + if let Err(status) = state.send_message(&new_session_id, message_str).await { + state.remove_session(&new_session_id).await; + return status.into_response(); + } + + let receiver = match state.get_receiver(&new_session_id).await { + Ok(r) => r, + Err(status) => { + state.remove_session(&new_session_id).await; + return status.into_response(); + } + }; + + let sse = create_sse_stream(receiver, Some((state.clone(), new_session_id.clone()))); + let mut response = sse.into_response(); + response + .headers_mut() + .insert(HEADER_SESSION_ID, new_session_id.parse().unwrap()); + response +} + +async fn handle_request( + state: Arc, + session_id: String, + json_message: &Value, +) -> Response { + if !state.has_session(&session_id).await { + return (StatusCode::NOT_FOUND, "Session not found").into_response(); + } + + let message_str = serde_json::to_string(json_message).unwrap(); + if let Err(status) = state.send_message(&session_id, message_str).await { + return status.into_response(); + } + + let receiver = match state.get_receiver(&session_id).await { + Ok(r) => r, + Err(status) => return status.into_response(), + }; + + create_sse_stream(receiver, None).into_response() +} + +async fn handle_notification_or_response( + state: Arc, + session_id: String, + json_message: &Value, +) -> Response { + if !state.has_session(&session_id).await { + return (StatusCode::NOT_FOUND, "Session not found").into_response(); + } + + let message_str = serde_json::to_string(json_message).unwrap(); + if let Err(status) = state.send_message(&session_id, message_str).await { + return status.into_response(); + } + + StatusCode::ACCEPTED.into_response() +} + +async fn handle_post(State(state): State>, request: Request) -> Response { + if !accepts_json_and_sse(&request) { + return ( + StatusCode::NOT_ACCEPTABLE, + "Not Acceptable: Client must accept both application/json and text/event-stream", + ) + .into_response(); + } + + if !content_type_is_json(&request) { + return ( + StatusCode::UNSUPPORTED_MEDIA_TYPE, + "Unsupported Media Type: Content-Type must be application/json", + ) + .into_response(); + } + + let session_id = get_session_id(&request); + + let body_bytes = match request.into_body().collect().await { + Ok(collected) => collected.to_bytes(), + Err(e) => { + error!("Failed to read request body: {}", e); + return (StatusCode::BAD_REQUEST, "Failed to read request body").into_response(); + } + }; + + let json_message: Value = match serde_json::from_slice(&body_bytes) { + Ok(v) => v, + Err(e) => { + error!("Failed to parse JSON: {}", e); + return (StatusCode::BAD_REQUEST, format!("Invalid JSON: {}", e)).into_response(); + } + }; + + if json_message.is_array() { + return ( + StatusCode::NOT_IMPLEMENTED, + "Batch requests are not supported", + ) + .into_response(); + } + + if is_initialize_request(&json_message) { + handle_initialize(state, &json_message).await + } else if is_jsonrpc_request(&json_message) { + let Some(id) = session_id else { + return ( + StatusCode::BAD_REQUEST, + "Bad Request: Acp-Session-Id header required", + ) + .into_response(); + }; + handle_request(state, id, &json_message).await + } else if is_jsonrpc_notification(&json_message) || is_jsonrpc_response(&json_message) { + let Some(id) = session_id else { + return ( + StatusCode::BAD_REQUEST, + "Bad Request: Acp-Session-Id header required", + ) + .into_response(); + }; + handle_notification_or_response(state, id, &json_message).await + } else { + (StatusCode::BAD_REQUEST, "Invalid JSON-RPC message").into_response() + } +} + +async fn handle_get(State(state): State>, request: Request) -> Response { + if !accepts_mime_type(&request, EVENT_STREAM_MIME_TYPE) { + return ( + StatusCode::NOT_ACCEPTABLE, + "Not Acceptable: Client must accept text/event-stream", + ) + .into_response(); + } + + let session_id = match get_session_id(&request) { + Some(id) => id, + None => { + return ( + StatusCode::BAD_REQUEST, + "Bad Request: Acp-Session-Id header required", + ) + .into_response(); + } + }; + + if !state.has_session(&session_id).await { + return (StatusCode::NOT_FOUND, "Session not found").into_response(); + } + + let receiver = match state.get_receiver(&session_id).await { + Ok(r) => r, + Err(status) => return status.into_response(), + }; + + let stream = async_stream::stream! { + let mut rx = receiver.lock().await; + while let Some(msg) = rx.recv().await { + yield Ok::<_, Infallible>(axum::response::sse::Event::default().data(msg)); + } + }; + + Sse::new(stream) + .keep_alive( + axum::response::sse::KeepAlive::new() + .interval(Duration::from_secs(15)) + .text(""), + ) + .into_response() +} + +async fn handle_delete(State(state): State>, request: Request) -> Response { + let session_id = match get_session_id(&request) { + Some(id) => id, + None => { + return ( + StatusCode::BAD_REQUEST, + "Bad Request: Acp-Session-Id header required", + ) + .into_response(); + } + }; + + if !state.has_session(&session_id).await { + return (StatusCode::NOT_FOUND, "Session not found").into_response(); + } + + state.remove_session(&session_id).await; + StatusCode::ACCEPTED.into_response() +} + +async fn health() -> &'static str { + "ok" +} + +pub fn create_router(state: Arc) -> Router { + let cors = CorsLayer::new() + .allow_origin(Any) + .allow_methods([Method::GET, Method::POST, Method::DELETE, Method::OPTIONS]) + .allow_headers([ + header::CONTENT_TYPE, + header::ACCEPT, + HEADER_SESSION_ID.parse().unwrap(), + ]); + + Router::new() + .route("/health", get(health)) + .route("/acp", post(handle_post)) + .route("/acp", get(handle_get)) + .route("/acp", delete(handle_delete)) + .layer(cors) + .with_state(state) +} + +pub async fn serve(state: Arc, addr: std::net::SocketAddr) -> Result<()> { + let router = create_router(state); + let listener = tokio::net::TcpListener::bind(addr).await?; + info!("ACP HTTP server listening on {}", addr); + axum::serve(listener, router).await?; + Ok(()) +} diff --git a/crates/goose-acp/src/lib.rs b/crates/goose-acp/src/lib.rs index 74f47ad347da..bd21c49fec75 100644 --- a/crates/goose-acp/src/lib.rs +++ b/crates/goose-acp/src/lib.rs @@ -1 +1,5 @@ +#![recursion_limit = "256"] + +pub mod http; pub mod server; +pub mod server_factory; diff --git a/crates/goose-acp/src/server.rs b/crates/goose-acp/src/server.rs index 3bf8d8ca75a7..c2049d669851 100644 --- a/crates/goose-acp/src/server.rs +++ b/crates/goose-acp/src/server.rs @@ -103,14 +103,11 @@ fn extract_tool_locations( ) -> Vec { let mut locations = Vec::new(); - // Get the tool call details if let Ok(tool_call) = &tool_request.tool_call { - // Only process text_editor tool if tool_call.name != "developer__text_editor" { return locations; } - // Extract the path from arguments let path_str = tool_call .arguments .as_ref() @@ -118,50 +115,42 @@ fn extract_tool_locations( .and_then(|p| p.as_str()); if let Some(path_str) = path_str { - // Get the command type let command = tool_call .arguments .as_ref() .and_then(|args| args.get("command")) .and_then(|c| c.as_str()); - // Extract line numbers from the response content if let Ok(result) = &tool_response.tool_result { for content in &result.content { if let RawContent::Text(text_content) = &content.raw { let text = &text_content.text; - // Parse line numbers based on command type and response format match command { Some("view") => { - // For view command, look for "lines X-Y" pattern in header let line = extract_view_line_range(text) .map(|range| range.0 as u32) .or(Some(1)); locations.push(create_tool_location(path_str, line)); } Some("str_replace") | Some("insert") => { - // For edits, extract the first line number from the snippet let line = extract_first_line_number(text) .map(|l| l as u32) .or(Some(1)); locations.push(create_tool_location(path_str, line)); } Some("write") => { - // For write, just point to the beginning of the file locations.push(create_tool_location(path_str, Some(1))); } _ => { - // For other commands or unknown, default to line 1 locations.push(create_tool_location(path_str, Some(1))); } } - break; // Only process first text content + break; } } } - // If we didn't find any locations yet, add a default one if locations.is_empty() { locations.push(create_tool_location(path_str, Some(1))); } @@ -172,12 +161,11 @@ fn extract_tool_locations( } fn extract_view_line_range(text: &str) -> Option<(usize, usize)> { - // Pattern: "(lines X-Y)" or "(lines X-end)" let re = regex::Regex::new(r"\(lines (\d+)-(\d+|end)\)").ok()?; if let Some(caps) = re.captures(text) { let start = caps.get(1)?.as_str().parse::().ok()?; let end = if caps.get(2)?.as_str() == "end" { - start // Use start as a reasonable default + start } else { caps.get(2)?.as_str().parse::().ok()? }; @@ -187,7 +175,6 @@ fn extract_view_line_range(text: &str) -> Option<(usize, usize)> { } fn extract_first_line_number(text: &str) -> Option { - // Pattern: "123: " at the start of a line within a code block let re = regex::Regex::new(r"```[^\n]*\n(\d+):").ok()?; if let Some(caps) = re.captures(text) { return caps.get(1)?.as_str().parse::().ok(); @@ -212,43 +199,30 @@ fn read_resource_link(link: ResourceLink) -> Option { } fn format_tool_name(tool_name: &str) -> String { + let capitalize = |s: &str| { + s.split_whitespace() + .map(|word| { + let mut chars = word.chars(); + match chars.next() { + None => String::new(), + Some(first) => first.to_uppercase().collect::() + chars.as_str(), + } + }) + .collect::>() + .join(" ") + }; + if let Some((extension, tool)) = tool_name.split_once("__") { let formatted_extension = extension.replace('_', " "); let formatted_tool = tool.replace('_', " "); - - // Capitalize first letter of each word - let capitalize = |s: &str| { - s.split_whitespace() - .map(|word| { - let mut chars = word.chars(); - match chars.next() { - None => String::new(), - Some(first) => first.to_uppercase().collect::() + chars.as_str(), - } - }) - .collect::>() - .join(" ") - }; - format!( "{}: {}", capitalize(&formatted_extension), capitalize(&formatted_tool) ) } else { - // Fallback for tools without double underscore let formatted = tool_name.replace('_', " "); - formatted - .split_whitespace() - .map(|word| { - let mut chars = word.chars(); - match chars.next() { - None => String::new(), - Some(first) => first.to_uppercase().collect::() + chars.as_str(), - } - }) - .collect::>() - .join(" ") + capitalize(&formatted) } } @@ -366,31 +340,60 @@ impl GooseAcpAgent { }) } + pub async fn create_session(&self) -> Result { + let manager = self.agent.config.session_manager.clone(); + let goose_session = manager + .create_session( + std::env::current_dir().unwrap_or_default(), + "ACP Session".to_string(), + SessionType::User, + ) + .await?; + + self.agent + .update_provider(self.provider.clone(), &goose_session.id) + .await?; + + let session = GooseAcpSession { + messages: Conversation::new_unvalidated(Vec::new()), + tool_requests: HashMap::new(), + cancel_token: None, + }; + + let mut sessions = self.sessions.lock().await; + sessions.insert(goose_session.id.clone(), session); + + info!( + session_id = %goose_session.id, + session_type = "acp", + "Session created" + ); + + Ok(goose_session.id) + } + + pub async fn has_session(&self, session_id: &str) -> bool { + self.sessions.lock().await.contains_key(session_id) + } + fn convert_acp_prompt_to_message(&self, prompt: Vec) -> Message { let mut user_message = Message::user(); - // Process all content blocks from the prompt for block in prompt { match block { ContentBlock::Text(text) => { user_message = user_message.with_text(&text.text); } ContentBlock::Image(image) => { - // Goose supports images via base64 encoded data - // The ACP ImageContent has data as a String directly user_message = user_message.with_image(&image.data, &image.mime_type); } ContentBlock::Resource(resource) => { - // Embed resource content as text with context - match &resource.resource { - EmbeddedResourceResource::TextResourceContents(text_resource) => { - let header = format!("--- Resource: {} ---\n", text_resource.uri); - let content = format!("{}{}\n---\n", header, text_resource.text); - user_message = user_message.with_text(&content); - } - _ => { - // Ignore non-text resources for now - } + if let EmbeddedResourceResource::TextResourceContents(text_resource) = + &resource.resource + { + let header = format!("--- Resource: {} ---\n", text_resource.uri); + let content = format!("{}{}\n---\n", header, text_resource.text); + user_message = user_message.with_text(&content); } } ContentBlock::ResourceLink(link) => { @@ -398,8 +401,7 @@ impl GooseAcpAgent { user_message = user_message.with_text(text) } } - ContentBlock::Audio(..) => (), - _ => (), // Handle any future ContentBlock variants + ContentBlock::Audio(..) | _ => (), } } @@ -415,7 +417,6 @@ impl GooseAcpAgent { ) -> Result<(), sacp::Error> { match content_item { MessageContent::Text(text) => { - // Stream text to the client cx.send_notification(SessionNotification::new( session_id.clone(), SessionUpdate::AgentMessageChunk(ContentChunk::new(ContentBlock::Text( @@ -432,7 +433,6 @@ impl GooseAcpAgent { .await?; } MessageContent::Thinking(thinking) => { - // Stream thinking/reasoning content as thought chunks cx.send_notification(SessionNotification::new( session_id.clone(), SessionUpdate::AgentThoughtChunk(ContentChunk::new(ContentBlock::Text( @@ -458,9 +458,7 @@ impl GooseAcpAgent { )?; } } - _ => { - // Ignore other content types for now - } + _ => {} } Ok(()) } @@ -472,18 +470,15 @@ impl GooseAcpAgent { session: &mut GooseAcpSession, cx: &JrConnectionCx, ) -> Result<(), sacp::Error> { - // Store the tool request for later use in response handling session .tool_requests .insert(tool_request.id.clone(), tool_request.clone()); - // Extract tool name from the ToolCall if successful let tool_name = match &tool_request.tool_call { Ok(tool_call) => tool_call.name.to_string(), Err(_) => "error".to_string(), }; - // Send tool call notification using the provider's tool call ID directly cx.send_notification(SessionNotification::new( session_id.clone(), SessionUpdate::ToolCall( @@ -513,14 +508,12 @@ impl GooseAcpAgent { let content = build_tool_call_content(&tool_response.tool_result); - // Extract locations from the tool request and response let locations = if let Some(tool_request) = session.tool_requests.get(&tool_response.id) { extract_tool_locations(tool_request, tool_response) } else { Vec::new() }; - // Send status update using provider's tool call ID directly let mut fields = ToolCallUpdateFields::new().status(status).content(content); if !locations.is_empty() { fields = fields.locations(locations); @@ -551,7 +544,6 @@ impl GooseAcpAgent { let formatted_name = format_tool_name(&tool_name); - // Use the request_id (provider's tool call ID) directly let mut fields = ToolCallUpdateFields::new() .title(formatted_name) .kind(ToolKind::default()) @@ -625,11 +617,10 @@ fn outcome_to_confirmation(outcome: &RequestPermissionOutcome) -> PermissionConf Ok(PermissionOptionKind::AllowOnce) => Permission::AllowOnce, Ok(PermissionOptionKind::RejectOnce) => Permission::DenyOnce, Ok(PermissionOptionKind::RejectAlways) => Permission::AlwaysDeny, - Ok(_) => Permission::Cancel, // Handle any future permission kinds - Err(_) => Permission::Cancel, + _ => Permission::Cancel, } } - _ => Permission::Cancel, // Handle any future variants + _ => Permission::Cancel, }; PermissionConfirmation { principal_type: PrincipalType::Tool, @@ -674,14 +665,7 @@ fn build_tool_call_content(tool_result: &ToolResult) -> Vec { - // Audio content is not supported in ACP ContentBlock, skip it - None - } - RawContent::ResourceLink(_) => { - // ResourceLink content is not supported in ACP ContentBlock, skip it - None - } + RawContent::Audio(_) | RawContent::ResourceLink(_) => None, }) .collect(), Err(_) => Vec::new(), @@ -695,7 +679,6 @@ impl GooseAcpAgent { ) -> Result { debug!(?args, "initialize request"); - // Advertise Goose's capabilities let capabilities = AgentCapabilities::new() .load_session(true) .prompt_capabilities( @@ -718,7 +701,7 @@ impl GooseAcpAgent { let goose_session = manager .create_session( args.cwd.clone(), - "ACP Session".to_string(), // just an initial name - may be replaced by maybe_update_name + "ACP Session".to_string(), SessionType::User, ) .await @@ -727,7 +710,6 @@ impl GooseAcpAgent { })?; self.update_session_with_provider(&goose_session).await?; - // Add MCP servers specified in the session request for mcp_server in args.mcp_servers { let config = match mcp_server_to_extension_config(mcp_server) { Ok(c) => c, @@ -810,9 +792,7 @@ impl GooseAcpAgent { cancel_token: None, }; - // Replay conversation history to client for message in conversation.messages() { - // Only replay user-visible messages if !message.metadata.user_visible { continue; } @@ -853,9 +833,7 @@ impl GooseAcpAgent { )), ))?; } - _ => { - // Ignore other content types - } + _ => {} } } } @@ -1015,8 +993,6 @@ impl JrMessageHandler for GooseAcpHandler { .await .if_request( |req: PromptRequest, req_cx: JrRequestCx| async { - // Spawn the prompt processing in a task so we don't block the event loop. - // This allows permission responses to be processed while the agent is working. let agent = self.agent.clone(); let cx_clone = cx.clone(); cx.spawn(async move { @@ -1042,7 +1018,6 @@ impl JrMessageHandler for GooseAcpHandler { } } -/// Serve ACP on a given transport (for in-process testing) pub async fn serve(agent: Arc, read: R, write: W) -> Result<()> where R: futures::AsyncRead + Unpin + Send + 'static, @@ -1188,14 +1163,6 @@ print(\"hello, world\") assert_eq!(format_tool_name("single"), "Single"); } - #[test] - fn test_format_tool_name_edge_cases() { - assert_eq!(format_tool_name(""), ""); - assert_eq!(format_tool_name("__"), ": "); - assert_eq!(format_tool_name("extension__"), "Extension: "); - assert_eq!(format_tool_name("__tool"), ": Tool"); - } - #[test_case( RequestPermissionOutcome::Selected(SelectedPermissionOutcome::new(PermissionOptionId::from("allow_once".to_string()))), PermissionConfirmation { principal_type: PrincipalType::Tool, permission: Permission::AllowOnce }; diff --git a/crates/goose-acp/src/server_factory.rs b/crates/goose-acp/src/server_factory.rs new file mode 100644 index 000000000000..0244e86084c6 --- /dev/null +++ b/crates/goose-acp/src/server_factory.rs @@ -0,0 +1,76 @@ +use anyhow::Result; +use goose::config::paths::Paths; +use goose::config::Config; +use goose::model::ModelConfig; +use goose::providers::create; +use std::sync::Arc; +use tracing::info; + +use crate::server::{AcpServerConfig, GooseAcpAgent}; + +pub struct AcpServerFactoryConfig { + pub builtins: Vec, + pub data_dir: std::path::PathBuf, + pub config_dir: std::path::PathBuf, +} + +impl Default for AcpServerFactoryConfig { + fn default() -> Self { + Self { + builtins: vec!["developer".to_string()], + data_dir: Paths::data_dir(), + config_dir: Paths::config_dir(), + } + } +} + +pub struct AcpServer { + config: AcpServerFactoryConfig, +} + +impl AcpServer { + pub fn new(config: AcpServerFactoryConfig) -> Self { + Self { config } + } + + pub async fn create_agent(&self) -> Result> { + let global_config = Config::global(); + + let provider_name: String = global_config + .get_goose_provider() + .map_err(|e| anyhow::anyhow!("No provider configured: {}", e))?; + + let model_name: String = global_config + .get_goose_model() + .map_err(|e| anyhow::anyhow!("No model configured: {}", e))?; + + let model_config = ModelConfig { + request_params: None, + model_name: model_name.clone(), + context_limit: None, + temperature: None, + max_tokens: None, + toolshim: false, + toolshim_model: None, + fast_model: None, + }; + + let provider = create(&provider_name, model_config).await?; + let goose_mode = global_config + .get_goose_mode() + .unwrap_or(goose::config::GooseMode::Auto); + + let acp_config = AcpServerConfig { + provider, + builtins: self.config.builtins.clone(), + data_dir: self.config.data_dir.clone(), + config_dir: self.config.config_dir.clone(), + goose_mode, + }; + + let agent = GooseAcpAgent::with_config(acp_config).await?; + info!("Created new ACP agent"); + + Ok(Arc::new(agent)) + } +}