diff --git a/.github/workflows/bundle-desktop.yml b/.github/workflows/bundle-desktop.yml index 5eb13d104d0e..c4856158ed6c 100644 --- a/.github/workflows/bundle-desktop.yml +++ b/.github/workflows/bundle-desktop.yml @@ -154,6 +154,11 @@ jobs: # Check disk space after cleanup df -h + - name: Install protobuf + run: | + brew install protobuf + echo "PROTOC=$(which protoc)" >> $GITHUB_ENV + - name: Setup Rust uses: dtolnay/rust-toolchain@38b70195107dddab2c7bbd522bcf763bac00963b # pin@stable with: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3a7f7c8c09a6..37699a1f9719 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: - name: Install Dependencies run: | sudo apt update -y - sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev + sudo apt install -y libdbus-1-dev gnome-keyring libxcb1-dev protobuf-compiler - name: Setup Rust uses: dtolnay/rust-toolchain@38b70195107dddab2c7bbd522bcf763bac00963b # pin@stable diff --git a/Cargo.lock b/Cargo.lock index afd1f558b45d..49cb9f55d3b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,6 +35,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "const-random", "getrandom 0.2.15", "once_cell", "version_check", @@ -172,6 +173,12 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "arg_enum_proc_macro" version = "0.3.4" @@ -201,6 +208,227 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" +[[package]] +name = "arrow" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05048a8932648b63f21c37d88b552ccc8a65afb6dfe9fc9f30ce79174c2e7a85" +dependencies = [ + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-csv", + "arrow-data", + "arrow-ipc", + "arrow-json", + "arrow-ord", + "arrow-row", + "arrow-schema", + "arrow-select", + "arrow-string", +] + +[[package]] +name = "arrow-arith" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8a57966e43bfe9a3277984a14c24ec617ad874e4c0e1d2a1b083a39cfbf22c" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "num", +] + +[[package]] +name = "arrow-array" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f4a9468c882dc66862cef4e1fd8423d47e67972377d85d80e022786427768c" +dependencies = [ + "ahash", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "chrono", + "chrono-tz", + "half", + "hashbrown 0.14.5", + "num", +] + +[[package]] +name = "arrow-buffer" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c975484888fc95ec4a632cdc98be39c085b1bb518531b0c80c5d462063e5daa1" +dependencies = [ + "bytes", + "half", + "num", +] + +[[package]] +name = "arrow-cast" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da26719e76b81d8bc3faad1d4dbdc1bcc10d14704e63dc17fc9f3e7e1e567c8e" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "atoi", + "base64 0.22.1", + "chrono", + "comfy-table", + "half", + "lexical-core", + "num", + "ryu", +] + +[[package]] +name = "arrow-csv" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c13c36dc5ddf8c128df19bab27898eea64bf9da2b555ec1cd17a8ff57fba9ec2" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "chrono", + "csv", + "csv-core", + "lazy_static", + "lexical-core", + "regex", +] + +[[package]] +name = "arrow-data" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd9d6f18c65ef7a2573ab498c374d8ae364b4a4edf67105357491c031f716ca5" +dependencies = [ + "arrow-buffer", + "arrow-schema", + "half", + "num", +] + +[[package]] +name = "arrow-ipc" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e786e1cdd952205d9a8afc69397b317cfbb6e0095e445c69cda7e8da5c1eeb0f" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "flatbuffers", + "lz4_flex", + "zstd", +] + +[[package]] +name = "arrow-json" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb22284c5a2a01d73cebfd88a33511a3234ab45d66086b2ca2d1228c3498e445" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "chrono", + "half", + "indexmap 2.7.1", + "lexical-core", + "num", + "serde", + "serde_json", +] + +[[package]] +name = "arrow-ord" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42745f86b1ab99ef96d1c0bcf49180848a64fe2c7a7a0d945bc64fa2b21ba9bc" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "half", + "num", +] + +[[package]] +name = "arrow-row" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd09a518c602a55bd406bcc291a967b284cfa7a63edfbf8b897ea4748aad23c" +dependencies = [ + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "half", +] + +[[package]] +name = "arrow-schema" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e972cd1ff4a4ccd22f86d3e53e835c2ed92e0eea6a3e8eadb72b4f1ac802cf8" +dependencies = [ + "bitflags 2.9.0", +] + +[[package]] +name = "arrow-select" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "600bae05d43483d216fb3494f8c32fdbefd8aa4e1de237e790dbb3d9f44690a3" +dependencies = [ + "ahash", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "num", +] + +[[package]] +name = "arrow-string" +version = "52.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0dc1985b67cb45f6606a248ac2b4a288849f196bab8c657ea5589f47cdd55e6" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "memchr", + "num", + "regex", + "regex-syntax 0.8.5", +] + [[package]] name = "askama" version = "0.13.1" @@ -282,6 +510,55 @@ dependencies = [ "zstd-safe", ] +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix 0.37.28", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-priority-channel" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acde96f444d31031f760c5c43dc786b97d3e1cb2ee49dd06898383fe9a999758" +dependencies = [ + "event-listener 4.0.3", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.99", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -315,6 +592,21 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "async_cell" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "834eee9ce518130a3b4d5af09ecc43e9d6b57ee76613f227a1ddd6b77c7a62bc" + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -380,7 +672,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.3.0", "hex", "http 0.2.12", "ring", @@ -418,7 +710,7 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.3.0", "http 0.2.12", "http-body 0.4.6", "once_cell", @@ -445,7 +737,30 @@ dependencies = [ "aws-smithy-types", "aws-types", "bytes", - "fastrand", + "fastrand 2.3.0", + "http 0.2.12", + "once_cell", + "regex-lite", + "tracing", +] + +[[package]] +name = "aws-sdk-dynamodb" +version = "1.67.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "250a727b598ad84f28a41165e6d7a1fcbfb13b5da88723f42d04e9122948f4a5" +dependencies = [ + "aws-credential-types", + "aws-runtime", + "aws-smithy-async", + "aws-smithy-http 0.61.1", + "aws-smithy-json", + "aws-smithy-runtime", + "aws-smithy-runtime-api", + "aws-smithy-types", + "aws-types", + "bytes", + "fastrand 2.3.0", "http 0.2.12", "once_cell", "regex-lite", @@ -635,7 +950,7 @@ dependencies = [ "aws-smithy-runtime-api", "aws-smithy-types", "bytes", - "fastrand", + "fastrand 2.3.0", "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", @@ -964,12 +1279,33 @@ dependencies = [ "serde", ] +[[package]] +name = "bitpacking" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c1d3e2bfd8d06048a179f7b17afc3188effa10385e7b00dc65af6aae732ea92" +dependencies = [ + "crunchy", +] + [[package]] name = "bitstream-io" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blake3" version = "1.6.1" @@ -1064,9 +1400,9 @@ checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" [[package]] name = "bytemuck" -version = "1.22.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" @@ -1120,6 +1456,19 @@ dependencies = [ "serde", ] +[[package]] +name = "cargo_metadata" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", +] + [[package]] name = "cargo_metadata" version = "0.19.2" @@ -1179,6 +1528,12 @@ dependencies = [ "shlex", ] +[[package]] +name = "census" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f4c707c6a209cbe82d10abd08e1ea8995e9ea937d2550646e02798948992be0" + [[package]] name = "cesu8" version = "1.1.0" @@ -1229,9 +1584,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.40" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1239,7 +1594,29 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-link", + "windows-targets 0.52.6", +] + +[[package]] +name = "chrono-tz" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93698b29de5e97ad0ae26447b344c482a7284c737d9ddc5f9e52b74a336671bb" +dependencies = [ + "chrono", + "chrono-tz-build", + "phf", +] + +[[package]] +name = "chrono-tz-build" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c088aee841df9c3041febbb73934cfc39708749bf96dc827e3359cd39ef11b1" +dependencies = [ + "parse-zoneinfo", + "phf", + "phf_codegen", ] [[package]] @@ -1412,6 +1789,25 @@ dependencies = [ "memchr", ] +[[package]] +name = "comfy-table" +version = "7.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a" +dependencies = [ + "unicode-segmentation", + "unicode-width 0.2.0", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "config" version = "0.14.1" @@ -1658,6 +2054,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1680,6 +2085,27 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.2.9" @@ -1726,14 +2152,364 @@ dependencies = [ ] [[package]] -name = "data-encoding" -version = "2.8.0" +name = "dashmap" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" - -[[package]] -name = "dbus" -version = "0.9.7" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" + +[[package]] +name = "datafusion" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4fd4a99fc70d40ef7e52b243b4a399c3f8d353a40d5ecb200deee05e49c61bb" +dependencies = [ + "ahash", + "arrow", + "arrow-array", + "arrow-ipc", + "arrow-schema", + "async-trait", + "bytes", + "chrono", + "dashmap 6.1.0", + "datafusion-catalog", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-execution", + "datafusion-expr", + "datafusion-functions", + "datafusion-functions-aggregate", + "datafusion-functions-nested", + "datafusion-optimizer", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "datafusion-physical-optimizer", + "datafusion-physical-plan", + "datafusion-sql", + "futures", + "glob", + "half", + "hashbrown 0.14.5", + "indexmap 2.7.1", + "itertools 0.12.1", + "log", + "num_cpus", + "object_store", + "parking_lot", + "paste", + "pin-project-lite", + "rand 0.8.5", + "sqlparser", + "tempfile", + "tokio", + "url", + "uuid", +] + +[[package]] +name = "datafusion-catalog" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b3cfbd84c6003594ae1972314e3df303a27ce8ce755fcea3240c90f4c0529" +dependencies = [ + "arrow-schema", + "async-trait", + "datafusion-common", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-plan", +] + +[[package]] +name = "datafusion-common" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fdbc877e3e40dcf88cc8f283d9f5c8851f0a3aa07fee657b1b75ac1ad49b9c" +dependencies = [ + "ahash", + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-schema", + "chrono", + "half", + "hashbrown 0.14.5", + "instant", + "libc", + "num_cpus", + "object_store", + "sqlparser", +] + +[[package]] +name = "datafusion-common-runtime" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7496d1f664179f6ce3a5cbef6566056ccaf3ea4aa72cc455f80e62c1dd86b1" +dependencies = [ + "tokio", +] + +[[package]] +name = "datafusion-execution" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799e70968c815b611116951e3dd876aef04bf217da31b72eec01ee6a959336a1" +dependencies = [ + "arrow", + "chrono", + "dashmap 6.1.0", + "datafusion-common", + "datafusion-expr", + "futures", + "hashbrown 0.14.5", + "log", + "object_store", + "parking_lot", + "rand 0.8.5", + "tempfile", + "url", +] + +[[package]] +name = "datafusion-expr" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c1841c409d9518c17971d15c9bae62e629eb937e6fb6c68cd32e9186f8b30d2" +dependencies = [ + "ahash", + "arrow", + "arrow-array", + "arrow-buffer", + "chrono", + "datafusion-common", + "paste", + "serde_json", + "sqlparser", + "strum", + "strum_macros", +] + +[[package]] +name = "datafusion-functions" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8e481cf34d2a444bd8fa09b65945f0ce83dc92df8665b761505b3d9f351bebb" +dependencies = [ + "arrow", + "arrow-buffer", + "base64 0.22.1", + "chrono", + "datafusion-common", + "datafusion-execution", + "datafusion-expr", + "hashbrown 0.14.5", + "hex", + "itertools 0.12.1", + "log", + "rand 0.8.5", + "regex", + "unicode-segmentation", + "uuid", +] + +[[package]] +name = "datafusion-functions-aggregate" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b4ece19f73c02727e5e8654d79cd5652de371352c1df3c4ac3e419ecd6943fb" +dependencies = [ + "ahash", + "arrow", + "arrow-schema", + "datafusion-common", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-expr-common", + "log", + "paste", + "sqlparser", +] + +[[package]] +name = "datafusion-functions-nested" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1474552cc824e8c9c88177d454db5781d4b66757d4aca75719306b8343a5e8d" +dependencies = [ + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-ord", + "arrow-schema", + "datafusion-common", + "datafusion-execution", + "datafusion-expr", + "datafusion-functions", + "datafusion-functions-aggregate", + "itertools 0.12.1", + "log", + "paste", + "rand 0.8.5", +] + +[[package]] +name = "datafusion-optimizer" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791ff56f55608bc542d1ea7a68a64bdc86a9413f5a381d06a39fd49c2a3ab906" +dependencies = [ + "arrow", + "async-trait", + "chrono", + "datafusion-common", + "datafusion-expr", + "datafusion-physical-expr", + "hashbrown 0.14.5", + "indexmap 2.7.1", + "itertools 0.12.1", + "log", + "paste", + "regex-syntax 0.8.5", +] + +[[package]] +name = "datafusion-physical-expr" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a223962b3041304a3e20ed07a21d5de3d88d7e4e71ca192135db6d24e3365a4" +dependencies = [ + "ahash", + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-ord", + "arrow-schema", + "arrow-string", + "base64 0.22.1", + "chrono", + "datafusion-common", + "datafusion-execution", + "datafusion-expr", + "datafusion-physical-expr-common", + "half", + "hashbrown 0.14.5", + "hex", + "indexmap 2.7.1", + "itertools 0.12.1", + "log", + "paste", + "petgraph", + "regex", +] + +[[package]] +name = "datafusion-physical-expr-common" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db5e7d8532a1601cd916881db87a70b0a599900d23f3db2897d389032da53bc6" +dependencies = [ + "ahash", + "arrow", + "datafusion-common", + "datafusion-expr", + "hashbrown 0.14.5", + "rand 0.8.5", +] + +[[package]] +name = "datafusion-physical-optimizer" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb9c78f308e050f5004671039786a925c3fee83b90004e9fcfd328d7febdcc0" +dependencies = [ + "datafusion-common", + "datafusion-execution", + "datafusion-physical-expr", + "datafusion-physical-plan", +] + +[[package]] +name = "datafusion-physical-plan" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d1116949432eb2d30f6362707e2846d942e491052a206f2ddcb42d08aea1ffe" +dependencies = [ + "ahash", + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-ord", + "arrow-schema", + "async-trait", + "chrono", + "datafusion-common", + "datafusion-common-runtime", + "datafusion-execution", + "datafusion-expr", + "datafusion-functions-aggregate", + "datafusion-physical-expr", + "datafusion-physical-expr-common", + "futures", + "half", + "hashbrown 0.14.5", + "indexmap 2.7.1", + "itertools 0.12.1", + "log", + "once_cell", + "parking_lot", + "pin-project-lite", + "rand 0.8.5", + "tokio", +] + +[[package]] +name = "datafusion-sql" +version = "41.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45d0180711165fe94015d7c4123eb3e1cf5fb60b1506453200b8d1ce666bef0" +dependencies = [ + "arrow", + "arrow-array", + "arrow-schema", + "datafusion-common", + "datafusion-expr", + "log", + "regex", + "sqlparser", + "strum", +] + +[[package]] +name = "dbus" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" dependencies = [ @@ -1774,6 +2550,26 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "092966b41edc516079bdf31ec78a2e0588d1d0c08f78b91d8307215928642b2b" +[[package]] +name = "deepsize" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdb987ec36f6bf7bfbea3f928b75590b736fc42af8e54d97592481351b2b96c" +dependencies = [ + "deepsize_derive", +] + +[[package]] +name = "deepsize_derive" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990101d41f3bc8c1a45641024377ee284ecc338e5ecf3ea0f0e236d897c72796" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "deranged" version = "0.3.11" @@ -1947,6 +2743,12 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dyn-clone" version = "1.0.19" @@ -1996,6 +2798,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "error-chain" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" +dependencies = [ + "version_check", +] + [[package]] name = "error-code" version = "3.3.1" @@ -2022,6 +2833,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + [[package]] name = "eventsource-client" version = "0.12.2" @@ -2064,6 +2892,21 @@ dependencies = [ "regex-syntax 0.8.5", ] +[[package]] +name = "fastdivide" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afc2bd4d5a73106dd53d10d73d3401c2f32730ba2c0b93ddb888a8983680471" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -2102,6 +2945,22 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flatbuffers" +version = "24.12.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f1baf0dbf96932ec9a3038d57900329c015b0bfb7b63d904f3bc27e2b02a096" +dependencies = [ + "bitflags 1.3.2", + "rustc_version", +] + [[package]] name = "flate2" version = "1.1.0" @@ -2119,7 +2978,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "foreign-types" +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -2194,6 +3059,31 @@ dependencies = [ "winapi", ] +[[package]] +name = "fs4" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7e180ac76c23b45e767bd7ae9579bc0bb458618c4bc71835926e098e61d15f8" +dependencies = [ + "rustix 0.38.44", + "windows-sys 0.52.0", +] + +[[package]] +name = "fsst" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac423dce38c8aafc3d348d9f9c207ac030385ba2edda08bcff43c74a29ce3eac" +dependencies = [ + "rand 0.8.5", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures" version = "0.3.31" @@ -2242,6 +3132,21 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -2485,6 +3390,7 @@ name = "goose" version = "1.0.24" dependencies = [ "anyhow", + "arrow", "async-stream", "async-trait", "aws-config", @@ -2505,6 +3411,7 @@ dependencies = [ "indoc 2.0.6", "jsonwebtoken", "keyring", + "lancedb", "lazy_static", "mcp-client", "mcp-core", @@ -2795,6 +3702,7 @@ checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", + "num-traits", ] [[package]] @@ -2818,6 +3726,11 @@ name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hashlink" @@ -2900,6 +3813,12 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "htmlescape" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" + [[package]] name = "http" version = "0.2.12" @@ -2968,6 +3887,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +[[package]] +name = "humantime" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" + [[package]] name = "hyper" version = "0.14.32" @@ -2985,7 +3910,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.5.8", "tokio", "tower-service", "tracing", @@ -3073,12 +3998,21 @@ dependencies = [ "http-body 1.0.1", "hyper 1.6.0", "pin-project-lite", - "socket2", + "socket2 0.5.8", "tokio", "tower-service", "tracing", ] +[[package]] +name = "hyperloglogplus" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "621debdf94dcac33e50475fdd76d34d5ea9c0362a834b9db08c3024696c1fbe3" +dependencies = [ + "serde", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -3396,6 +4330,18 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "interpolate_name" version = "0.2.4" @@ -3407,6 +4353,17 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -3569,29 +4526,533 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3879339076ac4da142cc852d91693462927cbc99773b5ea422e4834e68c4ff2" dependencies = [ - "bindgen", - "nix 0.27.1", - "tracing", - "windows 0.52.0", + "bindgen", + "nix 0.27.1", + "tracing", + "windows 0.52.0", +] + +[[package]] +name = "lance" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cd1ece8f8ca17955c805e846b43acc61922bf9729977807037a3b1e26584e4" +dependencies = [ + "arrow", + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-ord", + "arrow-row", + "arrow-schema", + "arrow-select", + "async-recursion", + "async-trait", + "async_cell", + "aws-credential-types", + "aws-sdk-dynamodb", + "byteorder", + "bytes", + "chrono", + "dashmap 5.5.3", + "datafusion", + "datafusion-functions", + "datafusion-physical-expr", + "deepsize", + "futures", + "half", + "itertools 0.12.1", + "lance-arrow", + "lance-core", + "lance-datafusion", + "lance-encoding", + "lance-file", + "lance-index", + "lance-io", + "lance-linalg", + "lance-table", + "lazy_static", + "log", + "moka", + "object_store", + "permutation", + "pin-project", + "prost", + "prost-build", + "rand 0.8.5", + "roaring", + "serde", + "serde_json", + "snafu", + "tantivy", + "tempfile", + "tokio", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "lance-arrow" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385c62668af77d75da2242c6e86b9c0868d92f13961643ba3d8dc7eb05deb5da" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "arrow-select", + "getrandom 0.2.15", + "half", + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "lance-core" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ca182e47d2926aa59526e2573dd1e634b72111b275410cb42dca30aef9f315" +dependencies = [ + "arrow-array", + "arrow-buffer", + "arrow-schema", + "async-trait", + "byteorder", + "bytes", + "chrono", + "datafusion-common", + "datafusion-sql", + "deepsize", + "futures", + "lance-arrow", + "lazy_static", + "libc", + "log", + "mock_instant", + "moka", + "num_cpus", + "object_store", + "pin-project", + "prost", + "rand 0.8.5", + "roaring", + "serde_json", + "snafu", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "lance-datafusion" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d90f3f250a6761d5f7e2a2d6838402defdad18367a122b260a2fadb1dea30464" +dependencies = [ + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-ord", + "arrow-schema", + "arrow-select", + "async-trait", + "datafusion", + "datafusion-common", + "datafusion-functions", + "datafusion-physical-expr", + "futures", + "lance-arrow", + "lance-core", + "lazy_static", + "log", + "prost", + "snafu", + "tokio", +] + +[[package]] +name = "lance-encoding" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4d187963282728ba0c756ae7dfdeef3e47a4ac6db56385860c665f07b6e59ae" +dependencies = [ + "arrayref", + "arrow", + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "arrow-select", + "bytemuck", + "byteorder", + "bytes", + "fsst", + "futures", + "hex", + "hyperloglogplus", + "itertools 0.12.1", + "lance-arrow", + "lance-core", + "lazy_static", + "log", + "num-traits", + "paste", + "prost", + "prost-build", + "prost-types", + "rand 0.8.5", + "seq-macro", + "snafu", + "tokio", + "tracing", + "zstd", +] + +[[package]] +name = "lance-file" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bdc8b00b0664e3944648f43b61785e5317ecc25b0015a80e2deba6f28a76e4a" +dependencies = [ + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-data", + "arrow-schema", + "arrow-select", + "async-recursion", + "async-trait", + "byteorder", + "bytes", + "datafusion-common", + "deepsize", + "futures", + "lance-arrow", + "lance-core", + "lance-encoding", + "lance-io", + "log", + "num-traits", + "object_store", + "prost", + "prost-build", + "prost-types", + "roaring", + "snafu", + "tempfile", + "tokio", + "tracing", +] + +[[package]] +name = "lance-index" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7051aa7a28c3dc0708cddd6f4448fa86968d183bc2be14a5acd7495fb8d8fd9" +dependencies = [ + "arrow", + "arrow-array", + "arrow-ord", + "arrow-schema", + "arrow-select", + "async-recursion", + "async-trait", + "bitvec", + "bytes", + "crossbeam-queue", + "datafusion", + "datafusion-common", + "datafusion-expr", + "datafusion-physical-expr", + "datafusion-sql", + "deepsize", + "futures", + "half", + "itertools 0.12.1", + "lance-arrow", + "lance-core", + "lance-datafusion", + "lance-encoding", + "lance-file", + "lance-io", + "lance-linalg", + "lance-table", + "lazy_static", + "log", + "moka", + "num-traits", + "object_store", + "prost", + "prost-build", + "rand 0.8.5", + "rayon", + "roaring", + "serde", + "serde_json", + "snafu", + "tantivy", + "tempfile", + "tokio", + "tracing", + "uuid", +] + +[[package]] +name = "lance-io" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d612eebbb3d9feca9c2b860f176f920142c859b3e175248a20b0250b898b149" +dependencies = [ + "arrow", + "arrow-arith", + "arrow-array", + "arrow-buffer", + "arrow-cast", + "arrow-data", + "arrow-schema", + "arrow-select", + "async-priority-channel", + "async-recursion", + "async-trait", + "aws-config", + "aws-credential-types", + "byteorder", + "bytes", + "chrono", + "deepsize", + "futures", + "lance-arrow", + "lance-core", + "lazy_static", + "log", + "object_store", + "path_abs", + "pin-project", + "prost", + "prost-build", + "rand 0.8.5", + "shellexpand", + "snafu", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "lance-linalg" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d642bfbece852f40e0aa01daa445940f80ede9c2914bd25cd720dac266ce41a9" +dependencies = [ + "arrow-array", + "arrow-ord", + "arrow-schema", + "bitvec", + "cc", + "deepsize", + "futures", + "half", + "lance-arrow", + "lance-core", + "lazy_static", + "log", + "num-traits", + "rand 0.8.5", + "rayon", + "tokio", + "tracing", +] + +[[package]] +name = "lance-table" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd8c8aaf1b74110fbd1a24cb30f54280cb7a0dc2cdd87513a7679385ca97f952" +dependencies = [ + "arrow", + "arrow-array", + "arrow-buffer", + "arrow-ipc", + "arrow-schema", + "async-trait", + "aws-credential-types", + "aws-sdk-dynamodb", + "byteorder", + "bytes", + "chrono", + "deepsize", + "futures", + "lance-arrow", + "lance-core", + "lance-file", + "lance-io", + "lazy_static", + "log", + "object_store", + "prost", + "prost-build", + "prost-types", + "rand 0.8.5", + "rangemap", + "roaring", + "serde", + "serde_json", + "snafu", + "tokio", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "lance-testing" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc37f345c06661a29cf9d89ad4c52f84ba2f037ff94403c1f4b486edd7713103" +dependencies = [ + "arrow-array", + "arrow-schema", + "lance-arrow", + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "lancedb" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c041835505f86cb5cc5cc6238a6bb981f7addda58afb40eabd76c2f91e47b9b0" +dependencies = [ + "arrow", + "arrow-array", + "arrow-cast", + "arrow-data", + "arrow-ipc", + "arrow-ord", + "arrow-schema", + "async-trait", + "bytes", + "chrono", + "datafusion-common", + "datafusion-physical-plan", + "futures", + "half", + "lance", + "lance-datafusion", + "lance-encoding", + "lance-index", + "lance-linalg", + "lance-table", + "lance-testing", + "lazy_static", + "log", + "moka", + "num-traits", + "object_store", + "pin-project", + "regex", + "serde", + "serde_json", + "serde_with", + "snafu", + "tokio", + "url", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + +[[package]] +name = "levenshtein_automata" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2cdeb66e45e9f36bfad5bbdb4d2384e70936afbee843c6f6543f0c551ebb25" + +[[package]] +name = "lexical-core" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" +dependencies = [ + "lexical-parse-float", + "lexical-parse-integer", + "lexical-util", + "lexical-write-float", + "lexical-write-integer", +] + +[[package]] +name = "lexical-parse-float" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" +dependencies = [ + "lexical-parse-integer", + "lexical-util", + "static_assertions", +] + +[[package]] +name = "lexical-parse-integer" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" +dependencies = [ + "lexical-util", + "static_assertions", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "lexical-util" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" +dependencies = [ + "static_assertions", +] [[package]] -name = "lazycell" -version = "1.3.0" +name = "lexical-write-float" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" +dependencies = [ + "lexical-util", + "lexical-write-integer", + "static_assertions", +] [[package]] -name = "lebe" -version = "0.5.2" +name = "lexical-write-integer" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" +checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" +dependencies = [ + "lexical-util", + "static_assertions", +] [[package]] name = "libc" @@ -3641,6 +5102,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + [[package]] name = "libredox" version = "0.1.3" @@ -3670,6 +5137,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -3749,6 +5222,33 @@ dependencies = [ "weezl", ] +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "lz4_flex" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "mach2" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" +dependencies = [ + "libc", +] + [[package]] name = "macro_rules_attribute" version = "0.2.0" @@ -3887,12 +5387,31 @@ dependencies = [ "digest", ] +[[package]] +name = "measure_time" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbefd235b0aadd181626f281e1d684e116972988c14c264e42069d5e8a5775cc" +dependencies = [ + "instant", + "log", +] + [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +[[package]] +name = "memmap2" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" +dependencies = [ + "libc", +] + [[package]] name = "mime" version = "0.3.17" @@ -3935,6 +5454,15 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "mock_instant" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9366861eb2a2c436c20b12c8dbec5f798cea6b47ad99216be0282942e2c81ea0" +dependencies = [ + "once_cell", +] + [[package]] name = "mockall" version = "0.13.1" @@ -3961,6 +5489,31 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "moka" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa6e72583bf6830c956235bff0d5afec8cf2952f579ebad18ae7821a917d950f" +dependencies = [ + "async-io", + "async-lock", + "crossbeam-channel", + "crossbeam-epoch", + "crossbeam-utils", + "futures-util", + "once_cell", + "parking_lot", + "quanta", + "rustc_version", + "scheduled-thread-pool", + "skeptic", + "smallvec", + "tagptr", + "thiserror 1.0.69", + "triomphe", + "uuid", +] + [[package]] name = "monostate" version = "0.1.14" @@ -3982,6 +5535,18 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "multimap" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084" + +[[package]] +name = "murmurhash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2195bf6aa996a481483b29d62a7663eed3fe39600c460e323f8ff41e90bdd89b" + [[package]] name = "nanoid" version = "0.4.0" @@ -4190,6 +5755,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -4255,12 +5821,49 @@ dependencies = [ "memchr", ] +[[package]] +name = "object_store" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6da452820c715ce78221e8202ccc599b4a52f3e1eb3eedb487b680c81a8e3f3" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bytes", + "chrono", + "futures", + "humantime", + "hyper 1.6.0", + "itertools 0.13.0", + "md-5", + "parking_lot", + "percent-encoding", + "quick-xml 0.36.2", + "rand 0.8.5", + "reqwest 0.12.12", + "ring", + "rustls-pemfile 2.2.0", + "serde", + "serde_json", + "snafu", + "tokio", + "tracing", + "url", + "walkdir", +] + [[package]] name = "once_cell" version = "1.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" +[[package]] +name = "oneshot" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce411919553d3f9fa53a0880544cda985a112117a0444d5ff1e870a893d6ea" + [[package]] name = "onig" version = "6.5.1" @@ -4377,6 +5980,21 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "ownedbytes" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a059efb063b8f425b948e042e6b9bd85edfe60e913630ed727b23e2dfcc558" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -4400,6 +6018,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "parse-zoneinfo" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" +dependencies = [ + "regex", +] + [[package]] name = "paste" version = "1.0.15" @@ -4412,7 +6039,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05ef02f6342ac01d8a93b65f96db53fe68a92a15f41144f97fb00a9e669633c3" dependencies = [ + "serde", + "serde_derive", "std_prelude", + "stfu8", ] [[package]] @@ -4437,6 +6067,12 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "permutation" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df202b0b0f5b8e389955afd5f27b007b00fb948162953f1db9c70d2c7e3157d7" + [[package]] name = "pest" version = "2.7.15" @@ -4482,6 +6118,54 @@ dependencies = [ "sha2", ] +[[package]] +name = "petgraph" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +dependencies = [ + "fixedbitset", + "indexmap 2.7.1", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared", + "rand 0.8.5", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.1", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -4580,6 +6264,22 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "portable-atomic" version = "1.11.0" @@ -4689,6 +6389,59 @@ dependencies = [ "syn 2.0.99", ] +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-build" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" +dependencies = [ + "bytes", + "heck 0.5.0", + "itertools 0.12.1", + "log", + "multimap", + "once_cell", + "petgraph", + "prettyplease", + "prost", + "prost-types", + "regex", + "syn 2.0.99", + "tempfile", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.12.1", + "proc-macro2", + "quote", + "syn 2.0.99", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost", +] + [[package]] name = "psl-types" version = "2.0.11" @@ -4705,6 +6458,17 @@ dependencies = [ "psl-types", ] +[[package]] +name = "pulldown-cmark" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b" +dependencies = [ + "bitflags 2.9.0", + "memchr", + "unicase", +] + [[package]] name = "qoi" version = "0.4.1" @@ -4714,6 +6478,22 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "quanta" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +dependencies = [ + "crossbeam-utils", + "libc", + "mach2", + "once_cell", + "raw-cpuid", + "wasi 0.11.0+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "2.0.1" @@ -4738,6 +6518,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.36.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quick-xml" version = "0.37.2" @@ -4760,7 +6550,7 @@ dependencies = [ "quinn-udp", "rustc-hash 2.1.1", "rustls 0.23.23", - "socket2", + "socket2 0.5.8", "thiserror 2.0.12", "tokio", "tracing", @@ -4795,7 +6585,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2", + "socket2 0.5.8", "tracing", "windows-sys 0.59.0", ] @@ -4809,6 +6599,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "radix_trie" version = "0.2.1" @@ -4878,6 +6674,16 @@ dependencies = [ "getrandom 0.3.1", ] +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "rangemap" version = "1.5.1" @@ -4934,6 +6740,15 @@ dependencies = [ "rgb", ] +[[package]] +name = "raw-cpuid" +version = "10.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "raw-window-handle" version = "0.5.2" @@ -5170,6 +6985,16 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "roaring" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41589aba99537475bf697f2118357cad1c31590c5a1b9f6d9fc4ad6d07503661" +dependencies = [ + "bytemuck", + "byteorder", +] + [[package]] name = "ron" version = "0.8.1" @@ -5192,6 +7017,16 @@ dependencies = [ "ordered-multimap", ] +[[package]] +name = "rust-stemmers" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e46a2036019fdb888131db7a4c847a1063a7493f971ed94ea82c67eada63ca54" +dependencies = [ + "serde", + "serde_derive", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -5219,6 +7054,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.37.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "519165d378b97752ca44bbe15047d5d3409e875f39327546b42ac81d7e18c1b6" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.44" @@ -5404,6 +7253,15 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + [[package]] name = "schemars" version = "0.8.22" @@ -5521,6 +7379,12 @@ dependencies = [ "serde", ] +[[package]] +name = "seq-macro" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" + [[package]] name = "serde" version = "1.0.218" @@ -5763,6 +7627,36 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "skeptic" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" +dependencies = [ + "bytecount", + "cargo_metadata 0.14.2", + "error-chain", + "glob", + "pulldown-cmark", + "tempfile", + "walkdir", +] + +[[package]] +name = "sketches-ddsketch" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85636c14b73d81f541e525f585c0a2109e6744e1565b5c1668e31c70c10ed65c" +dependencies = [ + "serde", +] + [[package]] name = "slab" version = "0.4.9" @@ -5787,6 +7681,38 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" +[[package]] +name = "snafu" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4de37ad025c587a29e8f3f5605c00f70b98715ef90b9061a815b9e59e9042d6" +dependencies = [ + "doc-comment", + "snafu-derive", +] + +[[package]] +name = "snafu-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990079665f075b699031e9c08fd3ab99be5029b96f3b78dc0709e8f77e4efebf" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "socket2" version = "0.5.8" @@ -5809,6 +7735,27 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "sqlparser" +version = "0.49.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a404d0e14905361b918cb8afdb73605e25c1d5029312bd9785142dcb3aa49e" +dependencies = [ + "log", + "sqlparser_derive", +] + +[[package]] +name = "sqlparser_derive" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b2e185515564f15375f593fb966b5718bc624ba77fe49fa4616ad619690554" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.99", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -5827,6 +7774,12 @@ version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8207e78455ffdf55661170876f88daf85356e4edd54e0a3dbc79586ca1e50cbe" +[[package]] +name = "stfu8" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51f1e89f093f99e7432c491c382b88a6860a5adbe6bf02574bf0a08efff1978" + [[package]] name = "strsim" version = "0.10.0" @@ -5839,6 +7792,28 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.99", +] + [[package]] name = "subtle" version = "2.6.1" @@ -5977,6 +7952,159 @@ dependencies = [ "version-compare", ] +[[package]] +name = "tagptr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417" + +[[package]] +name = "tantivy" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8d0582f186c0a6d55655d24543f15e43607299425c5ad8352c242b914b31856" +dependencies = [ + "aho-corasick", + "arc-swap", + "base64 0.22.1", + "bitpacking", + "byteorder", + "census", + "crc32fast", + "crossbeam-channel", + "downcast-rs", + "fastdivide", + "fnv", + "fs4", + "htmlescape", + "itertools 0.12.1", + "levenshtein_automata", + "log", + "lru", + "lz4_flex", + "measure_time", + "memmap2", + "num_cpus", + "once_cell", + "oneshot", + "rayon", + "regex", + "rust-stemmers", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "sketches-ddsketch", + "smallvec", + "tantivy-bitpacker", + "tantivy-columnar", + "tantivy-common", + "tantivy-fst", + "tantivy-query-grammar", + "tantivy-stacker", + "tantivy-tokenizer-api", + "tempfile", + "thiserror 1.0.69", + "time", + "uuid", + "winapi", +] + +[[package]] +name = "tantivy-bitpacker" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "284899c2325d6832203ac6ff5891b297fc5239c3dc754c5bc1977855b23c10df" +dependencies = [ + "bitpacking", +] + +[[package]] +name = "tantivy-columnar" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12722224ffbe346c7fec3275c699e508fd0d4710e629e933d5736ec524a1f44e" +dependencies = [ + "downcast-rs", + "fastdivide", + "itertools 0.12.1", + "serde", + "tantivy-bitpacker", + "tantivy-common", + "tantivy-sstable", + "tantivy-stacker", +] + +[[package]] +name = "tantivy-common" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8019e3cabcfd20a1380b491e13ff42f57bb38bf97c3d5fa5c07e50816e0621f4" +dependencies = [ + "async-trait", + "byteorder", + "ownedbytes", + "serde", + "time", +] + +[[package]] +name = "tantivy-fst" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d60769b80ad7953d8a7b2c70cdfe722bbcdcac6bccc8ac934c40c034d866fc18" +dependencies = [ + "byteorder", + "regex-syntax 0.8.5", + "utf8-ranges", +] + +[[package]] +name = "tantivy-query-grammar" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "847434d4af57b32e309f4ab1b4f1707a6c566656264caa427ff4285c4d9d0b82" +dependencies = [ + "nom", +] + +[[package]] +name = "tantivy-sstable" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c69578242e8e9fc989119f522ba5b49a38ac20f576fc778035b96cc94f41f98e" +dependencies = [ + "tantivy-bitpacker", + "tantivy-common", + "tantivy-fst", + "zstd", +] + +[[package]] +name = "tantivy-stacker" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56d6ff5591fc332739b3ce7035b57995a3ce29a93ffd6012660e0949c956ea8" +dependencies = [ + "murmurhash32", + "rand_distr", + "tantivy-common", +] + +[[package]] +name = "tantivy-tokenizer-api" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0dcade25819a89cfe6f17d932c9cedff11989936bf6dd4f336d50392053b04" +dependencies = [ + "serde", +] + +[[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" @@ -6011,7 +8139,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22e5a0acb1f3f55f65cc4a866c361b2fb2a0ff6366785ae6fbb5f85df07ba230" dependencies = [ "cfg-if", - "fastrand", + "fastrand 2.3.0", "getrandom 0.3.1", "once_cell", "rustix 0.38.44", @@ -6282,7 +8410,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.8", "tokio-macros", "windows-sys 0.52.0", ] @@ -6570,6 +8698,12 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "triomphe" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" + [[package]] name = "try-lock" version = "0.2.5" @@ -6593,6 +8727,16 @@ dependencies = [ "utf-8", ] +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + [[package]] name = "typenum" version = "1.18.0" @@ -6634,6 +8778,12 @@ dependencies = [ "zip 2.5.0", ] +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.18" @@ -6687,7 +8837,7 @@ checksum = "4dcd1d240101ba3b9d7532ae86d9cb64d9a7ff63e13a2b7b9e94a32a601d8233" dependencies = [ "anyhow", "camino", - "cargo_metadata", + "cargo_metadata 0.19.2", "clap 4.5.31", "uniffi_bindgen", "uniffi_core", @@ -6704,7 +8854,7 @@ dependencies = [ "anyhow", "askama", "camino", - "cargo_metadata", + "cargo_metadata 0.19.2", "fs-err", "glob", "goblin", @@ -6771,7 +8921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3acc9204632f6a555b2cba7c8852c5523bc1aa5f3eff605c64af5054ea28b72e" dependencies = [ "anyhow", - "siphasher", + "siphasher 0.3.11", "uniffi_internal_macros", "uniffi_pipeline", ] @@ -6843,6 +8993,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" +[[package]] +name = "utf8-ranges" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -6887,6 +9043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" dependencies = [ "getrandom 0.3.1", + "serde", ] [[package]] @@ -6930,6 +9087,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + [[package]] name = "walkdir" version = "2.5.0" @@ -7269,12 +9432,6 @@ dependencies = [ "syn 2.0.99", ] -[[package]] -name = "windows-link" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3" - [[package]] name = "windows-registry" version = "0.2.0" @@ -7592,6 +9749,15 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "xattr" version = "1.5.0" diff --git a/crates/goose-cli/src/commands/configure.rs b/crates/goose-cli/src/commands/configure.rs index bd3ca18117ef..7e49c50c70f4 100644 --- a/crates/goose-cli/src/commands/configure.rs +++ b/crates/goose-cli/src/commands/configure.rs @@ -824,6 +824,11 @@ pub fn remove_extension_dialog() -> Result<(), Box> { pub async fn configure_settings_dialog() -> Result<(), Box> { let setting_type = cliclack::select("What setting would you like to configure?") .item("goose_mode", "Goose Mode", "Configure Goose mode") + .item( + "goose_router_strategy", + "Router Tool Selection Strategy", + "Configure the strategy for selecting tools to use", + ) .item( "tool_permission", "Tool Permission", @@ -850,6 +855,9 @@ pub async fn configure_settings_dialog() -> Result<(), Box> { "goose_mode" => { configure_goose_mode_dialog()?; } + "goose_router_strategy" => { + configure_goose_router_strategy_dialog()?; + } "tool_permission" => { configure_tool_permissions_dialog().await.and(Ok(()))?; } @@ -921,6 +929,49 @@ pub fn configure_goose_mode_dialog() -> Result<(), Box> { Ok(()) } +pub fn configure_goose_router_strategy_dialog() -> Result<(), Box> { + let config = Config::global(); + + // Check if GOOSE_ROUTER_STRATEGY is set as an environment variable + if std::env::var("GOOSE_ROUTER_TOOL_SELECTION_STRATEGY").is_ok() { + let _ = cliclack::log::info("Notice: GOOSE_ROUTER_TOOL_SELECTION_STRATEGY environment variable is set. Configuration will override this."); + } + + let strategy = cliclack::select("Which router strategy would you like to use?") + .item( + "vector", + "Vector Strategy", + "Use vector-based similarity to select tools", + ) + .item( + "default", + "Default Strategy", + "Use the default tool selection strategy", + ) + .interact()?; + + match strategy { + "vector" => { + config.set_param( + "GOOSE_ROUTER_TOOL_SELECTION_STRATEGY", + Value::String("vector".to_string()), + )?; + cliclack::outro( + "Set to Vector Strategy - using vector-based similarity for tool selection", + )?; + } + "default" => { + config.set_param( + "GOOSE_ROUTER_TOOL_SELECTION_STRATEGY", + Value::String("default".to_string()), + )?; + cliclack::outro("Set to Default Strategy - using default tool selection")?; + } + _ => unreachable!(), + }; + Ok(()) +} + pub fn configure_tool_output_dialog() -> Result<(), Box> { let config = Config::global(); // Check if GOOSE_CLI_MIN_PRIORITY is set as an environment variable diff --git a/crates/goose-cli/src/session/builder.rs b/crates/goose-cli/src/session/builder.rs index 747862ded95e..f7cfeba70590 100644 --- a/crates/goose-cli/src/session/builder.rs +++ b/crates/goose-cli/src/session/builder.rs @@ -55,7 +55,13 @@ pub async fn build_session(session_config: SessionBuilderConfig) -> Session { // Create the agent let agent: Agent = Agent::new(); let new_provider = create(&provider_name, model_config).unwrap(); - let _ = agent.update_provider(new_provider).await; + agent + .update_provider(new_provider) + .await + .unwrap_or_else(|e| { + output::render_error(&format!("Failed to initialize agent: {}", e)); + process::exit(1); + }); // Configure tool monitoring if max_tool_repetitions is set if let Some(max_repetitions) = session_config.max_tool_repetitions { diff --git a/crates/goose-server/src/routes/extension.rs b/crates/goose-server/src/routes/extension.rs index b45466b6e86b..3b8f8dbcb387 100644 --- a/crates/goose-server/src/routes/extension.rs +++ b/crates/goose-server/src/routes/extension.rs @@ -268,12 +268,16 @@ async fn remove_extension( .get_agent() .await .map_err(|_| StatusCode::PRECONDITION_FAILED)?; - agent.remove_extension(&name).await; - - Ok(Json(ExtensionResponse { - error: false, - message: None, - })) + match agent.remove_extension(&name).await { + Ok(_) => Ok(Json(ExtensionResponse { + error: false, + message: None, + })), + Err(e) => Ok(Json(ExtensionResponse { + error: true, + message: Some(format!("Failed to remove extension: {:?}", e)), + })), + } } /// Registers the extension management routes with the Axum router. diff --git a/crates/goose/Cargo.toml b/crates/goose/Cargo.toml index 9bfa9e85134a..6809dd7376c0 100644 --- a/crates/goose/Cargo.toml +++ b/crates/goose/Cargo.toml @@ -76,6 +76,10 @@ blake3 = "1.5" fs2 = "0.4.3" futures-util = "0.3.31" +# Vector database for tool selection +lancedb = "0.13" +arrow = "52.2" + [target.'cfg(target_os = "windows")'.dependencies] winapi = { version = "0.3", features = ["wincred"] } diff --git a/crates/goose/src/agents/agent.rs b/crates/goose/src/agents/agent.rs index 5564470c9670..02bda3425bd7 100644 --- a/crates/goose/src/agents/agent.rs +++ b/crates/goose/src/agents/agent.rs @@ -18,7 +18,7 @@ use serde_json::Value; use tokio::sync::{mpsc, Mutex}; use tracing::{debug, error, instrument}; -use crate::agents::extension::{ExtensionConfig, ExtensionResult, ToolInfo}; +use crate::agents::extension::{ExtensionConfig, ExtensionError, ExtensionResult, ToolInfo}; use crate::agents::extension_manager::{get_parameter_names, ExtensionManager}; use crate::agents::platform_tools::{ PLATFORM_LIST_RESOURCES_TOOL_NAME, PLATFORM_MANAGE_EXTENSIONS_TOOL_NAME, @@ -29,6 +29,8 @@ use crate::agents::router_tool_selector::{ create_tool_selector, RouterToolSelectionStrategy, RouterToolSelector, }; use crate::agents::router_tools::ROUTER_VECTOR_SEARCH_TOOL_NAME; +use crate::agents::tool_router_index_manager::ToolRouterIndexManager; +use crate::agents::tool_vectordb::generate_table_id; use crate::agents::types::SessionConfig; use crate::agents::types::{FrontendTool, ToolResultReceiver}; use mcp_core::{ @@ -51,7 +53,7 @@ pub struct Agent { pub(super) tool_result_tx: mpsc::Sender<(String, ToolResult>)>, pub(super) tool_result_rx: ToolResultReceiver, pub(super) tool_monitor: Mutex>, - pub(super) router_tool_selector: Mutex>>, + pub(super) router_tool_selector: Mutex>>>, } impl Agent { @@ -60,16 +62,6 @@ impl Agent { let (confirm_tx, confirm_rx) = mpsc::channel(32); let (tool_tx, tool_rx) = mpsc::channel(32); - let router_tool_selection_strategy = std::env::var("GOOSE_ROUTER_TOOL_SELECTION_STRATEGY") - .ok() - .and_then(|s| { - if s.eq_ignore_ascii_case("vector") { - Some(RouterToolSelectionStrategy::Vector) - } else { - None - } - }); - Self { provider: Mutex::new(None), extension_manager: Mutex::new(ExtensionManager::new()), @@ -81,9 +73,7 @@ impl Agent { tool_result_tx: tool_tx, tool_result_rx: Arc::new(Mutex::new(tool_rx)), tool_monitor: Mutex::new(None), - router_tool_selector: Mutex::new(Some(create_tool_selector( - router_tool_selection_strategy, - ))), + router_tool_selector: Mutex::new(None), } } @@ -204,8 +194,8 @@ impl Agent { "Frontend tool execution required".to_string(), )) } else if tool_call.name == ROUTER_VECTOR_SEARCH_TOOL_NAME { - let router_tool_selector = self.router_tool_selector.lock().await; - if let Some(selector) = router_tool_selector.as_ref() { + let selector = self.router_tool_selector.lock().await.clone(); + if let Some(selector) = selector { selector.select_tools(tool_call.arguments.clone()).await } else { Err(ToolError::ExecutionError( @@ -284,6 +274,33 @@ impl Agent { }) .map_err(|e| ToolError::ExecutionError(e.to_string())); + // Update vector index if operation was successful and vector routing is enabled + if result.is_ok() { + let selector = self.router_tool_selector.lock().await.clone(); + if ToolRouterIndexManager::vector_tool_router_enabled(&selector) { + if let Some(selector) = selector { + let vector_action = if action == "disable" { "remove" } else { "add" }; + let extension_manager = self.extension_manager.lock().await; + if let Err(e) = ToolRouterIndexManager::update_extension_tools( + &selector, + &extension_manager, + &extension_name, + vector_action, + ) + .await + { + return ( + request_id, + Err(ToolError::ExecutionError(format!( + "Failed to update vector index: {}", + e + ))), + ); + } + } + } + } + (request_id, result) } @@ -317,10 +334,32 @@ impl Agent { } _ => { let mut extension_manager = self.extension_manager.lock().await; - extension_manager.add_extension(extension).await?; + extension_manager.add_extension(extension.clone()).await?; } }; + // If vector tool selection is enabled, index the tools + let selector = self.router_tool_selector.lock().await.clone(); + if ToolRouterIndexManager::vector_tool_router_enabled(&selector) { + if let Some(selector) = selector { + let extension_manager = self.extension_manager.lock().await; + if let Err(e) = ToolRouterIndexManager::update_extension_tools( + &selector, + &extension_manager, + &extension.name(), + "add", + ) + .await + { + return Err(ExtensionError::SetupError(format!( + "Failed to index tools for extension {}: {}", + extension.name(), + e + ))); + } + } + } + Ok(()) } @@ -350,8 +389,6 @@ impl Agent { &self, strategy: Option, ) -> Vec { - let extension_manager = self.extension_manager.lock().await; - let mut prefixed_tools = vec![]; match strategy { Some(RouterToolSelectionStrategy::Vector) => { @@ -359,22 +396,50 @@ impl Agent { } None => {} } - prefixed_tools.push(platform_tools::search_available_extensions_tool()); - prefixed_tools.push(platform_tools::manage_extensions_tool()); - if extension_manager.supports_resources() { - prefixed_tools.push(platform_tools::read_resource_tool()); - prefixed_tools.push(platform_tools::list_resources_tool()); + // Get recent tool calls from router tool selector if available + let selector = self.router_tool_selector.lock().await.clone(); + if let Some(selector) = selector { + if let Ok(recent_calls) = selector.get_recent_tool_calls(20).await { + let extension_manager = self.extension_manager.lock().await; + // Add recent tool calls to the list, avoiding duplicates + for tool_name in recent_calls { + // Find the tool in the extension manager's tools + if let Ok(extension_tools) = extension_manager.get_prefixed_tools(None).await { + if let Some(tool) = extension_tools.iter().find(|t| t.name == tool_name) { + // Only add if not already in prefixed_tools + if !prefixed_tools.iter().any(|t| t.name == tool.name) { + prefixed_tools.push(tool.clone()); + } + } + } + } + } } + prefixed_tools } - pub async fn remove_extension(&self, name: &str) { + pub async fn remove_extension(&self, name: &str) -> Result<()> { let mut extension_manager = self.extension_manager.lock().await; - extension_manager - .remove_extension(name) - .await - .expect("Failed to remove extension"); + extension_manager.remove_extension(name).await?; + + // If vector tool selection is enabled, remove tools from the index + let selector = self.router_tool_selector.lock().await.clone(); + if ToolRouterIndexManager::vector_tool_router_enabled(&selector) { + if let Some(selector) = selector { + let extension_manager = self.extension_manager.lock().await; + ToolRouterIndexManager::update_extension_tools( + &selector, + &extension_manager, + name, + "remove", + ) + .await?; + } + } + + Ok(()) } pub async fn list_extensions(&self) -> Vec { @@ -447,6 +512,26 @@ impl Agent { filtered_response) = self.categorize_tool_requests(&response).await; + // Record tool calls in the router selector + let selector = self.router_tool_selector.lock().await.clone(); + if let Some(selector) = selector { + // Record frontend tool calls + for request in &frontend_requests { + if let Ok(tool_call) = &request.tool_call { + if let Err(e) = selector.record_tool_call(&tool_call.name).await { + tracing::error!("Failed to record frontend tool call: {}", e); + } + } + } + // Record remaining tool calls + for request in &remaining_requests { + if let Ok(tool_call) = &request.tool_call { + if let Err(e) = selector.record_tool_call(&tool_call.name).await { + tracing::error!("Failed to record tool call: {}", e); + } + } + } + } // Yield the assistant's response with frontend tool requests filtered out yield filtered_response.clone(); @@ -598,7 +683,35 @@ impl Agent { /// Update the provider used by this agent pub async fn update_provider(&self, provider: Arc) -> Result<()> { - *self.provider.lock().await = Some(provider); + *self.provider.lock().await = Some(provider.clone()); + self.update_router_tool_selector(provider).await?; + Ok(()) + } + + async fn update_router_tool_selector(&self, provider: Arc) -> Result<()> { + let config = Config::global(); + let router_tool_selection_strategy = config + .get_param("GOOSE_ROUTER_TOOL_SELECTION_STRATEGY") + .unwrap_or_else(|_| "default".to_string()); + + let strategy = match router_tool_selection_strategy.to_lowercase().as_str() { + "vector" => Some(RouterToolSelectionStrategy::Vector), + _ => None, + }; + + if let Some(strategy) = strategy { + let table_name = generate_table_id(); + let selector = create_tool_selector(Some(strategy), provider, table_name) + .await + .map_err(|e| anyhow!("Failed to create tool selector: {}", e))?; + + let selector = Arc::new(selector); + *self.router_tool_selector.lock().await = Some(selector.clone()); + + let extension_manager = self.extension_manager.lock().await; + ToolRouterIndexManager::index_platform_tools(&selector, &extension_manager).await?; + } + Ok(()) } diff --git a/crates/goose/src/agents/mod.rs b/crates/goose/src/agents/mod.rs index fc44bcabc510..54326285216e 100644 --- a/crates/goose/src/agents/mod.rs +++ b/crates/goose/src/agents/mod.rs @@ -9,6 +9,8 @@ mod reply_parts; mod router_tool_selector; mod router_tools; mod tool_execution; +mod tool_router_index_manager; +pub(crate) mod tool_vectordb; mod types; pub use agent::Agent; diff --git a/crates/goose/src/agents/reply_parts.rs b/crates/goose/src/agents/reply_parts.rs index c777a4889577..0d7d8cbdefa1 100644 --- a/crates/goose/src/agents/reply_parts.rs +++ b/crates/goose/src/agents/reply_parts.rs @@ -3,6 +3,7 @@ use std::collections::HashSet; use std::sync::Arc; use crate::agents::router_tool_selector::RouterToolSelectionStrategy; +use crate::config::Config; use crate::message::{Message, MessageContent, ToolRequest}; use crate::providers::base::{Provider, ProviderUsage}; use crate::providers::errors::ProviderError; @@ -19,16 +20,17 @@ impl Agent { pub(crate) async fn prepare_tools_and_prompt( &self, ) -> anyhow::Result<(Vec, Vec, String)> { - // Get tool selection strategy - let tool_selection_strategy = std::env::var("GOOSE_ROUTER_TOOL_SELECTION_STRATEGY") - .ok() - .and_then(|s| { - if s.eq_ignore_ascii_case("vector") { - Some(RouterToolSelectionStrategy::Vector) - } else { - None - } - }); + // Get tool selection strategy from config + let config = Config::global(); + let router_tool_selection_strategy = config + .get_param("GOOSE_ROUTER_TOOL_SELECTION_STRATEGY") + .unwrap_or_else(|_| "default".to_string()); + + let tool_selection_strategy = match router_tool_selection_strategy.to_lowercase().as_str() { + "vector" => Some(RouterToolSelectionStrategy::Vector), + _ => None, + }; + // Get tools from extension manager let mut tools = match tool_selection_strategy { Some(RouterToolSelectionStrategy::Vector) => { diff --git a/crates/goose/src/agents/router_tool_selector.rs b/crates/goose/src/agents/router_tool_selector.rs index 6427952c8f88..62d28198854b 100644 --- a/crates/goose/src/agents/router_tool_selector.rs +++ b/crates/goose/src/agents/router_tool_selector.rs @@ -1,8 +1,20 @@ +use mcp_core::content::TextContent; +use mcp_core::tool::Tool; use mcp_core::{Content, ToolError}; +use anyhow::{Context, Result}; use async_trait::async_trait; use serde_json::Value; +use std::collections::VecDeque; +use std::env; +use std::sync::Arc; +use tokio::sync::RwLock; +use crate::agents::tool_vectordb::ToolVectorDB; +use crate::model::ModelConfig; +use crate::providers::{self, base::Provider}; + +#[derive(Debug, Clone, PartialEq)] pub enum RouterToolSelectionStrategy { Vector, } @@ -10,27 +22,194 @@ pub enum RouterToolSelectionStrategy { #[async_trait] pub trait RouterToolSelector: Send + Sync { async fn select_tools(&self, params: Value) -> Result, ToolError>; + async fn index_tools(&self, tools: &[Tool]) -> Result<(), ToolError>; + async fn remove_tool(&self, tool_name: &str) -> Result<(), ToolError>; + async fn record_tool_call(&self, tool_name: &str) -> Result<(), ToolError>; + async fn get_recent_tool_calls(&self, limit: usize) -> Result, ToolError>; + fn selector_type(&self) -> RouterToolSelectionStrategy; +} + +pub struct VectorToolSelector { + vector_db: Arc>, + embedding_provider: Arc, + recent_tool_calls: Arc>>, } -pub struct VectorToolSelector; +impl VectorToolSelector { + pub async fn new(provider: Arc, table_name: String) -> Result { + let vector_db = ToolVectorDB::new(Some(table_name)).await?; + + let embedding_provider = if env::var("EMBEDDING_MODEL_PROVIDER").is_ok() { + // If env var is set, create a new provider for embeddings + // Get embedding model and provider from environment variables + let embedding_model = env::var("EMBEDDING_MODEL") + .unwrap_or_else(|_| "text-embedding-3-small".to_string()); + let embedding_provider_name = + env::var("EMBEDDING_MODEL_PROVIDER").unwrap_or_else(|_| "openai".to_string()); + + // Create the provider using the factory + let model_config = ModelConfig::new(embedding_model); + providers::create(&embedding_provider_name, model_config).context(format!( + "Failed to create {} provider for embeddings. If using OpenAI, make sure OPENAI_API_KEY env var is set or that you have configured the OpenAI provider via Goose before.", + embedding_provider_name + ))? + } else { + // Otherwise fall back to using the same provider instance as used for base goose model + provider.clone() + }; + + Ok(Self { + vector_db: Arc::new(RwLock::new(vector_db)), + embedding_provider, + recent_tool_calls: Arc::new(RwLock::new(VecDeque::with_capacity(100))), + }) + } +} #[async_trait] impl RouterToolSelector for VectorToolSelector { async fn select_tools(&self, params: Value) -> Result, ToolError> { - let query = params.get("query").and_then(|v| v.as_str()); - println!("query: {:?}", query); - let selected_tools = Vec::new(); - // TODO: placeholder for vector tool selection + let query = params + .get("query") + .and_then(|v| v.as_str()) + .ok_or_else(|| ToolError::InvalidParameters("Missing 'query' parameter".to_string()))?; + + let k = params.get("k").and_then(|v| v.as_u64()).unwrap_or(5) as usize; + + // Check if provider supports embeddings + if !self.embedding_provider.supports_embeddings() { + return Err(ToolError::ExecutionError( + "Embedding provider does not support embeddings".to_string(), + )); + } + + let embeddings = self + .embedding_provider + .create_embeddings(vec![query.to_string()]) + .await + .map_err(|e| { + ToolError::ExecutionError(format!("Failed to generate query embedding: {}", e)) + })?; + + let query_embedding = embeddings + .into_iter() + .next() + .ok_or_else(|| ToolError::ExecutionError("No embedding returned".to_string()))?; + + let vector_db = self.vector_db.read().await; + let tools = vector_db + .search_tools(query_embedding, k) + .await + .map_err(|e| ToolError::ExecutionError(format!("Failed to search tools: {}", e)))?; + + let selected_tools: Vec = tools + .into_iter() + .map(|tool| { + let text = format!( + "Tool: {}\nDescription: {}\nSchema: {}", + tool.tool_name, tool.description, tool.schema + ); + Content::Text(TextContent { + text, + annotations: None, + }) + }) + .collect(); + Ok(selected_tools) } + + async fn index_tools(&self, tools: &[Tool]) -> Result<(), ToolError> { + let texts_to_embed: Vec = tools + .iter() + .map(|tool| { + let schema_str = serde_json::to_string_pretty(&tool.input_schema) + .unwrap_or_else(|_| "{}".to_string()); + format!("{} {} {}", tool.name, tool.description, schema_str) + }) + .collect(); + + if !self.embedding_provider.supports_embeddings() { + return Err(ToolError::ExecutionError( + "Embedding provider does not support embeddings".to_string(), + )); + } + + let embeddings = self + .embedding_provider + .create_embeddings(texts_to_embed) + .await + .map_err(|e| { + ToolError::ExecutionError(format!("Failed to generate tool embeddings: {}", e)) + })?; + + // Create tool records + let tool_records: Vec = tools + .iter() + .zip(embeddings.into_iter()) + .map(|(tool, vector)| { + let schema_str = serde_json::to_string_pretty(&tool.input_schema) + .unwrap_or_else(|_| "{}".to_string()); + crate::agents::tool_vectordb::ToolRecord { + tool_name: tool.name.clone(), + description: tool.description.clone(), + schema: schema_str, + vector, + } + }) + .collect(); + + // Index all tools at once + let vector_db = self.vector_db.read().await; + vector_db + .index_tools(tool_records) + .await + .map_err(|e| ToolError::ExecutionError(format!("Failed to index tools: {}", e)))?; + + Ok(()) + } + + async fn remove_tool(&self, tool_name: &str) -> Result<(), ToolError> { + let vector_db = self.vector_db.read().await; + vector_db.remove_tool(tool_name).await.map_err(|e| { + ToolError::ExecutionError(format!("Failed to remove tool {}: {}", tool_name, e)) + })?; + Ok(()) + } + + async fn record_tool_call(&self, tool_name: &str) -> Result<(), ToolError> { + let mut recent_calls = self.recent_tool_calls.write().await; + if recent_calls.len() >= 100 { + recent_calls.pop_front(); + } + recent_calls.push_back(tool_name.to_string()); + Ok(()) + } + + async fn get_recent_tool_calls(&self, limit: usize) -> Result, ToolError> { + let recent_calls = self.recent_tool_calls.read().await; + Ok(recent_calls.iter().rev().take(limit).cloned().collect()) + } + + fn selector_type(&self) -> RouterToolSelectionStrategy { + RouterToolSelectionStrategy::Vector + } } // Helper function to create a boxed tool selector -pub fn create_tool_selector( +pub async fn create_tool_selector( strategy: Option, -) -> Box { + provider: Arc, + table_name: String, +) -> Result> { match strategy { - Some(RouterToolSelectionStrategy::Vector) => Box::new(VectorToolSelector), - _ => Box::new(VectorToolSelector), // Default to VectorToolSelector + Some(RouterToolSelectionStrategy::Vector) => { + let selector = VectorToolSelector::new(provider, table_name).await?; + Ok(Box::new(selector)) + } + None => { + let selector = VectorToolSelector::new(provider, table_name).await?; + Ok(Box::new(selector)) + } } } diff --git a/crates/goose/src/agents/router_tools.rs b/crates/goose/src/agents/router_tools.rs index fe7aee59e5bb..e9ec9a96ceeb 100644 --- a/crates/goose/src/agents/router_tools.rs +++ b/crates/goose/src/agents/router_tools.rs @@ -22,7 +22,8 @@ pub fn vector_search_tool() -> Tool { "type": "object", "required": ["query"], "properties": { - "query": {"type": "string", "description": "The query to search for the most relevant tools based on the user's messages"} + "query": {"type": "string", "description": "The query to search for the most relevant tools based on the user's messages"}, + "k": {"type": "integer", "description": "The number of tools to retrieve (defaults to 5)", "default": 5} } }), Some(ToolAnnotations { diff --git a/crates/goose/src/agents/tool_router_index_manager.rs b/crates/goose/src/agents/tool_router_index_manager.rs new file mode 100644 index 000000000000..cdee03263ae1 --- /dev/null +++ b/crates/goose/src/agents/tool_router_index_manager.rs @@ -0,0 +1,106 @@ +use anyhow::{anyhow, Result}; +use std::sync::Arc; +use tracing; + +use crate::agents::extension_manager::ExtensionManager; +use crate::agents::platform_tools; +use crate::agents::router_tool_selector::{RouterToolSelectionStrategy, RouterToolSelector}; + +/// Manages tool indexing operations for the router when vector routing is enabled +pub struct ToolRouterIndexManager; + +impl ToolRouterIndexManager { + /// Updates the vector index for tools when extensions are added or removed + pub async fn update_extension_tools( + selector: &Arc>, + extension_manager: &ExtensionManager, + extension_name: &str, + action: &str, + ) -> Result<()> { + match action { + "add" => { + // Get tools for specific extension + let tools = extension_manager + .get_prefixed_tools(Some(extension_name.to_string())) + .await?; + + if !tools.is_empty() { + // Index all tools at once + selector.index_tools(&tools).await.map_err(|e| { + anyhow!( + "Failed to index tools for extension {}: {}", + extension_name, + e + ) + })?; + + tracing::info!( + "Indexed {} tools for extension {}", + tools.len(), + extension_name + ); + } + } + "remove" => { + // Get tool names for the extension to remove them + let tools = extension_manager + .get_prefixed_tools(Some(extension_name.to_string())) + .await?; + + for tool in &tools { + selector + .remove_tool(&tool.name) + .await + .map_err(|e| anyhow!("Failed to remove tool {}: {}", tool.name, e))?; + } + + tracing::info!( + "Removed {} tools for extension {}", + tools.len(), + extension_name + ); + } + _ => { + anyhow::bail!("Invalid action '{}' for tool indexing", action); + } + } + + Ok(()) + } + + /// Indexes platform tools (search_available_extensions, manage_extensions, etc.) + pub async fn index_platform_tools( + selector: &Arc>, + extension_manager: &ExtensionManager, + ) -> Result<()> { + let mut tools = Vec::new(); + + // Add the standard platform tools + tools.push(platform_tools::search_available_extensions_tool()); + tools.push(platform_tools::manage_extensions_tool()); + + // Add resource tools if supported + if extension_manager.supports_resources() { + tools.push(platform_tools::read_resource_tool()); + tools.push(platform_tools::list_resources_tool()); + } + + // Index all platform tools at once + selector + .index_tools(&tools) + .await + .map_err(|e| anyhow!("Failed to index platform tools: {}", e))?; + + tracing::info!("Indexed platform tools for vector search"); + Ok(()) + } + + /// Helper to check if vector tool router is enabled + pub fn vector_tool_router_enabled(selector: &Option>>) -> bool { + if let Some(selector) = selector { + selector.selector_type() == RouterToolSelectionStrategy::Vector + } else { + false + } + } +} diff --git a/crates/goose/src/agents/tool_vectordb.rs b/crates/goose/src/agents/tool_vectordb.rs new file mode 100644 index 000000000000..e46c13b41542 --- /dev/null +++ b/crates/goose/src/agents/tool_vectordb.rs @@ -0,0 +1,440 @@ +use anyhow::{Context, Result}; +use arrow::array::{FixedSizeListBuilder, StringArray}; +use arrow::datatypes::{DataType, Field, Schema}; +use chrono::Local; +use etcetera::base_strategy::{BaseStrategy, Xdg}; +use futures::TryStreamExt; +use lancedb::connect; +use lancedb::connection::Connection; +use lancedb::query::{ExecutableQuery, QueryBase}; +use serde::{Deserialize, Serialize}; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::sync::RwLock; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ToolRecord { + pub tool_name: String, + pub description: String, + pub schema: String, + pub vector: Vec, +} + +pub struct ToolVectorDB { + connection: Arc>, + table_name: String, +} + +impl ToolVectorDB { + pub async fn new(table_name: Option) -> Result { + let db_path = Self::get_db_path()?; + + // Ensure the directory exists + if let Some(parent) = db_path.parent() { + tokio::fs::create_dir_all(parent) + .await + .context("Failed to create database directory")?; + } + + let connection = connect(db_path.to_str().unwrap()) + .execute() + .await + .context("Failed to connect to LanceDB")?; + + let tool_db = Self { + connection: Arc::new(RwLock::new(connection)), + table_name: table_name.unwrap_or_else(|| "tools".to_string()), + }; + + // Initialize the table if it doesn't exist + tool_db.init_table().await?; + + Ok(tool_db) + } + + fn get_db_path() -> Result { + let data_dir = Xdg::new() + .context("Failed to determine base strategy")? + .data_dir(); + + Ok(data_dir.join("goose").join("tool_db")) + } + + async fn init_table(&self) -> Result<()> { + let connection = self.connection.read().await; + + // Check if table exists + let table_names = connection + .table_names() + .execute() + .await + .context("Failed to list tables")?; + + if !table_names.contains(&self.table_name) { + // Create the table schema + let schema = Arc::new(Schema::new(vec![ + Field::new("tool_name", DataType::Utf8, false), + Field::new("description", DataType::Utf8, false), + Field::new("schema", DataType::Utf8, false), + Field::new( + "vector", + DataType::FixedSizeList( + Arc::new(Field::new("item", DataType::Float32, true)), + 1536, // OpenAI embedding dimension + ), + false, + ), + ])); + + // Create empty table + let tool_names = StringArray::from(vec![] as Vec<&str>); + let descriptions = StringArray::from(vec![] as Vec<&str>); + let schemas = StringArray::from(vec![] as Vec<&str>); + + // Create empty fixed size list array for vectors + let mut vectors_builder = + FixedSizeListBuilder::new(arrow::array::Float32Builder::new(), 1536); + let vectors = vectors_builder.finish(); + + let batch = arrow::record_batch::RecordBatch::try_new( + schema.clone(), + vec![ + Arc::new(tool_names), + Arc::new(descriptions), + Arc::new(schemas), + Arc::new(vectors), + ], + ) + .context("Failed to create record batch")?; + // Create an empty table with the schema + // LanceDB will create the table from the RecordBatch + drop(connection); + let connection = self.connection.write().await; + + // Use the RecordBatch directly + let reader = arrow::record_batch::RecordBatchIterator::new( + vec![Ok(batch)].into_iter(), + schema.clone(), + ); + + connection + .create_table(&self.table_name, Box::new(reader)) + .execute() + .await + .map_err(|e| { + anyhow::anyhow!("Failed to create tools table '{}': {}", self.table_name, e) + })?; + } + + Ok(()) + } + + #[cfg(test)] + pub async fn clear_tools(&self) -> Result<()> { + let connection = self.connection.write().await; + + // Try to open the table first + match connection.open_table(&self.table_name).execute().await { + Ok(table) => { + // Delete all records instead of dropping the table + table + .delete("1=1") // This will match all records + .await + .context("Failed to delete all records")?; + } + Err(_) => { + // If table doesn't exist, that's fine - we'll create it + } + } + + drop(connection); + + // Ensure table exists with correct schema + self.init_table().await?; + + Ok(()) + } + + pub async fn index_tools(&self, tools: Vec) -> Result<()> { + if tools.is_empty() { + return Ok(()); + } + + let tool_names: Vec<&str> = tools.iter().map(|t| t.tool_name.as_str()).collect(); + let descriptions: Vec<&str> = tools.iter().map(|t| t.description.as_str()).collect(); + let schemas: Vec<&str> = tools.iter().map(|t| t.schema.as_str()).collect(); + + let vectors_data: Vec>>> = tools + .iter() + .map(|t| Some(t.vector.iter().map(|&v| Some(v)).collect())) + .collect(); + + let schema = Arc::new(Schema::new(vec![ + Field::new("tool_name", DataType::Utf8, false), + Field::new("description", DataType::Utf8, false), + Field::new("schema", DataType::Utf8, false), + Field::new( + "vector", + DataType::FixedSizeList( + Arc::new(Field::new("item", DataType::Float32, true)), + 1536, + ), + false, + ), + ])); + + let tool_names_array = StringArray::from(tool_names); + let descriptions_array = StringArray::from(descriptions); + let schemas_array = StringArray::from(schemas); + // Build vectors array + let mut vectors_builder = + FixedSizeListBuilder::new(arrow::array::Float32Builder::new(), 1536); + for vector_opt in vectors_data { + if let Some(vector) = vector_opt { + let values = vectors_builder.values(); + for val_opt in vector { + if let Some(val) = val_opt { + values.append_value(val); + } else { + values.append_null(); + } + } + vectors_builder.append(true); + } else { + vectors_builder.append(false); + } + } + let vectors_array = vectors_builder.finish(); + + let batch = arrow::record_batch::RecordBatch::try_new( + schema.clone(), + vec![ + Arc::new(tool_names_array), + Arc::new(descriptions_array), + Arc::new(schemas_array), + Arc::new(vectors_array), + ], + ) + .context("Failed to create record batch")?; + + let connection = self.connection.read().await; + let table = connection + .open_table(&self.table_name) + .execute() + .await + .context("Failed to open tools table")?; + + // Add batch to table using RecordBatchIterator + let reader = arrow::record_batch::RecordBatchIterator::new( + vec![Ok(batch)].into_iter(), + schema.clone(), + ); + + table + .add(Box::new(reader)) + .execute() + .await + .context("Failed to add tools to table")?; + + Ok(()) + } + + pub async fn search_tools(&self, query_vector: Vec, k: usize) -> Result> { + let connection = self.connection.read().await; + + let table = connection + .open_table(&self.table_name) + .execute() + .await + .context("Failed to open tools table")?; + + let results = table + .vector_search(query_vector) + .context("Failed to create vector search")? + .limit(k) + .execute() + .await + .context("Failed to execute vector search")?; + + let batches: Vec<_> = results.try_collect().await?; + + let mut tools = Vec::new(); + for batch in batches { + let tool_names = batch + .column_by_name("tool_name") + .context("Missing tool_name column")? + .as_any() + .downcast_ref::() + .context("Invalid tool_name column type")?; + + let descriptions = batch + .column_by_name("description") + .context("Missing description column")? + .as_any() + .downcast_ref::() + .context("Invalid description column type")?; + + let schemas = batch + .column_by_name("schema") + .context("Missing schema column")? + .as_any() + .downcast_ref::() + .context("Invalid schema column type")?; + + // Get the distance scores + let distances = batch + .column_by_name("_distance") + .context("Missing _distance column")? + .as_any() + .downcast_ref::() + .context("Invalid _distance column type")?; + + for i in 0..batch.num_rows() { + let tool_name = tool_names.value(i).to_string(); + let _distance = distances.value(i); + + tools.push(ToolRecord { + tool_name, + description: descriptions.value(i).to_string(), + schema: schemas.value(i).to_string(), + vector: vec![], // We don't need to return the vector + }); + } + } + Ok(tools) + } + + pub async fn remove_tool(&self, tool_name: &str) -> Result<()> { + let connection = self.connection.read().await; + + let table = connection + .open_table(&self.table_name) + .execute() + .await + .context("Failed to open tools table")?; + + // Delete records matching the tool name + table + .delete(&format!("tool_name = '{}'", tool_name)) + .await + .context("Failed to delete tool")?; + + Ok(()) + } +} + +pub fn generate_table_id() -> String { + Local::now().format("%Y%m%d_%H%M%S").to_string() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[tokio::test] + async fn test_tool_vectordb_creation() { + let db = ToolVectorDB::new(Some("test_tools_vectordb_creation".to_string())) + .await + .unwrap(); + db.clear_tools().await.unwrap(); + assert_eq!(db.table_name, "test_tools_vectordb_creation"); + } + + #[tokio::test] + async fn test_tool_vectordb_operations() -> Result<()> { + // Create a new database instance with a unique table name + let db = ToolVectorDB::new(Some("test_tool_vectordb_operations".to_string())).await?; + + // Clear any existing tools + db.clear_tools().await?; + + // Create test tool records + let test_tools = vec![ + ToolRecord { + tool_name: "test_tool_1".to_string(), + description: "A test tool for reading files".to_string(), + schema: r#"{"type": "object", "properties": {"path": {"type": "string"}}}"# + .to_string(), + vector: vec![0.1; 1536], // Mock embedding vector + }, + ToolRecord { + tool_name: "test_tool_2".to_string(), + description: "A test tool for writing files".to_string(), + schema: r#"{"type": "object", "properties": {"path": {"type": "string"}}}"# + .to_string(), + vector: vec![0.2; 1536], // Different mock embedding vector + }, + ]; + + // Index the test tools + db.index_tools(test_tools).await?; + + // Search for tools using a query vector similar to test_tool_1 + let query_vector = vec![0.1; 1536]; + let results = db.search_tools(query_vector, 2).await?; + + // Verify results + assert_eq!(results.len(), 2, "Should find both tools"); + assert_eq!( + results[0].tool_name, "test_tool_1", + "First result should be test_tool_1" + ); + assert_eq!( + results[1].tool_name, "test_tool_2", + "Second result should be test_tool_2" + ); + + Ok(()) + } + + #[tokio::test] + async fn test_empty_db() -> Result<()> { + // Create a new database instance with a unique table name + let db = ToolVectorDB::new(Some("test_empty_db".to_string())).await?; + + // Clear any existing tools + db.clear_tools().await?; + + // Search in empty database + let query_vector = vec![0.1; 1536]; + let results = db.search_tools(query_vector, 2).await?; + + // Verify no results returned + assert_eq!(results.len(), 0, "Empty database should return no results"); + + Ok(()) + } + + #[tokio::test] + async fn test_tool_deletion() -> Result<()> { + // Create a new database instance with a unique table name + let db = ToolVectorDB::new(Some("test_tool_deletion".to_string())).await?; + + // Clear any existing tools + db.clear_tools().await?; + + // Create and index a test tool + let test_tool = ToolRecord { + tool_name: "test_tool_to_delete".to_string(), + description: "A test tool that will be deleted".to_string(), + schema: r#"{"type": "object", "properties": {"path": {"type": "string"}}}"#.to_string(), + vector: vec![0.1; 1536], + }; + + db.index_tools(vec![test_tool]).await?; + + // Verify tool exists + let query_vector = vec![0.1; 1536]; + let results = db.search_tools(query_vector.clone(), 1).await?; + assert_eq!(results.len(), 1, "Tool should exist before deletion"); + + // Delete the tool + db.remove_tool("test_tool_to_delete").await?; + + // Verify tool is gone + let results = db.search_tools(query_vector.clone(), 1).await?; + assert_eq!(results.len(), 0, "Tool should be deleted"); + + Ok(()) + } +} diff --git a/crates/goose/src/providers/base.rs b/crates/goose/src/providers/base.rs index aa4bea4e12f5..c7062642141a 100644 --- a/crates/goose/src/providers/base.rs +++ b/crates/goose/src/providers/base.rs @@ -183,6 +183,18 @@ pub trait Provider: Send + Sync { async fn fetch_supported_models_async(&self) -> Result>, ProviderError> { Ok(None) } + + /// Check if this provider supports embeddings + fn supports_embeddings(&self) -> bool { + false + } + + /// Create embeddings if supported. Default implementation returns an error. + async fn create_embeddings(&self, _texts: Vec) -> Result>, ProviderError> { + Err(ProviderError::ExecutionError( + "This provider does not support embeddings".to_string(), + )) + } } #[cfg(test)] diff --git a/crates/goose/src/providers/databricks.rs b/crates/goose/src/providers/databricks.rs index 189d5b97ca05..7a04407a829c 100644 --- a/crates/goose/src/providers/databricks.rs +++ b/crates/goose/src/providers/databricks.rs @@ -1,11 +1,5 @@ -use anyhow::Result; -use async_trait::async_trait; -use reqwest::{Client, StatusCode}; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use std::time::Duration; - use super::base::{ConfigKey, Provider, ProviderMetadata, ProviderUsage, Usage}; +use super::embedding::EmbeddingCapable; use super::errors::ProviderError; use super::formats::databricks::{create_request, get_usage, response_to_message}; use super::oauth; @@ -14,8 +8,16 @@ use crate::config::ConfigError; use crate::message::Message; use crate::model::ModelConfig; use mcp_core::tool::Tool; +use serde_json::json; use url::Url; +use anyhow::Result; +use async_trait::async_trait; +use reqwest::{Client, StatusCode}; +use serde::{Deserialize, Serialize}; +use serde_json::Value; +use std::time::Duration; + const DEFAULT_CLIENT_ID: &str = "databricks-cli"; const DEFAULT_REDIRECT_URL: &str = "http://localhost:8020"; // "offline_access" scope is used to request an OAuth 2.0 Refresh Token @@ -128,7 +130,6 @@ impl DatabricksProvider { /// /// * `host` - The Databricks host URL /// * `token` - The Databricks API token - /// * `model` - The model configuration /// /// # Returns /// @@ -166,7 +167,17 @@ impl DatabricksProvider { async fn post(&self, payload: Value) -> Result { let base_url = Url::parse(&self.host) .map_err(|e| ProviderError::RequestFailed(format!("Invalid base URL: {e}")))?; - let path = format!("serving-endpoints/{}/invocations", self.model.model_name); + + // Check if this is an embedding request by looking at the payload structure + let is_embedding = payload.get("input").is_some() && payload.get("messages").is_none(); + let path = if is_embedding { + // For embeddings, use the embeddings endpoint + format!("serving-endpoints/{}/invocations", "text-embedding-3-small") + } else { + // For chat completions, use the model name in the path + format!("serving-endpoints/{}/invocations", self.model.model_name) + }; + let url = base_url.join(&path).map_err(|e| { ProviderError::RequestFailed(format!("Failed to construct endpoint URL: {e}")) })?; @@ -184,7 +195,7 @@ impl DatabricksProvider { let payload: Option = response.json().await.ok(); match status { - StatusCode::OK => payload.ok_or_else( || ProviderError::RequestFailed("Response body is not valid JSON".to_string()) ), + StatusCode::OK => payload.ok_or_else(|| ProviderError::RequestFailed("Response body is not valid JSON".to_string())), StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => { Err(ProviderError::Authentication(format!("Authentication failed. Please ensure your API keys are valid and have the required permissions. \ Status: {}. Response: {:?}", status, payload))) @@ -295,4 +306,47 @@ impl Provider for DatabricksProvider { Ok((message, ProviderUsage::new(model, usage))) } + + fn supports_embeddings(&self) -> bool { + true + } + + async fn create_embeddings(&self, texts: Vec) -> Result>, ProviderError> { + EmbeddingCapable::create_embeddings(self, texts) + .await + .map_err(|e| ProviderError::ExecutionError(e.to_string())) + } +} + +#[async_trait] +impl EmbeddingCapable for DatabricksProvider { + async fn create_embeddings(&self, texts: Vec) -> Result>> { + if texts.is_empty() { + return Ok(vec![]); + } + + // Create request in Databricks format for embeddings + let request = json!({ + "input": texts, + }); + + let response = self.post(request).await?; + + let embeddings = response["data"] + .as_array() + .ok_or_else(|| anyhow::anyhow!("Invalid response format: missing data array"))? + .iter() + .map(|item| { + item["embedding"] + .as_array() + .ok_or_else(|| anyhow::anyhow!("Invalid embedding format"))? + .iter() + .map(|v| v.as_f64().map(|f| f as f32)) + .collect::>>() + .ok_or_else(|| anyhow::anyhow!("Invalid embedding values")) + }) + .collect::>>>()?; + + Ok(embeddings) + } } diff --git a/crates/goose/src/providers/embedding.rs b/crates/goose/src/providers/embedding.rs new file mode 100644 index 000000000000..469d22aeb57e --- /dev/null +++ b/crates/goose/src/providers/embedding.rs @@ -0,0 +1,24 @@ +use anyhow::Result; +use async_trait::async_trait; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EmbeddingRequest { + pub input: Vec, + pub model: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EmbeddingResponse { + pub data: Vec, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct EmbeddingData { + pub embedding: Vec, +} + +#[async_trait] +pub trait EmbeddingCapable { + async fn create_embeddings(&self, texts: Vec) -> Result>>; +} diff --git a/crates/goose/src/providers/mod.rs b/crates/goose/src/providers/mod.rs index 14b810d880dc..c91e43c6267f 100644 --- a/crates/goose/src/providers/mod.rs +++ b/crates/goose/src/providers/mod.rs @@ -4,6 +4,7 @@ pub mod azureauth; pub mod base; pub mod bedrock; pub mod databricks; +pub mod embedding; pub mod errors; mod factory; pub mod formats; diff --git a/crates/goose/src/providers/openai.rs b/crates/goose/src/providers/openai.rs index 22c516d94009..71553a4c59f6 100644 --- a/crates/goose/src/providers/openai.rs +++ b/crates/goose/src/providers/openai.rs @@ -6,6 +6,7 @@ use std::collections::HashMap; use std::time::Duration; use super::base::{ConfigKey, Provider, ProviderMetadata, ProviderUsage, Usage}; +use super::embedding::{EmbeddingCapable, EmbeddingRequest, EmbeddingResponse}; use super::errors::ProviderError; use super::formats::openai::{create_request, get_usage, response_to_message}; use super::utils::{emit_debug_trace, get_model, handle_response_openai_compat, ImageFormat}; @@ -80,18 +81,8 @@ impl OpenAiProvider { }) } - async fn post(&self, payload: Value) -> Result { - let base_url = url::Url::parse(&self.host) - .map_err(|e| ProviderError::RequestFailed(format!("Invalid base URL: {e}")))?; - let url = base_url.join(&self.base_path).map_err(|e| { - ProviderError::RequestFailed(format!("Failed to construct endpoint URL: {e}")) - })?; - - let mut request = self - .client - .post(url) - .header("Authorization", format!("Bearer {}", self.api_key)); - + /// Helper function to add OpenAI-specific headers to a request + fn add_headers(&self, mut request: reqwest::RequestBuilder) -> reqwest::RequestBuilder { // Add organization header if present if let Some(org) = &self.organization { request = request.header("OpenAI-Organization", org); @@ -102,12 +93,30 @@ impl OpenAiProvider { request = request.header("OpenAI-Project", project); } + // Add custom headers if present if let Some(custom_headers) = &self.custom_headers { for (key, value) in custom_headers { request = request.header(key, value); } } + request + } + + async fn post(&self, payload: Value) -> Result { + let base_url = url::Url::parse(&self.host) + .map_err(|e| ProviderError::RequestFailed(format!("Invalid base URL: {e}")))?; + let url = base_url.join(&self.base_path).map_err(|e| { + ProviderError::RequestFailed(format!("Failed to construct endpoint URL: {e}")) + })?; + + let request = self + .client + .post(url) + .header("Authorization", format!("Bearer {}", self.api_key)); + + let request = self.add_headers(request); + let response = request.json(&payload).send().await?; handle_response_openai_compat(response).await @@ -209,6 +218,16 @@ impl Provider for OpenAiProvider { models.sort(); Ok(Some(models)) } + + fn supports_embeddings(&self) -> bool { + true + } + + async fn create_embeddings(&self, texts: Vec) -> Result>, ProviderError> { + EmbeddingCapable::create_embeddings(self, texts) + .await + .map_err(|e| ProviderError::ExecutionError(e.to_string())) + } } fn parse_custom_headers(s: String) -> HashMap { @@ -221,3 +240,57 @@ fn parse_custom_headers(s: String) -> HashMap { }) .collect() } + +#[async_trait] +impl EmbeddingCapable for OpenAiProvider { + async fn create_embeddings(&self, texts: Vec) -> Result>> { + if texts.is_empty() { + return Ok(vec![]); + } + + // Get embedding model from env var or use default + let embedding_model = std::env::var("EMBEDDING_MODEL") + .unwrap_or_else(|_| "text-embedding-3-small".to_string()); + + let request = EmbeddingRequest { + input: texts, + model: embedding_model, + }; + + // Construct embeddings endpoint URL + let base_url = + url::Url::parse(&self.host).map_err(|e| anyhow::anyhow!("Invalid base URL: {e}"))?; + let url = base_url + .join("v1/embeddings") + .map_err(|e| anyhow::anyhow!("Failed to construct embeddings URL: {e}"))?; + + let req = self + .client + .post(url) + .header("Authorization", format!("Bearer {}", self.api_key)) + .json(&request); + + let req = self.add_headers(req); + + let response = req + .send() + .await + .map_err(|e| anyhow::anyhow!("Failed to send embedding request: {e}"))?; + + if !response.status().is_success() { + let error_text = response.text().await.unwrap_or_default(); + return Err(anyhow::anyhow!("Embedding API error: {}", error_text)); + } + + let embedding_response: EmbeddingResponse = response + .json() + .await + .map_err(|e| anyhow::anyhow!("Failed to parse embedding response: {e}"))?; + + Ok(embedding_response + .data + .into_iter() + .map(|d| d.embedding) + .collect()) + } +} diff --git a/documentation/docs/guides/tool-router.md b/documentation/docs/guides/tool-router.md new file mode 100644 index 000000000000..7744b57f8023 --- /dev/null +++ b/documentation/docs/guides/tool-router.md @@ -0,0 +1,86 @@ +# Tool Router (preview) + +## Overview + +Tool Router is a powerful feature that addresses a common challenge in LLM-based development: the difficulty of selecting the right tool when multiple extensions are enabled. Traditional approaches feed an entire list of tools into the context during chat sessions, which not only consumes a significant number of tokens but also reduces the effectiveness of tool calling. + +## The Problem + +When you enable multiple extensions (like Slack), you get access to numerous tools such as: +- Reading threads +- Sending messages +- Creating channels +- And many more + +However, you typically don't need all this functionality at once. Loading every available tool into the context can be inefficient and potentially confusing for the LLM. + +## The Solution: Tool Router + +Tool Router introduces a smarter way to handle tool selection through vector-based indexing. Instead of passing all tools back and forth, it: + +1. Indexes all tools from your enabled extensions +2. Uses vector search to load only the relevant tools into context when needed +3. Ensures that only the functionality you actually need is available + +## Configuration + +To enable this feature, change the Tool Selection Strategy from default to vector. + +#### CLI +To configure Tool Router in the CLI, follow these steps: + +1. Run the configuration command: +```bash +./target/debug/goose configure +``` + +2. This will update your existing config file. Alternatively, you can edit it directly at: +``` +/Users/wendytang/.config/goose/config.yaml +``` + +3. During configuration: + - Select "Goose Settings" + - Choose "Router Tool Selection Strategy" + - Select "Vector Strategy" + +The configuration process will look like this: +``` +┌ goose-configure +│ +◇ What would you like to configure? +│ Goose Settings +│ +◇ What setting would you like to configure? +│ Router Tool Selection Strategy +│ +◇ Which router strategy would you like to use? +│ Vector Strategy +│ +└ Set to Vector Strategy - using vector-based similarity for tool selection +``` + +#### UI +Toggle the settings button on the top right and head to 'Advanced Settings', then 'Tool Selection Strategy' at the botoom. + +## Benefits + +- Reduced token consumption +- More accurate tool selection +- Improved LLM performance +- Better context management +- More efficient use of available tools + +## Notes + +### Model Compatibility + +Tool Router currently only works with Claude models served through Databricks. The embedding functionality uses OpenAI's `text-embedding-3-small` model by default. + +### Feedback & Next Steps + +We'd love to hear your thoughts on this feature! Please reach out in the Goose Discord channel to share your use case and experience. + +Our roadmap includes: +- Expanding Tool Router support to OpenAI models +- Adding customization options for the `k` parameter that controls how many similar tools are returned during vector similarity search diff --git a/documentation/yarn.lock b/documentation/yarn.lock index acbb2cd60ebb..3494f6d2ef1a 100644 --- a/documentation/yarn.lock +++ b/documentation/yarn.lock @@ -84,7 +84,7 @@ "@algolia/requester-fetch" "5.20.0" "@algolia/requester-node-http" "5.20.0" -"@algolia/client-search@>= 4.9.1 < 6", "@algolia/client-search@5.20.0": +"@algolia/client-search@5.20.0": version "5.20.0" resolved "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.20.0.tgz" integrity sha512-KL1zWTzrlN4MSiaK1ea560iCA/UewMbS4ZsLQRPoDTWyrbDKVbztkPwwv764LAqgXk0fvkNZvJ3IelcK7DqhjQ== @@ -177,7 +177,7 @@ resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.5.tgz" integrity sha512-XvcZi1KWf88RVbF9wn8MN6tYFloU5qX8KjuF3E1PVBmJ9eypXfs4GRiJwLuTZL0iSnJUKn1BFPa5BPZZJyFzPg== -"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.21.3", "@babel/core@^7.25.9", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0": +"@babel/core@^7.21.3", "@babel/core@^7.25.9": version "7.26.0" resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz" integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg== @@ -1598,7 +1598,7 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@*", "@docusaurus/plugin-content-docs@3.7.0": +"@docusaurus/plugin-content-docs@3.7.0": version "3.7.0" resolved "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.7.0.tgz" integrity sha512-GXg5V7kC9FZE4FkUZA8oo/NrlRb06UwuICzI6tcbzj0+TVgjq/mpUXXzSgKzMS82YByi4dY2Q808njcBCyy6tQ== @@ -2013,7 +2013,7 @@ "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5": +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== @@ -2152,7 +2152,7 @@ "@svgr/babel-plugin-transform-react-native-svg" "8.1.0" "@svgr/babel-plugin-transform-svg-component" "8.0.0" -"@svgr/core@*", "@svgr/core@8.1.0": +"@svgr/core@8.1.0": version "8.1.0" resolved "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz" integrity sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA== @@ -2473,7 +2473,7 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react@*", "@types/react@>= 16.8.0 < 19.0.0", "@types/react@>=16", "@types/react@>=18": +"@types/react@*": version "18.3.18" resolved "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz" integrity sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ== @@ -2558,7 +2558,7 @@ resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== -"@webassemblyjs/ast@^1.14.1", "@webassemblyjs/ast@1.14.1": +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz" integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== @@ -2659,7 +2659,7 @@ "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/wasm-parser" "1.14.1" -"@webassemblyjs/wasm-parser@^1.14.1", "@webassemblyjs/wasm-parser@1.14.1": +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": version "1.14.1" resolved "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz" integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== @@ -2709,7 +2709,7 @@ acorn-walk@^8.0.0: dependencies: acorn "^8.11.0" -"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.0.0, acorn@^8.0.4, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.8.2: +acorn@^8.0.0, acorn@^8.0.4, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.8.2: version "8.14.0" resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -2734,12 +2734,7 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv-keywords@^3.4.1: - version "3.5.2" - resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - -ajv-keywords@^3.5.2: +ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== @@ -2751,7 +2746,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.12.2, ajv@^6.12.5, ajv@^6.9.1: +ajv@^6.12.2, ajv@^6.12.5: version "6.12.6" resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -2761,7 +2756,7 @@ ajv@^6.12.2, ajv@^6.12.5, ajv@^6.9.1: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.0.0, ajv@^8.8.2, ajv@^8.9.0: +ajv@^8.0.0, ajv@^8.9.0: version "8.17.1" resolved "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz" integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== @@ -2778,7 +2773,7 @@ algoliasearch-helper@^3.22.6: dependencies: "@algolia/events" "^4.0.1" -algoliasearch@^5.14.2, algoliasearch@^5.17.1, "algoliasearch@>= 3.1 < 6", "algoliasearch@>= 4.9.1 < 6": +algoliasearch@^5.14.2, algoliasearch@^5.17.1: version "5.20.0" resolved "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.20.0.tgz" integrity sha512-groO71Fvi5SWpxjI9Ia+chy0QBwT61mg6yxJV27f5YFf+Mw+STT75K6SHySpP8Co5LsCrtsbCH5dJZSRtkSKaQ== @@ -3045,7 +3040,7 @@ braces@^3.0.3, braces@~3.0.2: dependencies: fill-range "^7.1.1" -browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.23.0, browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3, "browserslist@>= 4.21.0": +browserslist@^4.0.0, browserslist@^4.18.1, browserslist@^4.23.0, browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0, browserslist@^4.24.3: version "4.24.4" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -3708,27 +3703,20 @@ debounce@^1.2.1: resolved "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz" integrity sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug== -debug@^2.6.0: +debug@2.6.9, debug@^2.6.0: version "2.6.9" resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@4: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.4.0" resolved "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz" integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== dependencies: ms "^2.1.3" -debug@2.6.9: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - decode-named-character-reference@^1.0.0: version "1.0.2" resolved "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz" @@ -3802,16 +3790,16 @@ del@^6.1.1: rimraf "^3.0.2" slash "^3.0.0" -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" - integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== - depd@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz" + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== + dequal@^2.0.0: version "2.0.3" resolved "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz" @@ -4366,7 +4354,7 @@ figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" -file-loader@*, file-loader@^6.2.0: +file-loader@^6.2.0: version "6.2.0" resolved "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz" integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== @@ -4591,14 +4579,7 @@ glob-parent@^5.1.2, glob-parent@~5.1.2: dependencies: is-glob "^4.0.1" -glob-parent@^6.0.1: - version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" - integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== - dependencies: - is-glob "^4.0.3" - -glob-parent@^6.0.2: +glob-parent@^6.0.1, glob-parent@^6.0.2: version "6.0.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -4707,16 +4688,16 @@ got@^12.1.0: p-cancelable "^3.0.0" responselike "^3.0.0" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: - version "4.2.11" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graceful-fs@4.2.10: version "4.2.10" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.11" + resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + gray-matter@^4.0.3: version "4.0.3" resolved "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz" @@ -5008,16 +4989,6 @@ http-deceiver@^1.2.7: resolved "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz" integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== -http-errors@~1.6.2: - version "1.6.3" - resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" - integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.0" - statuses ">= 1.4.0 < 2" - http-errors@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz" @@ -5029,6 +5000,16 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz" + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + http-parser-js@>=0.5.1: version "0.5.9" resolved "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.9.tgz" @@ -5132,7 +5113,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3, inherits@2, inherits@2.0.4: +inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: version "2.0.4" resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -5142,16 +5123,16 @@ inherits@2.0.3: resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz" integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.8" - resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" - integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== - ini@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz" integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA== +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: + version "1.3.8" + resolved "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + inline-style-parser@0.2.4: version "0.2.4" resolved "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz" @@ -5169,16 +5150,16 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -ipaddr.js@^2.0.1: - version "2.2.0" - resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz" - integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== - ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +ipaddr.js@^2.0.1: + version "2.2.0" + resolved "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz" + integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== + is-alphabetical@^2.0.0: version "2.0.1" resolved "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz" @@ -5342,16 +5323,16 @@ is-yarn-global@^0.4.0: resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.4.1.tgz" integrity sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ== -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isarray@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz" integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + isexe@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" @@ -6339,6 +6320,11 @@ micromatch@^4.0.2, micromatch@^4.0.5, micromatch@^4.0.8: braces "^3.0.3" picomatch "^2.3.1" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + "mime-db@>= 1.43.0 < 2": version "1.53.0" resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz" @@ -6349,40 +6335,14 @@ mime-db@~1.33.0: resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz" integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.27: - version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime-types@^2.1.31: - version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime-types@~2.1.17, mime-types@2.1.18: +mime-types@2.1.18, mime-types@~2.1.17: version "2.1.18" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz" integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== dependencies: mime-db "~1.33.0" -mime-types@~2.1.24: - version "2.1.35" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -mime-types@~2.1.34: +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -6422,7 +6382,7 @@ minimalistic-assert@^1.0.0: resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@3.1.2: +minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -6463,16 +6423,16 @@ mrmime@^2.0.0: resolved "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz" integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== -ms@^2.1.3, ms@2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - ms@2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== +ms@2.1.3, ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + multicast-dns@^7.2.5: version "7.2.5" resolved "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz" @@ -6495,16 +6455,16 @@ nanoid@^3.3.8: resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz" integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== -negotiator@~0.6.4: - version "0.6.4" - resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz" - integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@~0.6.4: + version "0.6.4" + resolved "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + neo-async@^2.6.2: version "2.6.2" resolved "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz" @@ -6853,13 +6813,6 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" -path-to-regexp@^1.7.0: - version "1.9.0" - resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz" - integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== - dependencies: - isarray "0.0.1" - path-to-regexp@0.1.12: version "0.1.12" resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz" @@ -6870,6 +6823,13 @@ path-to-regexp@3.3.0: resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz" integrity sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw== +path-to-regexp@^1.7.0: + version "1.9.0" + resolved "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== + dependencies: + isarray "0.0.1" + path-type@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" @@ -7496,7 +7456,7 @@ postcss-zindex@^6.0.2: resolved "https://registry.npmjs.org/postcss-zindex/-/postcss-zindex-6.0.2.tgz" integrity sha512-5BxW9l1evPB/4ZIc+2GobEBoKC+h8gPGCMi+jxsYvd2x0mjq7wazk6DrP71pStqxE9Foxh5TVnonbWpFZzXaYg== -"postcss@^7.0.0 || ^8.0.1", postcss@^8, postcss@^8.0.0, postcss@^8.0.3, postcss@^8.0.9, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.2.2, postcss@^8.4, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.31, postcss@^8.4.33, postcss@^8.4.35, postcss@^8.4.38, postcss@^8.4.47, postcss@^8.4.6, postcss@>=8.0.9: +postcss@^8.4.21, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4.33, postcss@^8.4.35, postcss@^8.4.38, postcss@^8.4.47: version "8.5.2" resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.2.tgz" integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA== @@ -7614,21 +7574,16 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -range-parser@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - range-parser@1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz" integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + raw-body@2.5.2: version "2.5.2" resolved "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz" @@ -7679,7 +7634,7 @@ react-dev-utils@^12.0.1: strip-ansi "^6.0.1" text-table "^0.2.0" -react-dom@*, "react-dom@^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18.0.0 || ^19.0.0", react-dom@^19.0.0, "react-dom@>= 16.8.0 < 19.0.0": +react-dom@^19.0.0: version "19.0.0" resolved "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz" integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== @@ -7724,7 +7679,7 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: dependencies: "@babel/runtime" "^7.10.3" -react-loadable@*, "react-loadable@npm:@docusaurus/react-loadable@6.0.0": +"react-loadable@npm:@docusaurus/react-loadable@6.0.0": version "6.0.0" resolved "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz" integrity sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ== @@ -7768,7 +7723,7 @@ react-router-dom@^5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@^5.3.4, react-router@>=5, react-router@5.3.4: +react-router@5.3.4, react-router@^5.3.4: version "5.3.4" resolved "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz" integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== @@ -7783,7 +7738,7 @@ react-router@^5.3.4, react-router@>=5, react-router@5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react@*, "react@^16.13.1 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.6.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18.0.0 || ^19.0.0", react@^19.0.0, "react@>= 16.8.0 < 19.0.0", react@>=15, react@>=16, react@>=16.0.0, react@>=18: +react@^19.0.0: version "19.0.0" resolved "https://registry.npmjs.org/react/-/react-19.0.0.tgz" integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== @@ -8145,7 +8100,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.1.0, safe-buffer@>=5.1.0, safe-buffer@~5.2.0, safe-buffer@5.2.1: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -8170,16 +8125,16 @@ scheduler@^0.25.0: resolved "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz" integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== -schema-utils@^3.0.0: - version "3.3.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== +schema-utils@2.7.0: + version "2.7.0" + resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" + integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" + "@types/json-schema" "^7.0.4" + ajv "^6.12.2" + ajv-keywords "^3.4.1" -schema-utils@^3.2.0: +schema-utils@^3.0.0, schema-utils@^3.2.0: version "3.3.0" resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -8198,20 +8153,6 @@ schema-utils@^4.0.0, schema-utils@^4.0.1, schema-utils@^4.3.0: ajv-formats "^2.1.1" ajv-keywords "^5.1.0" -schema-utils@2.7.0: - version "2.7.0" - resolved "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz" - integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A== - dependencies: - "@types/json-schema" "^7.0.4" - ajv "^6.12.2" - ajv-keywords "^3.4.1" - -"search-insights@>= 1 < 3": - version "2.17.3" - resolved "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz" - integrity sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ== - section-matter@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz" @@ -8498,7 +8439,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0: +source-map@^0.6.0, source-map@~0.6.0: version "0.6.1" resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -8508,11 +8449,6 @@ source-map@^0.7.0: resolved "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz" integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== -source-map@~0.6.0: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - space-separated-tokens@^2.0.0: version "2.0.2" resolved "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz" @@ -8551,35 +8487,21 @@ srcset@^4.0.0: resolved "https://registry.npmjs.org/srcset/-/srcset-4.0.0.tgz" integrity sha512-wvLeHgcVHKO8Sc/H/5lkGreJQVeYMm9rlmt8PuR1xE31rIuXhuzznUUqAt8MqLhB3MqJdFzlNAfpcWnxiFUcPw== -"statuses@>= 1.4.0 < 2": - version "1.5.0" - resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" - integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== - statuses@2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== + std-env@^3.7.0: version "3.8.0" resolved "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz" integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== -string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" @@ -8589,16 +8511,7 @@ string_decoder@~1.1.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^4.1.0: - version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.2.0: +string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8616,6 +8529,20 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + stringify-entities@^4.0.0: version "4.0.4" resolved "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz" @@ -8909,7 +8836,7 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -"typescript@>= 2.7", typescript@>=4.9.5, typescript@~5.6.2: +typescript@~5.6.2: version "5.6.3" resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz" integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw== @@ -9017,7 +8944,7 @@ universalify@^2.0.0: resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz" integrity sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw== -unpipe@~1.0.0, unpipe@1.0.0: +unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== @@ -9233,7 +9160,7 @@ webpack-sources@^3.2.3: resolved "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -"webpack@^4.0.0 || ^5.0.0", "webpack@^4.37.0 || ^5.0.0", webpack@^5.0.0, webpack@^5.1.0, webpack@^5.20.0, webpack@^5.88.1, webpack@^5.95.0, "webpack@>= 4", "webpack@>=4.41.1 || 5.x", webpack@>=5, "webpack@3 || 4 || 5": +webpack@^5.88.1, webpack@^5.95.0: version "5.97.1" resolved "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz" integrity sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg== @@ -9276,7 +9203,7 @@ webpackbar@^6.0.1: std-env "^3.7.0" wrap-ansi "^7.0.0" -websocket-driver@^0.7.4, websocket-driver@>=0.5.1: +websocket-driver@>=0.5.1, websocket-driver@^0.7.4: version "0.7.4" resolved "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz" integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== diff --git a/ui/desktop/src/components/settings_v2/SettingsView.tsx b/ui/desktop/src/components/settings_v2/SettingsView.tsx index f670cdbaee2b..b6a5bd7d3dec 100644 --- a/ui/desktop/src/components/settings_v2/SettingsView.tsx +++ b/ui/desktop/src/components/settings_v2/SettingsView.tsx @@ -4,6 +4,7 @@ import type { View, ViewOptions } from '../../App'; import ExtensionsSection from './extensions/ExtensionsSection'; import ModelsSection from './models/ModelsSection'; import { ModeSection } from './mode/ModeSection'; +import { ToolSelectionStrategySection } from './tool_selection_strategy/ToolSelectionStrategySection'; import SessionSharingSection from './sessions/SessionSharingSection'; import { ResponseStylesSection } from './response_styles/ResponseStylesSection'; import { ExtensionConfig } from '../../api'; @@ -50,6 +51,8 @@ export default function SettingsView({ {/* Response Styles */} + {/* Tool Selection Strategy */} + diff --git a/ui/desktop/src/components/settings_v2/tool_selection_strategy/ToolSelectionStrategySection.tsx b/ui/desktop/src/components/settings_v2/tool_selection_strategy/ToolSelectionStrategySection.tsx new file mode 100644 index 000000000000..b6cb85f40571 --- /dev/null +++ b/ui/desktop/src/components/settings_v2/tool_selection_strategy/ToolSelectionStrategySection.tsx @@ -0,0 +1,101 @@ +import { useEffect, useState, useCallback } from 'react'; +import { View, ViewOptions } from '../../../App'; +import { useConfig } from '../../ConfigContext'; + +interface ToolSelectionStrategySectionProps { + setView: (view: View, viewOptions?: ViewOptions) => void; +} + +export const all_tool_selection_strategies = [ + { + key: 'default', + label: 'Default', + description: 'Loads all tools from enabled extensions', + }, + { + key: 'vector', + label: 'Vector', + description: + 'Filter tools based on vector-based similarity. Recommended when many extensions are enabled.', + }, +]; + +export const ToolSelectionStrategySection = ({ + setView: _setView, +}: ToolSelectionStrategySectionProps) => { + const [currentStrategy, setCurrentStrategy] = useState('default'); + const { read, upsert } = useConfig(); + + const handleStrategyChange = async (newStrategy: string) => { + try { + await upsert('GOOSE_ROUTER_TOOL_SELECTION_STRATEGY', newStrategy, false); + setCurrentStrategy(newStrategy); + } catch (error) { + console.error('Error updating tool selection strategy:', error); + throw new Error(`Failed to store new tool selection strategy: ${newStrategy}`); + } + }; + + const fetchCurrentStrategy = useCallback(async () => { + try { + const strategy = (await read('GOOSE_ROUTER_TOOL_SELECTION_STRATEGY', false)) as string; + if (strategy) { + setCurrentStrategy(strategy); + } + } catch (error) { + console.error('Error fetching current tool selection strategy:', error); + } + }, [read]); + + useEffect(() => { + fetchCurrentStrategy(); + }, [fetchCurrentStrategy]); + + return ( +
+
+

Tool Selection Strategy (preview)

+
+
+

+ Configure how Goose selects tools for your requests. Available only with Claude models + served on Databricks. +

+
+ {all_tool_selection_strategies.map((strategy) => ( +
+
handleStrategyChange(strategy.key)} + > +
+
+

{strategy.label}

+

{strategy.description}

+
+
+ +
+ handleStrategyChange(strategy.key)} + className="peer sr-only" + /> +
+
+
+
+ ))} +
+
+
+ ); +};