diff --git a/Cargo.lock b/Cargo.lock index e8c8246d4344..e36d91c55570 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,6 +74,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -198,7 +207,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -276,7 +285,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -287,7 +296,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -770,7 +779,7 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "rustc_version", + "rustc_version 0.4.1", "tracing", ] @@ -887,7 +896,7 @@ checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -965,7 +974,7 @@ dependencies = [ "path_abs", "plist", "regex", - "semver", + "semver 1.0.26", "serde", "serde_yaml", "shell-words", @@ -991,7 +1000,7 @@ version = "0.69.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -1004,7 +1013,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.99", + "syn 2.0.111", "which 4.4.2", ] @@ -1052,11 +1061,11 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1096,6 +1105,147 @@ dependencies = [ "generic-array", ] +[[package]] +name = "boa_ast" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc119a5ad34c3f459062a96907f53358989b173d104258891bb74f95d93747e8" +dependencies = [ + "bitflags 2.10.0", + "boa_interner", + "boa_macros", + "boa_string", + "indexmap 2.12.0", + "num-bigint", + "rustc-hash 2.1.1", +] + +[[package]] +name = "boa_engine" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e637ec52ea66d76b0ca86180c259d6c7bb6e6a6e14b2f36b85099306d8b00cc3" +dependencies = [ + "aligned-vec 0.6.4", + "arrayvec", + "bitflags 2.10.0", + "boa_ast", + "boa_gc", + "boa_interner", + "boa_macros", + "boa_parser", + "boa_string", + "bytemuck", + "cfg-if", + "cow-utils", + "dashmap", + "dynify", + "fast-float2", + "float16", + "futures-channel", + "futures-concurrency", + "futures-lite", + "hashbrown 0.16.0", + "icu_normalizer 2.0.1", + "indexmap 2.12.0", + "intrusive-collections", + "itertools 0.14.0", + "num-bigint", + "num-integer", + "num-traits", + "num_enum", + "paste", + "portable-atomic", + "rand 0.9.2", + "regress", + "rustc-hash 2.1.1", + "ryu-js", + "serde", + "serde_json", + "small_btree", + "static_assertions", + "tag_ptr", + "tap", + "thin-vec", + "thiserror 2.0.17", + "time", + "xsum", +] + +[[package]] +name = "boa_gc" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1179f690cbfcbe5364cceee5f1cb577265bb6f07b0be6f210aabe270adcf9da" +dependencies = [ + "boa_macros", + "boa_string", + "hashbrown 0.16.0", + "thin-vec", +] + +[[package]] +name = "boa_interner" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9626505d33dc63d349662437297df1d3afd9d5fc4a2b3ad34e5e1ce879a78848" +dependencies = [ + "boa_gc", + "boa_macros", + "hashbrown 0.16.0", + "indexmap 2.12.0", + "once_cell", + "phf", + "rustc-hash 2.1.1", + "static_assertions", +] + +[[package]] +name = "boa_macros" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f36418a46544b152632c141b0a0b7a453cd69ca150caeef83aee9e2f4b48b7d" +dependencies = [ + "cfg-if", + "cow-utils", + "proc-macro2", + "quote", + "syn 2.0.111", + "synstructure", +] + +[[package]] +name = "boa_parser" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f99bf5b684f0de946378fcfe5f38c3a0fbd51cbf83a0f39ff773a0e218541f" +dependencies = [ + "bitflags 2.10.0", + "boa_ast", + "boa_interner", + "boa_macros", + "fast-float2", + "icu_properties 2.0.2", + "num-bigint", + "num-traits", + "regress", + "rustc-hash 2.1.1", +] + +[[package]] +name = "boa_string" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45ce9d7aa5563a2e14eab111e2ae1a06a69a812f6c0c3d843196c9d03fbef440" +dependencies = [ + "fast-float2", + "itoa", + "paste", + "rustc-hash 2.1.1", + "ryu-js", + "static_assertions", +] + [[package]] name = "borrow-or-share" version = "0.2.2" @@ -1165,9 +1315,23 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.18.0" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" +checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] [[package]] name = "byteorder" @@ -1287,9 +1451,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1392,7 +1556,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1603,6 +1767,16 @@ 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" @@ -1635,7 +1809,7 @@ version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "core-foundation 0.10.0", "core-graphics-types", "foreign-types 0.5.0", @@ -1648,11 +1822,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "core-foundation 0.10.0", "libc", ] +[[package]] +name = "cow-utils" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1796,7 +1976,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1830,7 +2010,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1844,7 +2024,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1855,7 +2035,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1866,7 +2046,7 @@ checksum = "e79f8e61677d5df9167cd85265f8e5f64b215cdea3fb55eebc3e622e44c7a146" dependencies = [ "darling_core 0.21.0", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1945,12 +2125,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.11" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -1961,7 +2141,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1982,7 +2162,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -1992,7 +2172,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -2005,6 +2185,12 @@ 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" @@ -2067,7 +2253,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -2133,6 +2319,26 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" +[[package]] +name = "dynify" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81acb15628a3e22358bf73de5e7e62360b8a777dbcb5fc9ac7dfa9ae73723747" +dependencies = [ + "dynify-macros", +] + +[[package]] +name = "dynify-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec431cd708430d5029356535259c5d645d60edd3d39c54e5eea9782d46caa7d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "either" version = "1.15.0" @@ -2201,6 +2407,26 @@ dependencies = [ "log", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -2298,6 +2524,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "fast-float2" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8eb564c5c7423d25c886fb561d1e4ee69f72354d16918afa32c08811f6b6a55" + [[package]] name = "fastrand" version = "2.3.0" @@ -2336,6 +2568,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + [[package]] name = "flate2" version = "1.1.0" @@ -2346,6 +2584,16 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float16" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bffafbd079d520191c7c2779ae9cf757601266cf4167d3f659ff09617ff8483" +dependencies = [ + "cfg-if", + "rustc_version 0.2.3", +] + [[package]] name = "fluent-uri" version = "0.3.2" @@ -2365,7 +2613,7 @@ checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", - "spin", + "spin 0.9.8", ] [[package]] @@ -2380,6 +2628,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2407,7 +2661,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -2478,6 +2732,19 @@ 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" @@ -2488,6 +2755,21 @@ dependencies = [ "futures-sink", ] +[[package]] +name = "futures-concurrency" +version = "7.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eb68017df91f2e477ed4bea586c59eaecaa47ed885a770d0444e21e62572cd2" +dependencies = [ + "fixedbitset", + "futures-buffered", + "futures-core", + "futures-lite", + "pin-project", + "slab", + "smallvec", +] + [[package]] name = "futures-core" version = "0.3.31" @@ -2522,6 +2804,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -2530,7 +2825,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -2563,6 +2858,20 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.59.0", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -2631,7 +2940,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -2640,7 +2949,7 @@ version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "libc", "libgit2-sys", "log", @@ -2681,6 +2990,8 @@ dependencies = [ "axum 0.8.1", "base64 0.21.7", "blake3", + "boa_engine", + "boa_gc", "chrono", "criterion", "ctor", @@ -3031,7 +3342,7 @@ checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", ] [[package]] @@ -3039,6 +3350,11 @@ name = "hashbrown" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] [[package]] name = "hashlink" @@ -3345,9 +3661,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", - "yoke", + "yoke 0.7.5", + "zerofrom", + "zerovec 0.10.4", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke 0.8.1", "zerofrom", - "zerovec", + "zerovec 0.11.5", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap 0.8.1", + "serde", + "tinystr 0.8.2", + "writeable 0.6.2", + "zerovec 0.11.5", ] [[package]] @@ -3357,10 +3700,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "litemap 0.7.5", + "tinystr 0.7.6", + "writeable 0.5.5", + "zerovec 0.10.4", ] [[package]] @@ -3372,9 +3715,9 @@ dependencies = [ "displaydoc", "icu_locid", "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", + "icu_provider 1.5.0", + "tinystr 0.7.6", + "zerovec 0.10.4", ] [[package]] @@ -3390,15 +3733,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", + "icu_collections 1.5.0", + "icu_normalizer_data 1.5.0", + "icu_properties 1.5.1", + "icu_provider 1.5.0", "smallvec", "utf16_iter", "utf8_iter", "write16", - "zerovec", + "zerovec 0.10.4", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b24a59706036ba941c9476a55cd57b82b77f38a3c667d637ee7cabbc85eaedc" +dependencies = [ + "displaydoc", + "icu_collections 2.0.0", + "icu_normalizer_data 2.0.0", + "icu_properties 2.0.2", + "icu_provider 2.1.1", + "smallvec", + "utf16_iter", + "write16", + "zerovec 0.11.5", ] [[package]] @@ -3407,6 +3767,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + [[package]] name = "icu_properties" version = "1.5.1" @@ -3414,12 +3780,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", - "icu_collections", + "icu_collections 1.5.0", "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", + "icu_properties_data 1.5.0", + "icu_provider 1.5.0", + "tinystr 0.7.6", + "zerovec 0.10.4", +] + +[[package]] +name = "icu_properties" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a97b8ac6235e69506e8dacfb2adf38461d2ce6d3e9bd9c94c4cbc3cd4400a4" +dependencies = [ + "displaydoc", + "icu_collections 2.0.0", + "icu_locale_core", + "icu_properties_data 2.0.1", + "icu_provider 2.1.1", + "potential_utf", + "zerotrie", + "zerovec 0.11.5", ] [[package]] @@ -3428,6 +3810,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + [[package]] name = "icu_provider" version = "1.5.0" @@ -3438,11 +3826,28 @@ dependencies = [ "icu_locid", "icu_provider_macros", "stable_deref_trait", - "tinystr", - "writeable", - "yoke", + "tinystr 0.7.6", + "writeable 0.5.5", + "yoke 0.7.5", + "zerofrom", + "zerovec 0.10.4", +] + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "serde", + "stable_deref_trait", + "writeable 0.6.2", + "yoke 0.8.1", "zerofrom", - "zerovec", + "zerotrie", + "zerovec 0.11.5", ] [[package]] @@ -3453,7 +3858,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -3479,8 +3884,8 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "icu_normalizer", - "icu_properties", + "icu_normalizer 1.5.0", + "icu_properties 1.5.1", ] [[package]] @@ -3646,7 +4051,16 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", +] + +[[package]] +name = "intrusive-collections" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86" +dependencies = [ + "memoffset", ] [[package]] @@ -3711,9 +4125,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -3745,7 +4159,7 @@ checksum = "03343451ff899767262ec32146f6d559dd759fdadf42ff0e227c7c48f72594b4" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -3872,7 +4286,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -3947,7 +4361,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "libc", "redox_syscall", ] @@ -3999,6 +4413,12 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + [[package]] name = "litrs" version = "0.4.1" @@ -4027,6 +4447,19 @@ version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" +[[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 = "loop9" version = "0.1.5" @@ -4055,7 +4488,7 @@ dependencies = [ "nom_locate", "rangemap", "rayon", - "thiserror 2.0.12", + "thiserror 2.0.17", "time", "weezl", ] @@ -4131,6 +4564,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -4208,7 +4650,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -4262,7 +4704,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -4274,7 +4716,7 @@ version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "cfg-if", "cfg_aliases", "libc", @@ -4356,6 +4798,7 @@ checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", + "serde", ] [[package]] @@ -4404,7 +4847,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -4458,6 +4901,37 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "number_prefix" version = "0.4.0" @@ -4514,7 +4988,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "objc2", ] @@ -4529,9 +5003,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.3" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "onig" @@ -4539,7 +5013,7 @@ version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "libc", "once_cell", "onig_sys", @@ -4578,7 +5052,7 @@ version = "0.10.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -4595,7 +5069,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -4846,7 +5320,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b7cafe60d6cf8e62e1b9b2ea516a089c008945bb5a275416789e7db0bc199dc" dependencies = [ "memchr", - "thiserror 2.0.12", + "thiserror 2.0.17", "ucd-trie", ] @@ -4870,7 +5344,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -4884,6 +5358,48 @@ dependencies = [ "sha2", ] +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.111", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -4901,7 +5417,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5021,12 +5537,21 @@ dependencies = [ "chrono", "derive_builder", "reqwest 0.11.27", - "semver", + "semver 1.0.26", "serde", "serde_json", "uuid", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec 0.11.5", +] + [[package]] name = "powerfmt" version = "0.2.0" @@ -5075,7 +5600,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6837b9e10d61f45f987d50808f83d1ee3d206c66acf650c3e4ae2e1f6ddedf55" dependencies = [ "proc-macro2", - "syn 2.0.99", + "syn 2.0.111", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit 0.23.9", ] [[package]] @@ -5104,9 +5638,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ "unicode-ident", ] @@ -5141,7 +5675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5161,10 +5695,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5239,7 +5773,7 @@ dependencies = [ "rustc-hash 2.1.1", "rustls 0.23.31", "socket2 0.5.8", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tracing", ] @@ -5258,7 +5792,7 @@ dependencies = [ "rustls 0.23.31", "rustls-pki-types", "slab", - "thiserror 2.0.12", + "thiserror 2.0.17", "tinyvec", "tracing", "web-time", @@ -5280,9 +5814,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.39" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ "proc-macro2", ] @@ -5444,7 +5978,7 @@ version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", ] [[package]] @@ -5466,7 +6000,7 @@ checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ "getrandom 0.2.15", "libredox", - "thiserror 2.0.12", + "thiserror 2.0.17", ] [[package]] @@ -5486,7 +6020,7 @@ checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5538,6 +6072,16 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "regress" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2057b2325e68a893284d1538021ab90279adac1139957ca2a74426c6f118fb48" +dependencies = [ + "hashbrown 0.16.0", + "memchr", +] + [[package]] name = "reqwest" version = "0.11.27" @@ -5671,7 +6215,7 @@ dependencies = [ "schemars", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-stream", "tokio-util", @@ -5699,7 +6243,7 @@ dependencies = [ "serde", "serde_json", "sse-stream", - "thiserror 2.0.12", + "thiserror 2.0.17", "tokio", "tokio-stream", "tokio-util", @@ -5717,7 +6261,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5730,7 +6274,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -5740,7 +6284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags 2.9.0", + "bitflags 2.10.0", "serde", "serde_derive", ] @@ -5793,13 +6337,22 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver", + "semver 1.0.26", ] [[package]] @@ -5808,7 +6361,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -5821,7 +6374,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "errno", "libc", "linux-raw-sys 0.9.4", @@ -5942,7 +6495,7 @@ version = "15.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2ee1e066dc922e513bda599c6ccb5f3bb2b0ea5870a579448f2622993f0a9a2f" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "cfg-if", "clipboard-win", "fd-lock", @@ -5964,6 +6517,12 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "ryu-js" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd29631678d6fb0903b69223673e122c32e9ae559d0960a38d574695ebc0ea15" + [[package]] name = "same-file" version = "1.0.6" @@ -6014,9 +6573,15 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.99", + "syn 2.0.111", ] +[[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" @@ -6045,7 +6610,7 @@ version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -6058,7 +6623,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", "core-foundation 0.10.0", "core-foundation-sys", "libc", @@ -6081,12 +6646,27 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.228" @@ -6114,7 +6694,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -6125,20 +6705,21 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] name = "serde_json" -version = "1.0.142" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "indexmap 2.12.0", "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -6200,7 +6781,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -6238,7 +6819,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -6347,10 +6928,16 @@ checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.12", + "thiserror 2.0.17", "time", ] +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "slab" version = "0.4.9" @@ -6360,6 +6947,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "small_btree" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ba60d2df92ba73864714808ca68c059734853e6ab722b40e1cf543ebb3a057a" +dependencies = [ + "arrayvec", +] + [[package]] name = "smallvec" version = "1.14.0" @@ -6401,6 +6997,12 @@ 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" @@ -6524,7 +7126,7 @@ checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.9.0", + "bitflags 2.10.0", "byteorder", "bytes", "chrono", @@ -6567,7 +7169,7 @@ checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64 0.21.7", - "bitflags 2.9.0", + "bitflags 2.10.0", "byteorder", "chrono", "crc", @@ -6641,6 +7243,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "std_prelude" version = "0.2.12" @@ -6689,9 +7297,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.99" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -6721,7 +7329,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -6818,6 +7426,18 @@ dependencies = [ "version-compare", ] +[[package]] +name = "tag_ptr" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0e973b34477b7823833469eb0f5a3a60370fef7a453e02d751b59180d0a5a05" + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tar" version = "0.4.44" @@ -6902,7 +7522,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -6913,7 +7533,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", "test-case-core", ] @@ -6930,9 +7550,9 @@ dependencies = [ [[package]] name = "thin-vec" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" +checksum = "144f754d318415ac792f9d69fc87abbbfc043ce2ef041c60f16ad828f638717d" [[package]] name = "thiserror" @@ -6945,11 +7565,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.17", ] [[package]] @@ -6960,18 +7580,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -7019,13 +7639,16 @@ dependencies = [ [[package]] name = "time" -version = "0.3.38" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb041120f25f8fbe8fd2dbe4671c7c2ed74d83be2e7a77529bf7e0790ae3f472" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", "itoa", + "js-sys", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -7034,15 +7657,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef" +checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" [[package]] name = "time-macros" -version = "0.2.20" +version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c" +checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" dependencies = [ "num-conv", "time-core", @@ -7064,7 +7687,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", - "zerovec", + "zerovec 0.10.4", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "serde_core", + "zerovec 0.11.5", ] [[package]] @@ -7133,7 +7767,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -7218,8 +7852,8 @@ checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", - "toml_datetime", - "toml_edit", + "toml_datetime 0.6.8", + "toml_edit 0.22.24", ] [[package]] @@ -7231,6 +7865,15 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" version = "0.22.24" @@ -7240,7 +7883,28 @@ dependencies = [ "indexmap 2.12.0", "serde", "serde_spanned", - "toml_datetime", + "toml_datetime 0.6.8", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.23.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832" +dependencies = [ + "indexmap 2.12.0", + "toml_datetime 0.7.3", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e" +dependencies = [ "winnow", ] @@ -7317,7 +7981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "base64 0.21.7", - "bitflags 2.9.0", + "bitflags 2.10.0", "bytes", "futures-util", "http 1.2.0", @@ -7380,7 +8044,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -7553,7 +8217,7 @@ dependencies = [ "log", "rand 0.9.2", "sha1", - "thiserror 2.0.12", + "thiserror 2.0.17", "utf-8", ] @@ -7572,7 +8236,7 @@ dependencies = [ "rustls 0.23.31", "rustls-pki-types", "sha1", - "thiserror 2.0.12", + "thiserror 2.0.17", "utf-8", ] @@ -7756,7 +8420,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -7786,7 +8450,7 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" dependencies = [ - "aligned-vec", + "aligned-vec 0.5.0", "num-traits", "wasm-bindgen", ] @@ -7883,7 +8547,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", "wasm-bindgen-shared", ] @@ -7918,7 +8582,7 @@ checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -8190,7 +8854,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8201,7 +8865,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8212,7 +8876,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8223,7 +8887,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8234,7 +8898,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8245,7 +8909,7 @@ checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8601,9 +9265,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.3" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] @@ -8664,7 +9328,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" dependencies = [ - "bitflags 2.9.0", + "bitflags 2.10.0", ] [[package]] @@ -8679,6 +9343,12 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + [[package]] name = "xattr" version = "1.5.0" @@ -8730,6 +9400,12 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +[[package]] +name = "xsum" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0637d3a5566a82fa5214bae89087bc8c9fb94cd8e8a3c07feb691bb8d9c632db" + [[package]] name = "yaml-rust" version = "0.4.5" @@ -8758,7 +9434,18 @@ checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", - "yoke-derive", + "yoke-derive 0.7.5", + "zerofrom", +] + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive 0.8.1", "zerofrom", ] @@ -8770,7 +9457,19 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", + "synstructure", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", "synstructure", ] @@ -8792,7 +9491,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", ] [[package]] @@ -8812,7 +9511,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", "synstructure", ] @@ -8833,7 +9532,18 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke 0.8.1", + "zerofrom", ] [[package]] @@ -8842,9 +9552,21 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ - "yoke", + "yoke 0.7.5", "zerofrom", - "zerovec-derive", + "zerovec-derive 0.10.3", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "serde", + "yoke 0.8.1", + "zerofrom", + "zerovec-derive 0.11.2", ] [[package]] @@ -8855,7 +9577,18 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.99", + "syn 2.0.111", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.111", ] [[package]] diff --git a/crates/goose/Cargo.toml b/crates/goose/Cargo.toml index 454761d81a99..5116105983c2 100644 --- a/crates/goose/Cargo.toml +++ b/crates/goose/Cargo.toml @@ -107,12 +107,13 @@ oauth2 = "5.0.0" schemars = { version = "1.0.4", default-features = false, features = ["derive"] } insta = "1.43.2" paste = "1.0.0" +posthog-rs = "0.3.7" shellexpand = "3.1.1" indexmap = "2.12.0" ignore = "0.4.25" which = "8.0.0" -posthog-rs = "0.3.7" - +boa_engine = "0.21.0" +boa_gc = "0.21" [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincred"] } diff --git a/crates/goose/src/agents/code_execution_extension.rs b/crates/goose/src/agents/code_execution_extension.rs new file mode 100644 index 000000000000..e9903c18d232 --- /dev/null +++ b/crates/goose/src/agents/code_execution_extension.rs @@ -0,0 +1,916 @@ +use crate::agents::extension::PlatformExtensionContext; +use crate::agents::extension_manager::get_parameter_names; +use crate::agents::mcp_client::{Error, McpClientTrait}; +use anyhow::Result; +use async_trait::async_trait; +use boa_engine::builtins::promise::PromiseState; +use boa_engine::module::{MapModuleLoader, Module, SyntheticModuleInitializer}; +use boa_engine::property::Attribute; +use boa_engine::{js_string, Context, JsNativeError, JsString, JsValue, NativeFunction, Source}; +use indoc::indoc; +use regex::Regex; +use rmcp::model::{ + CallToolRequestParam, CallToolResult, Content, GetPromptResult, Implementation, + InitializeResult, JsonObject, ListPromptsResult, ListResourcesResult, ListToolsResult, + ProtocolVersion, RawContent, ReadResourceResult, ServerCapabilities, ServerNotification, + Tool as McpTool, ToolAnnotations, ToolsCapability, +}; +use schemars::{schema_for, JsonSchema}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::collections::{BTreeMap, BTreeSet}; +use std::rc::Rc; +use tokio::sync::mpsc; +use tokio_util::sync::CancellationToken; + +pub static EXTENSION_NAME: &str = "code_execution"; + +type ToolCallRequest = ( + String, + String, + tokio::sync::oneshot::Sender>, +); + +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +struct ExecuteCodeParams { + /// JavaScript code with ES6 imports for MCP tools. + code: String, +} + +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +struct ReadModuleParams { + /// Module path format: + /// - For entire server: "server_name" + /// - For specific tool: "server_name/tool_name" + module_path: String, +} + +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +struct SearchModulesParams { + /// Search terms to find servers/tools (case-insensitive). Can be a single string or array of strings. + terms: SearchTerms, + /// If true, treat search terms as regex patterns + #[serde(default)] + regex: bool, +} + +#[derive(Debug, Serialize, Deserialize, JsonSchema)] +#[serde(untagged)] +enum SearchTerms { + Single(String), + Multiple(Vec), +} + +#[derive(Debug, Default, Deserialize)] +struct InputSchema { + #[serde(default)] + properties: BTreeMap, + #[serde(default)] + required: Vec, +} + +struct ToolInfo { + server_name: String, + tool_name: String, + full_name: String, + description: String, + params: Vec<(String, String, bool)>, +} + +impl ToolInfo { + fn from_mcp_tool(tool: &McpTool) -> Option { + let (server_name, tool_name) = tool.name.as_ref().split_once("__")?; + let param_names = get_parameter_names(tool); + + let schema: InputSchema = + serde_json::from_value(Value::Object(tool.input_schema.as_ref().clone())) + .unwrap_or_default(); + + let params = param_names + .iter() + .map(|name| { + let ty = schema + .properties + .get(name) + .and_then(|p| p.get("type")) + .and_then(|t| t.as_str()) + .unwrap_or("any"); + let required = schema.required.contains(name); + (name.clone(), ty.to_string(), required) + }) + .collect(); + + Some(Self { + server_name: server_name.to_string(), + tool_name: tool_name.to_string(), + full_name: tool.name.as_ref().to_string(), + description: tool + .description + .as_ref() + .map(|d| d.as_ref().to_string()) + .unwrap_or_default(), + params, + }) + } + + fn to_signature(&self) -> String { + let params = self + .params + .iter() + .map(|(name, ty, req)| format!("{name}{}: {ty}", if *req { "" } else { "?" })) + .collect::>() + .join(", "); + let desc = self.description.lines().next().unwrap_or(""); + format!("{}({{ {params} }}): string - {desc}", self.tool_name) + } +} + +thread_local! { + static CALL_TX: std::cell::RefCell>> = + const { std::cell::RefCell::new(None) }; +} + +fn create_server_module(server_tools: &[&ToolInfo], ctx: &mut Context) -> Module { + let (export_names, tool_data): (Vec, Vec<(String, String)>) = server_tools + .iter() + .map(|t| { + ( + js_string!(t.tool_name.as_str()), + (t.tool_name.clone(), t.full_name.clone()), + ) + }) + .unzip(); + + Module::synthetic( + &export_names, + SyntheticModuleInitializer::from_copy_closure_with_captures( + |module, tools, context| { + for (tool_name, full_name) in tools { + let func = create_tool_function(full_name.clone()); + let js_func = func.to_js_function(context.realm()); + module.set_export(&js_string!(tool_name.as_str()), js_func.into())?; + } + Ok(()) + }, + tool_data, + ), + None, + None, + ctx, + ) +} + +fn create_tool_function(full_tool_name: String) -> NativeFunction { + NativeFunction::from_copy_closure_with_captures( + |_this, args, full_name: &String, ctx| { + let args_json = args + .first() + .cloned() + .unwrap_or(JsValue::undefined()) + .to_json(ctx) + .map_err(|e| JsNativeError::error().with_message(e.to_string()))? + .unwrap_or(Value::Object(serde_json::Map::new())); + + let args_str = serde_json::to_string(&args_json).unwrap_or_else(|_| "{}".to_string()); + let (tx, rx) = tokio::sync::oneshot::channel(); + + CALL_TX + .with(|call_tx| { + call_tx + .borrow() + .as_ref() + .and_then(|sender| sender.send((full_name.clone(), args_str, tx)).ok()) + }) + .ok_or_else(|| JsNativeError::error().with_message("Channel unavailable"))?; + + rx.blocking_recv() + .map_err(|e| e.to_string()) + .and_then(|r| r) + .map(|result| JsValue::from(js_string!(result.as_str()))) + .map_err(|e| JsNativeError::error().with_message(e).into()) + }, + full_tool_name, + ) +} + +fn run_js_module( + code: &str, + tools: &[ToolInfo], + call_tx: mpsc::UnboundedSender, +) -> Result { + CALL_TX.with(|tx| *tx.borrow_mut() = Some(call_tx)); + + let loader = Rc::new(MapModuleLoader::new()); + let mut ctx = Context::builder() + .module_loader(loader.clone()) + .build() + .map_err(|e| format!("Failed to create JS context: {e}"))?; + + ctx.register_global_property( + js_string!("__result__"), + JsValue::undefined(), + Attribute::WRITABLE, + ) + .map_err(|e| format!("Failed to register __result__: {e}"))?; + + let mut by_server: BTreeMap<&str, Vec<&ToolInfo>> = BTreeMap::new(); + for tool in tools { + by_server.entry(&tool.server_name).or_default().push(tool); + } + + for (server_name, server_tools) in &by_server { + let module = create_server_module(server_tools, &mut ctx); + loader.insert(*server_name, module); + } + + let wrapped = { + let lines: Vec<&str> = code.trim().lines().collect(); + let last_idx = lines + .iter() + .rposition(|l| !l.trim().is_empty() && !l.trim().starts_with("//")) + .unwrap_or(0); + let last = lines.get(last_idx).map(|s| s.trim()).unwrap_or(""); + + const NO_WRAP: &[&str] = &["import ", "export ", "function ", "class "]; + if last.contains("__result__") || NO_WRAP.iter().any(|p| last.starts_with(p)) { + code.to_string() + } else { + let before = lines[..last_idx].join("\n"); + let mut result = None; + for decl in ["const ", "let ", "var "] { + if let Some(rest) = last.strip_prefix(decl) { + if let Some(name) = rest.split('=').next().map(str::trim) { + result = Some(format!("{before}\n{last}\n__result__ = {name};")); + } + break; + } + } + result.unwrap_or_else(|| { + format!("{before}\n__result__ = {};", last.trim_end_matches(';')) + }) + } + }; + + let user_module = Module::parse(Source::from_bytes(&wrapped), None, &mut ctx) + .map_err(|e| format!("Parse error: {e}"))?; + loader.insert("__main__", user_module.clone()); + + let promise = user_module.load_link_evaluate(&mut ctx); + ctx.run_jobs() + .map_err(|e| format!("Job execution error: {e}"))?; + + match promise.state() { + PromiseState::Fulfilled(_) => { + let result = ctx + .global_object() + .get(js_string!("__result__"), &mut ctx) + .map_err(|e| format!("Failed to get result: {e}"))?; + Ok(result.display().to_string()) + } + PromiseState::Rejected(err) => Err(format!("Module error: {}", err.display())), + PromiseState::Pending => Err("Module evaluation did not complete".to_string()), + } +} + +pub struct CodeExecutionClient { + info: InitializeResult, + context: PlatformExtensionContext, +} + +impl CodeExecutionClient { + pub fn new(context: PlatformExtensionContext) -> Result { + let info = InitializeResult { + protocol_version: ProtocolVersion::V_2025_03_26, + capabilities: ServerCapabilities { + tools: Some(ToolsCapability { + list_changed: Some(false), + }), + resources: None, + prompts: None, + completions: None, + experimental: None, + logging: None, + }, + server_info: Implementation { + name: EXTENSION_NAME.to_string(), + title: Some("Code Execution".to_string()), + version: "1.0.0".to_string(), + icons: None, + website_url: None, + }, + instructions: Some(indoc! {r#" + BATCH MULTIPLE TOOL CALLS INTO ONE execute_code CALL. + + This extension exists to reduce round-trips. When a task requires multiple tool calls: + - WRONG: Multiple execute_code calls, each with one tool + - RIGHT: One execute_code call with a script that calls all needed tools + + Workflow: + 1. Use read_module("server") to discover tools and signatures + 2. Write ONE script that imports and calls ALL tools needed for the task + 3. Chain results: use output from one tool as input to the next + "#}.to_string()), + }; + + Ok(Self { info, context }) + } + + async fn get_tool_infos(&self) -> Vec { + let Some(manager) = self + .context + .extension_manager + .as_ref() + .and_then(|w| w.upgrade()) + else { + return Vec::new(); + }; + + match manager.get_prefixed_tools_excluding(EXTENSION_NAME).await { + Ok(tools) if !tools.is_empty() => { + tools.iter().filter_map(ToolInfo::from_mcp_tool).collect() + } + _ => Vec::new(), + } + } + + async fn handle_execute_code( + &self, + arguments: Option, + ) -> Result, String> { + let code = arguments + .as_ref() + .and_then(|a| a.get("code")) + .and_then(|v| v.as_str()) + .ok_or("Missing required parameter: code")? + .to_string(); + + let tools = self.get_tool_infos().await; + let (call_tx, call_rx) = mpsc::unbounded_channel(); + let tool_handler = tokio::spawn(Self::run_tool_handler( + call_rx, + self.context.extension_manager.clone(), + )); + + let js_result = tokio::task::spawn_blocking(move || run_js_module(&code, &tools, call_tx)) + .await + .map_err(|e| format!("JS execution task failed: {e}"))?; + + tool_handler.abort(); + js_result.map(|r| vec![Content::text(format!("Result: {r}"))]) + } + + async fn handle_read_module( + &self, + arguments: Option, + ) -> Result, String> { + let path = arguments + .as_ref() + .and_then(|a| a.get("path")) + .and_then(|v| v.as_str()) + .ok_or("Missing required parameter: path")?; + + let tools = self.get_tool_infos().await; + let parts: Vec<&str> = path.trim_start_matches('/').split('/').collect(); + + match parts.as_slice() { + [server] => { + let server_tools: Vec<_> = + tools.iter().filter(|t| t.server_name == *server).collect(); + if server_tools.is_empty() { + return Err(format!("Module not found: {server}")); + } + let names: Vec<_> = server_tools.iter().map(|t| t.tool_name.as_str()).collect(); + let sigs: Vec<_> = server_tools.iter().map(|t| t.to_signature()).collect(); + Ok(vec![Content::text(format!( + "// import {{ {} }} from \"{server}\";\n\n{}", + names.join(", "), + sigs.join("\n") + ))]) + } + [server, tool] => { + let t = tools + .iter() + .find(|t| t.server_name == *server && t.tool_name == *tool) + .ok_or_else(|| format!("Tool not found: {server}/{tool}"))?; + Ok(vec![Content::text(format!( + "// import {{ {tool} }} from \"{server}\";\n\n{}\n\n{}", + t.to_signature(), + t.description + ))]) + } + _ => Err(format!( + "Invalid path: {path}. Use 'server' or 'server/tool'" + )), + } + } + + async fn handle_search_modules( + &self, + arguments: Option, + ) -> Result, String> { + let terms = arguments + .as_ref() + .and_then(|a| a.get("terms")) + .ok_or("Missing required parameter: terms")?; + + let terms_vec = if let Some(s) = terms.as_str() { + vec![s.to_string()] + } else if let Some(arr) = terms.as_array() { + arr.iter() + .filter_map(|v| v.as_str().map(String::from)) + .collect() + } else { + return Err("Parameter 'terms' must be a string or array of strings".to_string()); + }; + + if terms_vec.is_empty() { + return Err("Search terms cannot be empty".to_string()); + } + + let use_regex = arguments + .as_ref() + .and_then(|a| a.get("regex")) + .and_then(|v| v.as_bool()) + .unwrap_or(false); + + let tools = self.get_tool_infos().await; + Self::handle_search(&tools, &terms_vec, use_regex) + } + + fn handle_search( + tools: &[ToolInfo], + terms: &[String], + use_regex: bool, + ) -> Result, String> { + enum Matcher { + Regex(Vec), + Plain(Vec), + } + + let matcher = if use_regex { + let patterns: Result, _> = terms + .iter() + .map(|t| { + Regex::new(&format!("(?i){t}")).map_err(|e| format!("Invalid regex '{t}': {e}")) + }) + .collect(); + Matcher::Regex(patterns?) + } else { + Matcher::Plain(terms.iter().map(|t| t.to_lowercase()).collect()) + }; + + let matches_any = |text: &str| -> bool { + match &matcher { + Matcher::Regex(patterns) => patterns.iter().any(|p| p.is_match(text)), + Matcher::Plain(terms) => { + let lower = text.to_lowercase(); + terms.iter().any(|t| lower.contains(t)) + } + } + }; + + let mut matching_servers: BTreeSet<&str> = BTreeSet::new(); + let mut matching_tools: Vec<&ToolInfo> = Vec::new(); + + for tool in tools { + if matches_any(&tool.server_name) { + matching_servers.insert(&tool.server_name); + } + if matches_any(&tool.tool_name) || matches_any(&tool.description) { + matching_tools.push(tool); + } + } + + if matching_servers.is_empty() && matching_tools.is_empty() { + return Err(format!("No matches found for: {}", terms.join(", "))); + } + + let mut output = String::new(); + + if !matching_servers.is_empty() { + output.push_str("## Matching Servers\n"); + for server in &matching_servers { + let count = tools.iter().filter(|t| t.server_name == *server).count(); + output.push_str(&format!("- {server} ({count} tools)\n")); + } + output.push('\n'); + } + + if !matching_tools.is_empty() { + output.push_str("## Matching Tools\n"); + for tool in &matching_tools { + output.push_str(&format!( + "- {}/{}: {}\n", + tool.server_name, + tool.tool_name, + tool.description.lines().next().unwrap_or("") + )); + } + } + + Ok(vec![Content::text(output)]) + } + + async fn run_tool_handler( + mut call_rx: mpsc::UnboundedReceiver, + extension_manager: Option>, + ) { + while let Some((tool_name, arguments, response_tx)) = call_rx.recv().await { + let result = match extension_manager.as_ref().and_then(|w| w.upgrade()) { + Some(manager) => { + let tool_call = CallToolRequestParam { + name: tool_name.into(), + arguments: serde_json::from_str(&arguments).ok(), + }; + match manager + .dispatch_tool_call(tool_call, CancellationToken::new()) + .await + { + Ok(dispatch_result) => match dispatch_result.result.await { + Ok(result) => Ok(result + .content + .iter() + .filter_map(|c| match &c.raw { + RawContent::Text(t) => Some(t.text.clone()), + _ => None, + }) + .collect::>() + .join("\n")), + Err(e) => Err(format!("Tool error: {}", e.message)), + }, + Err(e) => Err(format!("Dispatch error: {e}")), + } + } + None => Err("Extension manager not available".to_string()), + }; + let _ = response_tx.send(result); + } + } +} + +#[async_trait] +impl McpClientTrait for CodeExecutionClient { + async fn list_resources( + &self, + _next_cursor: Option, + _cancellation_token: CancellationToken, + ) -> Result { + Err(Error::TransportClosed) + } + + async fn read_resource( + &self, + _uri: &str, + _cancellation_token: CancellationToken, + ) -> Result { + Err(Error::TransportClosed) + } + + async fn list_tools( + &self, + _next_cursor: Option, + _cancellation_token: CancellationToken, + ) -> Result { + fn schema() -> JsonObject { + serde_json::to_value(schema_for!(T)) + .map(|v| v.as_object().unwrap().clone()) + .expect("valid schema") + } + + Ok(ListToolsResult { + tools: vec![ + McpTool::new( + "execute_code".to_string(), + indoc! {r#" + Batch multiple MCP tool calls into ONE execution. This is the primary purpose of this tool. + + CRITICAL: Always combine related operations into a single execute_code call. + - WRONG: execute_code to read → execute_code to write (2 calls) + - RIGHT: execute_code that reads AND writes in one script (1 call) + + EXAMPLE - Read file and write to another (ONE call): + ```javascript + import { text_editor } from "developer"; + const content = text_editor({ path: "/path/to/source.md", command: "view" }); + text_editor({ path: "/path/to/dest.md", command: "write", file_text: content }); + ``` + + EXAMPLE - Multiple operations chained: + ```javascript + import { shell, text_editor } from "developer"; + const files = shell({ command: "ls -la" }); + const readme = text_editor({ path: "./README.md", command: "view" }); + const status = shell({ command: "git status" }); + { files, readme, status } + ``` + + SYNTAX: + - Import: import { tool1, tool2 } from "serverName"; + - Call: toolName({ param1: value, param2: value }) + - All calls are synchronous, return strings + - Last expression is the result + - No comments in code + + BEFORE CALLING: Use read_module("server") to check required parameters. + "#} + .to_string(), + schema::(), + ) + .annotate(ToolAnnotations { + title: Some("Execute JavaScript".to_string()), + read_only_hint: Some(false), + destructive_hint: Some(true), + idempotent_hint: Some(false), + open_world_hint: Some(true), + }), + McpTool::new( + "read_module".to_string(), + indoc! {r#" + Read tool definitions to understand how to call them correctly. + + PATHS: + - "serverName" → lists all tools with signatures (shows required vs optional params) + - "serverName/toolName" → full details for one tool including description + + USE THIS BEFORE execute_code when: + - You haven't used a tool before + - You're unsure of parameter names or which are required + - A previous call failed due to missing/wrong parameters + + The signature format is: toolName({ param1: type, param2?: type }): string + Parameters with ? are optional; others are required. + "#} + .to_string(), + schema::(), + ) + .annotate(ToolAnnotations { + title: Some("Read module".to_string()), + read_only_hint: Some(true), + destructive_hint: Some(false), + idempotent_hint: Some(true), + open_world_hint: Some(false), + }), + McpTool::new( + "search_modules".to_string(), + indoc! {r#" + Search for tools by name or description across all available modules. + + USAGE: + - Single term: search_modules({ terms: "file" }) + - Multiple terms: search_modules({ terms: ["git", "shell"] }) + - Regex patterns: search_modules({ terms: "sh.*", regex: true }) + + Returns matching servers and tools with descriptions. + Use this when you don't know which module contains the tool you need. + "#} + .to_string(), + schema::(), + ) + .annotate(ToolAnnotations { + title: Some("Search modules".to_string()), + read_only_hint: Some(true), + destructive_hint: Some(false), + idempotent_hint: Some(true), + open_world_hint: Some(false), + }), + ], + next_cursor: None, + }) + } + + async fn call_tool( + &self, + name: &str, + arguments: Option, + _cancellation_token: CancellationToken, + ) -> Result { + let content = match name { + "execute_code" => self.handle_execute_code(arguments).await, + "read_module" => self.handle_read_module(arguments).await, + "search_modules" => self.handle_search_modules(arguments).await, + _ => Err(format!("Unknown tool: {name}")), + }; + + match content { + Ok(content) => Ok(CallToolResult::success(content)), + Err(error) => Ok(CallToolResult::error(vec![Content::text(format!( + "Error: {error}" + ))])), + } + } + + async fn list_prompts( + &self, + _next_cursor: Option, + _cancellation_token: CancellationToken, + ) -> Result { + Err(Error::TransportClosed) + } + + async fn get_prompt( + &self, + _name: &str, + _arguments: Value, + _cancellation_token: CancellationToken, + ) -> Result { + Err(Error::TransportClosed) + } + + async fn subscribe(&self) -> mpsc::Receiver { + mpsc::channel(1).1 + } + + fn get_info(&self) -> Option<&InitializeResult> { + Some(&self.info) + } + + async fn get_moim(&self) -> Option { + let tools = self.get_tool_infos().await; + if tools.is_empty() { + return None; + } + + let mut servers: BTreeSet<&str> = BTreeSet::new(); + for tool in &tools { + servers.insert(&tool.server_name); + } + + let server_list: Vec<_> = servers.into_iter().collect(); + + Some(format!( + indoc::indoc! {r#" + ALWAYS batch multiple tool operations into ONE execute_code call. + - WRONG: Separate execute_code calls for read file, then write file + - RIGHT: One execute_code with a script that reads AND writes + + Modules: {} + + Use read_module("name") to see tool signatures before calling unfamiliar tools. + "#}, + server_list.join(", ") + )) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_execute_code_simple() { + let context = PlatformExtensionContext { + session_id: None, + extension_manager: None, + tool_route_manager: None, + }; + let client = CodeExecutionClient::new(context).unwrap(); + + let mut args = JsonObject::new(); + args.insert("code".to_string(), Value::String("2 + 2".to_string())); + + let result = client + .call_tool("execute_code", Some(args), CancellationToken::new()) + .await + .unwrap(); + + assert!(!result.is_error.unwrap_or(false)); + if let RawContent::Text(text) = &result.content[0].raw { + assert_eq!(text.text, "Result: 4"); + } else { + panic!("Expected text content"); + } + } + + #[tokio::test] + async fn test_read_module_not_found() { + let context = PlatformExtensionContext { + session_id: None, + extension_manager: None, + tool_route_manager: None, + }; + let client = CodeExecutionClient::new(context).unwrap(); + + let mut args = JsonObject::new(); + args.insert("path".to_string(), Value::String("nonexistent".to_string())); + + let result = client.handle_read_module(Some(args)).await; + assert!(result.is_err()); + } + + #[test] + fn test_search_plain_text() { + let tools = vec![ + ToolInfo { + server_name: "developer".to_string(), + tool_name: "shell".to_string(), + full_name: "developer__shell".to_string(), + description: "Execute shell commands".to_string(), + params: vec![("command".to_string(), "string".to_string(), true)], + }, + ToolInfo { + server_name: "developer".to_string(), + tool_name: "text_editor".to_string(), + full_name: "developer__text_editor".to_string(), + description: "Edit text files".to_string(), + params: vec![("path".to_string(), "string".to_string(), true)], + }, + ToolInfo { + server_name: "git".to_string(), + tool_name: "commit".to_string(), + full_name: "git__commit".to_string(), + description: "Commit changes to git".to_string(), + params: vec![("message".to_string(), "string".to_string(), true)], + }, + ]; + + // Search for "shell" - should match tool name + let result = + CodeExecutionClient::handle_search(&tools, &["shell".to_string()], false).unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer/shell")); + assert!(!text.contains("git/commit")); + + // Search for "developer" - should match server name + let result = + CodeExecutionClient::handle_search(&tools, &["developer".to_string()], false).unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer (2 tools)")); + + // Search for "edit" - should match description + let result = + CodeExecutionClient::handle_search(&tools, &["edit".to_string()], false).unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer/text_editor")); + + // Search for multiple terms + let result = CodeExecutionClient::handle_search( + &tools, + &["shell".to_string(), "git".to_string()], + false, + ) + .unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer/shell")); + assert!(text.contains("git/commit")); + + // Search with no matches + let result = + CodeExecutionClient::handle_search(&tools, &["nonexistent".to_string()], false); + assert!(result.is_err()); + } + + #[test] + fn test_search_regex() { + let tools = vec![ + ToolInfo { + server_name: "developer".to_string(), + tool_name: "shell".to_string(), + full_name: "developer__shell".to_string(), + description: "Execute shell commands".to_string(), + params: vec![], + }, + ToolInfo { + server_name: "developer".to_string(), + tool_name: "text_editor".to_string(), + full_name: "developer__text_editor".to_string(), + description: "Edit text files".to_string(), + params: vec![], + }, + ]; + + // Regex search for "sh.*" - should match shell + let result = + CodeExecutionClient::handle_search(&tools, &["sh.*".to_string()], true).unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer/shell")); + + // Regex search for "^text" - should match text_editor + let result = + CodeExecutionClient::handle_search(&tools, &["^text".to_string()], true).unwrap(); + let text = match &result[0].raw { + RawContent::Text(t) => &t.text, + _ => panic!("Expected text"), + }; + assert!(text.contains("developer/text_editor")); + + // Invalid regex should error + let result = CodeExecutionClient::handle_search(&tools, &["[invalid".to_string()], true); + assert!(result.is_err()); + assert!(result.unwrap_err().contains("Invalid regex")); + } +} diff --git a/crates/goose/src/agents/extension.rs b/crates/goose/src/agents/extension.rs index f09ce243a8d8..6e1b42d9cd56 100644 --- a/crates/goose/src/agents/extension.rs +++ b/crates/goose/src/agents/extension.rs @@ -1,4 +1,5 @@ use crate::agents::chatrecall_extension; +use crate::agents::code_execution_extension; use crate::agents::extension_manager_extension; use crate::agents::skills_extension; use crate::agents::todo_extension; @@ -87,6 +88,18 @@ pub static PLATFORM_EXTENSIONS: Lazy }, ); + map.insert( + code_execution_extension::EXTENSION_NAME, + PlatformExtensionDef { + name: code_execution_extension::EXTENSION_NAME, + description: "Execute JavaScript code in a sandboxed environment", + default_enabled: false, + client_factory: |ctx| { + Box::new(code_execution_extension::CodeExecutionClient::new(ctx).unwrap()) + }, + }, + ); + map }, ); diff --git a/crates/goose/src/agents/extension_manager.rs b/crates/goose/src/agents/extension_manager.rs index faa1549dd0ee..abee7d7a2443 100644 --- a/crates/goose/src/agents/extension_manager.rs +++ b/crates/goose/src/agents/extension_manager.rs @@ -598,7 +598,7 @@ impl ExtensionManager { .insert(name, Extension::new(config, client, info, temp_dir)); } - /// Get extensions info + /// Get extensions info for building the system prompt pub async fn get_extensions_info(&self) -> Vec { self.extensions .lock() @@ -637,6 +637,10 @@ impl ExtensionManager { Ok(self.extensions.lock().await.keys().cloned().collect()) } + pub async fn is_extension_enabled(&self, name: &str) -> bool { + self.extensions.lock().await.contains_key(name) + } + pub async fn get_extension_configs(&self) -> Vec { self.extensions .lock() @@ -650,6 +654,14 @@ impl ExtensionManager { pub async fn get_prefixed_tools( &self, extension_name: Option, + ) -> ExtensionResult> { + self.get_prefixed_tools_impl(extension_name, None).await + } + + async fn get_prefixed_tools_impl( + &self, + extension_name: Option, + exclude: Option<&str>, ) -> ExtensionResult> { // Filter clients based on the provided extension_name or include all if None let filtered_clients: Vec<_> = self @@ -658,6 +670,12 @@ impl ExtensionManager { .await .iter() .filter(|(name, _ext)| { + if let Some(excluded) = exclude { + if name.as_str() == excluded { + return false; + } + } + if let Some(ref name_filter) = extension_name { *name == name_filter } else { @@ -723,6 +741,10 @@ impl ExtensionManager { Ok(tools) } + pub async fn get_prefixed_tools_excluding(&self, exclude: &str) -> ExtensionResult> { + self.get_prefixed_tools_impl(None, Some(exclude)).await + } + /// Get the extension prompt including client instructions pub async fn get_planning_prompt(&self, tools_info: Vec) -> String { let mut context: HashMap<&str, Value> = HashMap::new(); @@ -1249,16 +1271,26 @@ impl ExtensionManager { let timestamp = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string(); let mut content = format!("\nIt is currently {}\n", timestamp); - let extensions = self.extensions.lock().await; - for (name, extension) in extensions.iter() { - if let ExtensionConfig::Platform { .. } = &extension.config { - let client = extension.get_client(); - let client_guard = client.lock().await; - if let Some(moim_content) = client_guard.get_moim().await { - tracing::debug!("MOIM content from {}: {} chars", name, moim_content.len()); - content.push('\n'); - content.push_str(&moim_content); - } + let platform_clients: Vec<(String, McpClientBox)> = { + let extensions = self.extensions.lock().await; + extensions + .iter() + .filter_map(|(name, extension)| { + if let ExtensionConfig::Platform { .. } = &extension.config { + Some((name.clone(), extension.get_client())) + } else { + None + } + }) + .collect() + }; + + for (name, client) in platform_clients { + let client_guard = client.lock().await; + if let Some(moim_content) = client_guard.get_moim().await { + tracing::debug!("MOIM content from {}: {} chars", name, moim_content.len()); + content.push('\n'); + content.push_str(&moim_content); } } diff --git a/crates/goose/src/agents/mod.rs b/crates/goose/src/agents/mod.rs index 4a6b2b904c25..62676edee19e 100644 --- a/crates/goose/src/agents/mod.rs +++ b/crates/goose/src/agents/mod.rs @@ -1,5 +1,6 @@ mod agent; pub(crate) mod chatrecall_extension; +pub(crate) mod code_execution_extension; pub mod extension; pub mod extension_malware_check; pub mod extension_manager; diff --git a/crates/goose/src/agents/prompt_manager.rs b/crates/goose/src/agents/prompt_manager.rs index cce4a852538f..5304e5526d47 100644 --- a/crates/goose/src/agents/prompt_manager.rs +++ b/crates/goose/src/agents/prompt_manager.rs @@ -43,6 +43,7 @@ struct SystemPromptContext { enable_subagents: bool, max_extensions: usize, max_tools: usize, + code_execution_mode: bool, } pub struct SystemPromptBuilder<'a, M> { @@ -54,6 +55,7 @@ pub struct SystemPromptBuilder<'a, M> { router_enabled: bool, subagents_enabled: bool, hints: Option, + code_execution_mode: bool, } impl<'a> SystemPromptBuilder<'a, PromptManager> { @@ -88,6 +90,11 @@ impl<'a> SystemPromptBuilder<'a, PromptManager> { self } + pub fn with_code_execution_mode(mut self, enabled: bool) -> Self { + self.code_execution_mode = enabled; + self + } + pub fn with_hints(mut self, working_dir: &Path) -> Self { let config = Config::global(); let hints_filenames = config @@ -159,6 +166,7 @@ impl<'a> SystemPromptBuilder<'a, PromptManager> { enable_subagents: self.subagents_enabled, max_extensions: MAX_EXTENSIONS, max_tools: MAX_TOOLS, + code_execution_mode: self.code_execution_mode, }; let base_prompt = if let Some(override_prompt) = &self.manager.system_prompt_override { @@ -242,6 +250,7 @@ impl PromptManager { router_enabled: false, subagents_enabled: false, hints: None, + code_execution_mode: false, } } diff --git a/crates/goose/src/agents/reply_parts.rs b/crates/goose/src/agents/reply_parts.rs index 2fb26da650d2..5384f776a997 100644 --- a/crates/goose/src/agents/reply_parts.rs +++ b/crates/goose/src/agents/reply_parts.rs @@ -16,6 +16,7 @@ use crate::providers::toolshim::{ modify_system_prompt_for_tool_json, OllamaInterpreter, }; +use crate::agents::code_execution_extension::EXTENSION_NAME as CODE_EXECUTION_EXTENSION; use crate::session::SessionManager; #[cfg(test)] use crate::session::SessionType; @@ -129,6 +130,15 @@ impl Agent { tools.push(frontend_tool.tool.clone()); } + let code_execution_active = self + .extension_manager + .is_extension_enabled(CODE_EXECUTION_EXTENSION) + .await; + if code_execution_active { + let code_exec_prefix = format!("{CODE_EXECUTION_EXTENSION}__"); + tools.retain(|tool| tool.name.starts_with(&code_exec_prefix)); + } + if !router_enabled { // Stable tool ordering is important for multi session prompt caching. tools.sort_by(|a, b| a.name.cmp(&b.name)); @@ -150,6 +160,7 @@ impl Agent { .with_frontend_instructions(self.frontend_instructions.lock().await.clone()) .with_extension_and_tool_counts(extension_count, tool_count) .with_router_enabled(router_enabled) + .with_code_execution_mode(code_execution_active) .with_hints(working_dir) .with_enable_subagents(self.subagents_enabled().await) .build(); diff --git a/crates/goose/src/prompts/system.md b/crates/goose/src/prompts/system.md index 795934e23514..e9743240dadf 100644 --- a/crates/goose/src/prompts/system.md +++ b/crates/goose/src/prompts/system.md @@ -5,6 +5,7 @@ goose uses LLM providers with tool calling capability. You can be used with diff claude-sonnet-4, o1, llama-3.2, deepseek-r1, etc). These models have varying knowledge cut-off dates depending on when they were trained, but typically it's between 5-10 months prior to the current date. +{% if not code_execution_mode %} # Extensions @@ -40,6 +41,7 @@ and platform__list_resources on this extension. {% else %} No extensions are defined. You should let the user know that they should add extensions. {% endif %} +{% endif %} {% if extension_tool_limits is defined %} {% with (extension_count, tool_count) = extension_tool_limits %}