From f2aa48d2ec0846ce863b2549914a8b0e1b7e2ab9 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Thu, 2 Jul 2026 19:59:16 +0200 Subject: [PATCH 1/4] try to use local ai to generate commit message --- .claude/settings.local.json | 16 +- .gitignore | 3 +- src-tauri/Cargo.lock | 3569 ++++++++++++++++++++++++- src-tauri/Cargo.toml | 11 +- src-tauri/crates/commit_ai/Cargo.toml | 10 + src-tauri/crates/commit_ai/src/lib.rs | 157 ++ src-tauri/src/git.rs | 32 + src-tauri/src/main.rs | 28 +- src/App.svelte | 55 +- src/app.css | 2 + src/lib/components/CommitPanel.svelte | 52 +- src/lib/git.ts | 9 + src/lib/types.ts | 7 + 13 files changed, 3889 insertions(+), 62 deletions(-) create mode 100644 src-tauri/crates/commit_ai/Cargo.toml create mode 100644 src-tauri/crates/commit_ai/src/lib.rs diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 0817c64..3356e50 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -34,7 +34,21 @@ "Read(//mnt/c/Users/cbr/Desktop/src-tauri/src/**)", "Bash(sudo apt install -y libdbus-1-dev pkg-config)", "Bash(dpkg -l)", - "Bash(apt list *)" + "Bash(apt list *)", + "Bash(cargo search *)", + "Bash(curl -s \"https://crates.io/api/v1/crates/mistralrs\")", + "Bash(cargo info *)", + "WebFetch(domain:raw.githubusercontent.com)", + "Bash(gh api *)", + "WebFetch(domain:github.com)", + "WebFetch(domain:ericlbuehler.github.io)", + "WebFetch(domain:docs.rs)", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-1.5B-Instruct-GGUF\")", + "Bash(python3 -c ' *)", + "Bash(curl -sI \"https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct-GGUF/resolve/main/qwen2.5-1.5b-instruct-q4_k_m.gguf\")", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-1.5B-Instruct-GGUF?blobs=true\")", + "Bash(grep -n 'from \"\\\\./lib/git\"\\\\|from \"\\\\./lib/types\"\\\\|^ commit,$' src/App.svelte)", + "Bash(kill 24343 24363 24375 24376)" ] } } diff --git a/.gitignore b/.gitignore index 035e28c..7cf1ea8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ .idea .DS_Store ~ -.codex* \ No newline at end of file +.codex* +target diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 749251e..945e55a 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1,6 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] [[package]] name = "adler2" @@ -19,6 +29,20 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "serde", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -28,6 +52,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "akin" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763692fc1416554cf051efc56a3de5595eca47299d731cc5c2b583adf8b4d2f" + +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + [[package]] name = "alloc-no-stdlib" version = "2.0.4" @@ -43,6 +91,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -52,12 +106,88 @@ dependencies = [ "libc", ] +[[package]] +name = "annotate-snippets" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" +dependencies = [ + "anstyle", + "memchr", + "unicode-width", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.61.2", +] + [[package]] name = "anyhow" version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "apodize" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fca387cdc0a1f9c7a7c26556d584aa2d07fc529843082e4861003cde4ab914ed" + +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arbitrary" version = "1.4.2" @@ -67,6 +197,44 @@ dependencies = [ "derive_arbitrary", ] +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "arraydeque" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" + +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + +[[package]] +name = "as-any" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" + +[[package]] +name = "as-slice" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "async-broadcast" version = "0.7.2" @@ -244,6 +412,78 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.18", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "aws-lc-rs" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4342d8937fc7e5dd9b1c60292261c0670c882a2cd1719cfc11b1af41731e32ad" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.42.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9ceb1da931507a12f4fccea479dccd00da1943e1b4ae72d8e502d707361444" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -256,21 +496,42 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec 0.6.3", +] + [[package]] name = "bit-set" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", ] +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + [[package]] name = "bit-vec" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -286,6 +547,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -326,6 +596,20 @@ dependencies = [ "piper", ] +[[package]] +name = "bm25" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cbd8ffdfb7b4c2ff038726178a780a94f90525ed0ad264c0afaa75dd8c18a64" +dependencies = [ + "cached", + "deunicode", + "fxhash", + "rust-stemmers", + "stop-words", + "unicode-segmentation", +] + [[package]] name = "brotli" version = "8.0.4" @@ -356,6 +640,23 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "bstr" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" +dependencies = [ + "memchr", + "regex-automata", + "serde_core", +] + +[[package]] +name = "built" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" + [[package]] name = "bumpalo" version = "3.20.3" @@ -367,6 +668,20 @@ name = "bytemuck" version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] [[package]] name = "byteorder" @@ -374,6 +689,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.12.0" @@ -383,6 +704,39 @@ dependencies = [ "serde", ] +[[package]] +name = "cached" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801927ee168e17809ab8901d9f01f700cd7d8d6a6527997fee44e4b0327a253c" +dependencies = [ + "ahash", + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.15.5", + "once_cell", + "thiserror 2.0.18", + "web-time", +] + +[[package]] +name = "cached_proc_macro" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9225bdcf4e4a9a4c08bf16607908eb2fbf746828d5e0b5e019726dbf6571f201" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" + [[package]] name = "cairo-rs" version = "0.18.5" @@ -417,6 +771,46 @@ dependencies = [ "serde_core", ] +[[package]] +name = "candle-core" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd9895436c1ba5dc1037a19935d084b838db066ff4e15ef7dded020b7c12a4a" +dependencies = [ + "byteorder", + "float8", + "gemm", + "half", + "libm", + "memmap2", + "num-traits", + "num_cpus", + "rand 0.9.4", + "rand_distr 0.5.1", + "rayon", + "safetensors", + "thiserror 2.0.18", + "tokenizers 0.22.2", + "yoke", + "zip 7.2.0", +] + +[[package]] +name = "candle-nn" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9317a09d6530b758990ed7f625ac69ff43653bc9ee28b0464644ad1169ada87" +dependencies = [ + "candle-core", + "half", + "libc", + "num-traits", + "rayon", + "safetensors", + "serde", + "thiserror 2.0.18", +] + [[package]] name = "cargo-platform" version = "0.1.9" @@ -450,6 +844,15 @@ dependencies = [ "toml 0.9.12+spec-1.1.0", ] +[[package]] +name = "castaway" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" +dependencies = [ + "rustversion", +] + [[package]] name = "cbc" version = "0.1.2" @@ -466,6 +869,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -483,7 +888,7 @@ checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" dependencies = [ "byteorder", "fnv", - "uuid", + "uuid 1.23.4", ] [[package]] @@ -492,7 +897,7 @@ version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ - "smallvec", + "smallvec 1.15.2", "target-lexicon", ] @@ -508,6 +913,20 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "cfgrammar" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5ef80386dea3cda50570f22e1c6a474f0cc688ae220fc584fef354acaf41f2b" +dependencies = [ + "indexmap 2.14.0", + "num-traits", + "proc-macro2", + "quote", + "regex", + "vob", +] + [[package]] name = "chrono" version = "0.4.45" @@ -515,8 +934,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-link 0.2.1", ] @@ -530,6 +951,68 @@ dependencies = [ "inout", ] +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim 0.11.1", + "terminal_size", +] + +[[package]] +name = "clap_derive" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "combine" version = "4.6.7" @@ -540,6 +1023,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "commit_ai" +version = "0.1.0" +dependencies = [ + "mistralrs", + "serde", + "tokio", +] + +[[package]] +name = "compact_str" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "serde", + "static_assertions", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -549,6 +1056,31 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "console" +version = "0.15.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "console" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width", + "windows-sys 0.61.2", +] + [[package]] name = "cookie" version = "0.18.1" @@ -636,12 +1168,62 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crossterm" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" +dependencies = [ + "bitflags 1.3.2", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" +dependencies = [ + "winapi", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -662,7 +1244,7 @@ dependencies = [ "dtoa-short", "itoa", "phf", - "smallvec", + "smallvec 1.15.2", ] [[package]] @@ -675,6 +1257,27 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "csv" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" +dependencies = [ + "csv-core", + "itoa", + "ryu", + "serde_core", +] + +[[package]] +name = "csv-core" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" +dependencies = [ + "memchr", +] + [[package]] name = "ctor" version = "0.8.0" @@ -691,14 +1294,62 @@ version = "0.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52560adf09603e58c9a7ee1fe1dcb95a16927b17c127f0ac02d6e768a0e25bc1" +[[package]] +name = "darling" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbffa8f8e38810422f320ca457a93cf1cd0056dc9c06c556b867558e0d471463" +dependencies = [ + "darling_core 0.11.0", + "darling_macro 0.11.0", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + [[package]] name = "darling" version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.23.0", + "darling_macro 0.23.0", +] + +[[package]] +name = "darling_core" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e172685d94b7b83800e3256a63261537b9d6129e10f21c8e13ddf9dba8c64d" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.11.1", + "syn 2.0.118", ] [[package]] @@ -710,7 +1361,29 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.11.1", + "syn 2.0.118", +] + +[[package]] +name = "darling_macro" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0618ac802792cebd1918ac6042a6ea1eeab92db34b35656afaa577929820788" +dependencies = [ + "darling_core 0.11.0", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core 0.20.11", + "quote", "syn 2.0.118", ] @@ -720,11 +1393,26 @@ version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "darling_core", + "darling_core 0.23.0", "quote", "syn 2.0.118", ] +[[package]] +name = "dary_heap" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" +dependencies = [ + "serde", +] + +[[package]] +name = "data-encoding" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" + [[package]] name = "dbus" version = "0.9.11" @@ -754,6 +1442,12 @@ dependencies = [ "zeroize", ] +[[package]] +name = "defmac" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafbece59594ed57696a1a69e8bb3ca1683fbc9cdb41d5c02726070b2cd8f19d" + [[package]] name = "deranged" version = "0.5.8" @@ -763,6 +1457,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "derive_arbitrary" version = "1.4.2" @@ -774,6 +1479,37 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "derive_builder" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" +dependencies = [ + "darling 0.20.11", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" +dependencies = [ + "derive_builder_core", + "syn 2.0.118", +] + [[package]] name = "derive_more" version = "2.1.1" @@ -795,6 +1531,26 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "derivre" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a892ec3953f4ca893e8d2086ed03d4b58e19c77ffb864a574b332d7d40c175f3" +dependencies = [ + "anyhow", + "bytemuck", + "bytemuck_derive", + "hashbrown 0.17.1", + "regex-syntax", + "strum 0.28.0", +] + +[[package]] +name = "deunicode" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" + [[package]] name = "digest" version = "0.10.7" @@ -873,19 +1629,25 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "doctest-file" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2db04e74f0a9a93103b50e90b96024c9b2bdca8bce6a632ec71b88736d3d359" + [[package]] name = "dom_query" version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521e380c0c8afb8d9a1e83a1822ee03556fc3e3e7dbc1fd30be14e37f9cb3f89" dependencies = [ - "bit-set", + "bit-set 0.8.0", "cssparser", - "foldhash", - "html5ever", + "foldhash 0.2.0", + "html5ever 0.38.0", "precomputed-hash", - "selectors", - "tendril", + "selectors 0.36.1", + "tendril 0.5.0", ] [[package]] @@ -939,6 +1701,37 @@ version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +[[package]] +name = "dyn-stack" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4713e43e2886ba72b8271aa66c93d722116acf7a75555cce11dcde84388fe8" +dependencies = [ + "bytemuck", + "dyn-stack-macros", +] + +[[package]] +name = "dyn-stack-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d926b4d407d372f141f93bb444696142c29d32962ccbd3531117cf3aa0bfa9" + +[[package]] +name = "ego-tree" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" +dependencies = [ + "serde", +] + [[package]] name = "embed-resource" version = "3.0.9" @@ -959,12 +1752,54 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "encoding_rs_io" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cc3c5651fb62ab8aa3103998dade57efdd028544bd300516baa31840c252a83" +dependencies = [ + "encoding_rs", +] + [[package]] name = "endi" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099" +[[package]] +name = "endian-type" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "869b0adbda23651a9c5c0c3d270aac9fcb52e8622a8f2b17e57802d7791962f2" + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "enumflags2" version = "0.7.12" @@ -986,6 +1821,26 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -1013,6 +1868,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "esaxx-rs" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d817e038c30374a4bcb22f94d0a8a0e216958d4c3dcde369b1439fec4bdda6e6" + [[package]] name = "event-listener" version = "5.4.1" @@ -1034,12 +1895,61 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "exr" +version = "1.74.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec 1.15.2", + "zune-inflate", +] + +[[package]] +name = "extended" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" + +[[package]] +name = "fancy-regex" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +dependencies = [ + "bit-set 0.5.3", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +dependencies = [ + "bit-set 0.8.0", + "regex-automata", + "regex-syntax", +] + [[package]] name = "fastrand" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + [[package]] name = "fdeflate" version = "0.3.7" @@ -1085,12 +1995,30 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float8" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d1f04709a8ac06e8e8042875a3c466cc4832d3c1a18dbcb9dba3c6e83046bc" +dependencies = [ + "half", + "num-traits", + "rand 0.9.4", + "rand_distr 0.5.1", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foldhash" version = "0.2.0" @@ -1133,6 +2061,37 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.32" @@ -1140,6 +2099,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -1207,6 +2167,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1217,6 +2178,25 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "galil-seiferas" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "794ac25cfda3fa11d2b07ff8c65889c6c03411646df54e59e606878d899e1d5a" +dependencies = [ + "defmac", + "unchecked-index", +] + [[package]] name = "gdk" version = "0.18.2" @@ -1316,6 +2296,125 @@ dependencies = [ "x11", ] +[[package]] +name = "gemm" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa0673db364b12263d103b68337a68fbecc541d6f6b61ba72fe438654709eacb" +dependencies = [ + "dyn-stack", + "gemm-c32", + "gemm-c64", + "gemm-common", + "gemm-f16", + "gemm-f32", + "gemm-f64", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c32" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "086936dbdcb99e37aad81d320f98f670e53c1e55a98bee70573e83f95beb128c" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-c64" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c8aeeeec425959bda4d9827664029ba1501a90a0d1e6228e48bef741db3a3f" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-common" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88027625910cc9b1085aaaa1c4bc46bb3a36aad323452b33c25b5e4e7c8e2a3e" +dependencies = [ + "bytemuck", + "dyn-stack", + "half", + "libm", + "num-complex", + "num-traits", + "once_cell", + "paste", + "pulp", + "raw-cpuid", + "rayon", + "seq-macro", + "sysctl", +] + +[[package]] +name = "gemm-f16" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3df7a55202e6cd6739d82ae3399c8e0c7e1402859b30e4cb780e61525d9486e" +dependencies = [ + "dyn-stack", + "gemm-common", + "gemm-f32", + "half", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "rayon", + "seq-macro", +] + +[[package]] +name = "gemm-f32" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e0b8c9da1fbec6e3e3ab2ce6bc259ef18eb5f6f0d3e4edf54b75f9fd41a81c" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + +[[package]] +name = "gemm-f64" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056131e8f2a521bfab322f804ccd652520c79700d81209e9d9275bbdecaadc6a" +dependencies = [ + "dyn-stack", + "gemm-common", + "num-complex", + "num-traits", + "paste", + "raw-cpuid", + "seq-macro", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1326,6 +2425,15 @@ dependencies = [ "version_check", ] +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.17" @@ -1333,8 +2441,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi", + "wasm-bindgen", ] [[package]] @@ -1344,9 +2454,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -1360,6 +2472,16 @@ dependencies = [ "r-efi 6.0.0", ] +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "gio" version = "0.18.4" @@ -1375,7 +2497,7 @@ dependencies = [ "libc", "once_cell", "pin-project-lite", - "smallvec", + "smallvec 1.15.2", "thiserror 1.0.69", ] @@ -1396,6 +2518,7 @@ dependencies = [ name = "git_lite" version = "0.1.0" dependencies = [ + "commit_ai", "keyring", "serde", "serde_json", @@ -1424,7 +2547,7 @@ dependencies = [ "libc", "memchr", "once_cell", - "smallvec", + "smallvec 1.15.2", "thiserror 1.0.69", ] @@ -1521,12 +2644,70 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "h2" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.14.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "bytemuck", + "cfg-if", + "crunchy", + "num-traits", + "rand 0.9.4", + "rand_distr 0.5.1", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", + "serde", + "serde_core", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -1557,6 +2738,29 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hf-hub" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "629d8f3bbeda9d148036d6b0de0a3ab947abd08ce90626327fc3547a49d59d97" +dependencies = [ + "dirs", + "futures", + "http", + "indicatif 0.17.11", + "libc", + "log", + "num_cpus", + "rand 0.9.4", + "reqwest 0.12.28", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "ureq", + "windows-sys 0.60.2", +] + [[package]] name = "hkdf" version = "0.12.4" @@ -1575,6 +2779,34 @@ dependencies = [ "digest", ] +[[package]] +name = "hound" +version = "3.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" + +[[package]] +name = "html2text" +version = "0.16.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12d23156ea4dbe6b37ad48fab2da56ff27b0f6192fb5db210c44eb07bfe6e787" +dependencies = [ + "html5ever 0.38.0", + "tendril 0.5.0", + "thiserror 2.0.18", + "unicode-width", +] + +[[package]] +name = "html5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6452c4751a24e1b99c3260d505eaeee76a050573e61f30ac2c924ddc7236f01e" +dependencies = [ + "log", + "markup5ever 0.36.1", +] + [[package]] name = "html5ever" version = "0.38.0" @@ -1582,7 +2814,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1054432bae2f14e0061e33d23402fbaa67a921d319d56adc6bcf887ddad1cbc2" dependencies = [ "log", - "markup5ever", + "markup5ever 0.38.0", ] [[package]] @@ -1634,12 +2866,13 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2", "http", "http-body", "httparse", "itoa", "pin-project-lite", - "smallvec", + "smallvec 1.15.2", "tokio", "want", ] @@ -1657,6 +2890,7 @@ dependencies = [ "tokio", "tokio-rustls", "tower-service", + "webpki-roots 1.0.8", ] [[package]] @@ -1677,9 +2911,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -1753,7 +2989,7 @@ dependencies = [ "icu_normalizer_data", "icu_properties", "icu_provider", - "smallvec", + "smallvec 1.15.2", "zerovec", ] @@ -1811,7 +3047,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ "idna_adapter", - "smallvec", + "smallvec 1.15.2", "utf8_iter", ] @@ -1825,6 +3061,46 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7" + [[package]] name = "indexmap" version = "1.9.3" @@ -1848,6 +3124,33 @@ dependencies = [ "serde_core", ] +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console 0.15.11", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "indicatif" +version = "0.18.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" +dependencies = [ + "console 0.16.4", + "portable-atomic", + "rayon", + "unicode-width", + "unit-prefix", + "web-time", +] + [[package]] name = "infer" version = "0.19.0" @@ -1867,12 +3170,51 @@ dependencies = [ "generic-array", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "interprocess" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "069323743400cb7ab06a8fe5c1ed911d36b6919ec531661d034c89083629595b" +dependencies = [ + "doctest-file", + "libc", + "recvmsg", + "widestring", + "windows-sys 0.61.2", +] + [[package]] name = "ipnet" version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.18" @@ -1976,6 +3318,16 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.103" @@ -2037,6 +3389,18 @@ dependencies = [ "zeroize", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libappindicator" version = "0.9.0" @@ -2076,6 +3440,16 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "libfuzzer-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" +dependencies = [ + "arbitrary", + "cc", +] + [[package]] name = "libloading" version = "0.7.4" @@ -2086,6 +3460,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" version = "0.1.17" @@ -2107,6 +3487,21 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "llguidance" +version = "1.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a519d0a437a6cc433edf3db7df98db11fc860a1f57657b84913d51fc670570ff" +dependencies = [ + "anyhow", + "derivre", + "indexmap 2.14.0", + "regex-syntax", + "serde", + "serde_json", + "toktrie", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -2122,6 +3517,67 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "lrtable" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcbe6a005a604615ab7aab7d1f74be563e508f5c6e42f85fbf65c38fe1f5f268" +dependencies = [ + "cfgrammar", + "fnv", + "num-traits", + "sparsevec", + "vob", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "macro_rules_attribute" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65049d7923698040cd0b1ddcced9b0eb14dd22c5f86ae59c3740eab64a676520" +dependencies = [ + "macro_rules_attribute-proc_macro", + "paste", +] + +[[package]] +name = "macro_rules_attribute-proc_macro" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" + +[[package]] +name = "markup5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3294c4d74d0742910f8c7b466f44dda9eb2d5742c1e430138df290a1e8451c" +dependencies = [ + "log", + "tendril 0.4.3", + "web_atoms", +] + [[package]] name = "markup5ever" version = "0.38.0" @@ -2129,16 +3585,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8983d30f2915feeaaab2d6babdd6bc7e9ed1a00b66b5e6d74df19aa9c0e91862" dependencies = [ "log", - "tendril", + "tendril 0.5.0", "web_atoms", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matrixmultiply" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06de3016e9fae57a36fd14dba131fccf49f74b40b7fbdb472f96e361ec71a08" +dependencies = [ + "autocfg", + "rawpointer", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", +] + [[package]] name = "memchr" version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" +[[package]] +name = "memmap2" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1219ed1b7f229ee7104d281dd01d6802fe28bb6e95d292942c4daacdeb798c0" +dependencies = [ + "libc", + "stable_deref_trait", +] + +[[package]] +name = "memo-map" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" + [[package]] name = "memoffset" version = "0.9.1" @@ -2154,6 +3655,43 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minijinja" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3d648e68cea56d9858d535ee28f9538404e2dd8cb08ed0bd05dca379477f39" +dependencies = [ + "memo-map", + "serde", + "serde_json", +] + +[[package]] +name = "minijinja-contrib" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85342f6fac0be8ccd5bd00d9066be538f34f393f577b75d81b17c8398a6b43bb" +dependencies = [ + "minijinja", + "serde", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "minisign-verify" version = "0.2.5" @@ -2170,6 +3708,18 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.2.1" @@ -2181,6 +3731,242 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "mistralrs" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb0a83340b4492ebba9760ba6845364de369c7e10c1f91af8733d574c7405fa" +dependencies = [ + "anyhow", + "candle-core", + "candle-nn", + "clap", + "either", + "futures", + "image", + "indexmap 2.14.0", + "mistralrs-core", + "mistralrs-macros", + "rand 0.9.4", + "reqwest 0.13.4", + "schemars 1.2.1", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", + "tracing-subscriber", + "walkdir", +] + +[[package]] +name = "mistralrs-audio" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ac5d36f634c7c20c45845bc995be3b6387ab01048410386a5b180cfeaf89c72" +dependencies = [ + "anyhow", + "apodize", + "hound", + "symphonia", +] + +[[package]] +name = "mistralrs-core" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b8b9e5c94491d9ceeded3a30291cb6af6ae74810a5776dd55e3bbb8b3429d4" +dependencies = [ + "ahash", + "akin", + "anyhow", + "apodize", + "as-any", + "async-trait", + "base64 0.22.1", + "bm25", + "bytemuck", + "bytemuck_derive", + "candle-core", + "candle-nn", + "cfgrammar", + "chrono", + "clap", + "csv", + "derive-new", + "derive_more", + "dirs", + "either", + "float8", + "futures", + "galil-seiferas", + "half", + "hashbrown 0.16.1", + "hf-hub", + "hound", + "html2text", + "http", + "image", + "indexmap 2.14.0", + "indicatif 0.18.6", + "interprocess", + "itertools", + "libc", + "llguidance", + "lrtable", + "minijinja", + "minijinja-contrib", + "mistralrs-audio", + "mistralrs-mcp", + "mistralrs-quant", + "mistralrs-vision", + "num-traits", + "openai-harmony", + "ordered-float", + "parking_lot", + "radix_trie", + "rand 0.9.4", + "rand_distr 0.5.1", + "rand_isaac", + "rayon", + "regex", + "regex-automata", + "reqwest 0.13.4", + "rubato", + "rust-mcp-schema", + "rustc-hash 2.1.2", + "rustfft", + "safetensors", + "schemars 1.2.1", + "scraper", + "serde", + "serde-big-array", + "serde-saphyr", + "serde_json", + "serde_plain", + "statrs", + "strum 0.27.2", + "symphonia", + "sysinfo", + "thiserror 2.0.18", + "tokenizers 0.21.4", + "tokio", + "tokio-rayon", + "tokio-tungstenite", + "toktrie", + "toktrie_hf_tokenizers", + "toml 0.9.12+spec-1.1.0", + "tqdm", + "tracing", + "tracing-subscriber", + "urlencoding", + "uuid 1.23.4", + "variantly", + "vob", +] + +[[package]] +name = "mistralrs-macros" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa9b4794322d3f89fe61d21f33f67be494c16d5bd869604b111218f32544d32" +dependencies = [ + "darling 0.23.0", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "mistralrs-mcp" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa97d4e3189ed80ebbc730b7da5b2356df0ae004ab489066249340c33c089ab" +dependencies = [ + "anyhow", + "async-trait", + "futures-util", + "http", + "reqwest 0.13.4", + "rust-mcp-schema", + "serde", + "serde_json", + "tokio", + "tokio-tungstenite", + "tracing", + "utoipa", + "uuid 1.23.4", +] + +[[package]] +name = "mistralrs-quant" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "980715493d252e9aaf0779c4c101576d67ef4dd9812bfd77a54987f6f17526f4" +dependencies = [ + "byteorder", + "candle-core", + "candle-nn", + "float8", + "half", + "hf-hub", + "lazy_static", + "memmap2", + "paste", + "rayon", + "regex", + "safetensors", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", + "yoke", +] + +[[package]] +name = "mistralrs-vision" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10046a3da2de5b702d3e829b5ddef7aa829ad454819dcc4876dea481a6cb5456" +dependencies = [ + "candle-core", + "image", + "rayon", +] + +[[package]] +name = "monostate" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3341a273f6c9d5bef1908f17b7267bbab0e95c9bf69a0d4dcf8e9e1b2c76ef67" +dependencies = [ + "monostate-impl", + "serde", + "serde_core", +] + +[[package]] +name = "monostate-impl" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + [[package]] name = "muda" version = "0.19.3" @@ -2202,6 +3988,23 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nalgebra" +version = "0.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d43ddcacf343185dfd6de2ee786d9e8b1c2301622afab66b6c73baf9882abfd" +dependencies = [ + "approx", + "matrixmultiply", + "num-complex", + "num-rational", + "num-traits", + "rand 0.8.6", + "rand_distr 0.4.3", + "simba", + "typenum", +] + [[package]] name = "ndk" version = "0.9.0" @@ -2232,6 +4035,15 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nibble_vec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a5d83df9f36fe23f0c3648c6bbb8b0298bb5f1939c8f2704431371f4b84d43" +dependencies = [ + "smallvec 1.15.2", +] + [[package]] name = "nix" version = "0.29.0" @@ -2245,6 +4057,64 @@ dependencies = [ "memoffset", ] +[[package]] +name = "no_std_io2" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" +dependencies = [ + "memchr", +] + +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "ntapi" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" +dependencies = [ + "winapi", +] + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "num" version = "0.4.3" @@ -2275,6 +4145,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ + "bytemuck", "num-traits", ] @@ -2284,6 +4155,17 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "num-integer" version = "0.1.46" @@ -2322,6 +4204,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", ] [[package]] @@ -2346,6 +4239,12 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "objc2" version = "0.6.4" @@ -2474,6 +4373,16 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "objc2-io-surface" version = "0.3.2" @@ -2560,6 +4469,58 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "onig" +version = "6.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" +dependencies = [ + "bitflags 2.13.0", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7" +dependencies = [ + "cc", + "pkg-config", +] + +[[package]] +name = "openai-harmony" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e77e82af451fc95deeb728a40b84db8ee82d341e136c268de415123a560b9b72" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bstr", + "clap", + "fancy-regex 0.13.0", + "futures", + "image", + "regex", + "reqwest 0.12.28", + "rustc-hash 1.1.0", + "serde", + "serde_json", + "serde_with", + "sha1", + "sha2", + "thiserror 2.0.18", +] + [[package]] name = "openssl-probe" version = "0.2.1" @@ -2572,6 +4533,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7d950ca161dc355eaf28f82b11345ed76c6e1f6eb1f4f4479e0323b9e2fbd0e" +dependencies = [ + "num-traits", +] + [[package]] name = "ordered-stream" version = "0.2.0" @@ -2596,6 +4566,15 @@ dependencies = [ "thiserror 2.0.18", ] +[[package]] +name = "packedvec" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a69e0a534dd2e6aefce319af62a0aa0066a76bdfcec0201dfe02df226bc9ec70" +dependencies = [ + "num-traits", +] + [[package]] name = "pango" version = "0.18.3" @@ -2646,10 +4625,22 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "smallvec", + "smallvec 1.15.2", "windows-link 0.2.1", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2785,6 +4776,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "portable-atomic" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + [[package]] name = "potential_utf" version = "0.1.5" @@ -2815,6 +4812,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "primal-check" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0d895b311e3af9902528fbb8f928688abbd95872819320517cc24ca6b2bd08" +dependencies = [ + "num-integer", +] + [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -2877,6 +4883,69 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.118", +] + +[[package]] +name = "pulp" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", + "reborrow", + "version_check", +] + +[[package]] +name = "pulp-wasm-simd-flag" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" + +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quick-xml" version = "0.39.4" @@ -2886,6 +4955,62 @@ dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.2", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.4", + "ring", + "rustc-hash 2.1.2", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.46" @@ -2907,6 +5032,16 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "radix_trie" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b4431027dcd37fc2a73ef740b5f233aa805897935b8bce0195e41bbf9a3289a" +dependencies = [ + "endian-type", + "nibble_vec", +] + [[package]] name = "rand" version = "0.8.6" @@ -2914,8 +5049,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", - "rand_chacha", - "rand_core", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", ] [[package]] @@ -2925,7 +5070,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -2937,12 +5092,167 @@ dependencies = [ "getrandom 0.2.17", ] +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[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.6", +] + +[[package]] +name = "rand_distr" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" +dependencies = [ + "num-traits", + "rand 0.9.4", +] + +[[package]] +name = "rand_isaac" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3382fc9f0aad4f2e2a56b53d9133c8c810b4dbf21e7e370e24346161a5b2c7bd" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.18", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.13.0", +] + [[package]] name = "raw-window-handle" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-cond" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2964d0cf57a3e7a06e8183d14a8b527195c706b7983549cd5462d5aa3747438f" +dependencies = [ + "either", + "itertools", + "rayon", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "realfft" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f821338fddb99d089116342c46e9f1fbf3828dba077674613e734e01d6ea8677" +dependencies = [ + "rustfft", +] + +[[package]] +name = "reborrow" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" + +[[package]] +name = "recvmsg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3edd4d5d42c92f0a659926464d4cce56b562761267ecf0f469d85b7de384175" + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3014,14 +5324,17 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.13.4" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", + "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", @@ -3030,8 +5343,56 @@ dependencies = [ "hyper-util", "js-sys", "log", + "mime", + "mime_guess", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "webpki-roots 1.0.8", +] + +[[package]] +name = "reqwest" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "percent-encoding", + "pin-project-lite", + "quinn", "rustls", "rustls-pki-types", "rustls-platform-verifier", @@ -3047,7 +5408,7 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", "web-sys", ] @@ -3075,6 +5436,12 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "ring" version = "0.17.14" @@ -3089,6 +5456,44 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rubato" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5258099699851cfd0082aeb645feb9c084d9a5e1f1b8d5372086b989fc5e56a1" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "realfft", +] + +[[package]] +name = "rust-mcp-schema" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1209aa7fb74fccafe6b2a649b15581fb328343427d85def865b0ad233fe1f74" +dependencies = [ + "serde", + "serde_json", +] + +[[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-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.2" @@ -3104,6 +5509,20 @@ dependencies = [ "semver", ] +[[package]] +name = "rustfft" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21db5f9893e91f41798c88680037dba611ca6674703c1a18601b01a72c8adb89" +dependencies = [ + "num-complex", + "num-integer", + "num-traits", + "primal-check", + "strength_reduce", + "transpose", +] + [[package]] name = "rustix" version = "1.1.4" @@ -3123,6 +5542,8 @@ version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ + "aws-lc-rs", + "log", "once_cell", "ring", "rustls-pki-types", @@ -3149,6 +5570,7 @@ version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ + "web-time", "zeroize", ] @@ -3185,6 +5607,7 @@ version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -3196,6 +5619,32 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "safe_arch" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b02de82ddbe1b636e6170c21be622223aea188ef2e139be0a5b219ec215323" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "safetensors" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "675656c1eabb620b921efea4f9199f97fc86e36dd6ffd1fbbe48d0f59a4987f5" +dependencies = [ + "hashbrown 0.16.1", + "serde", + "serde_json", +] + [[package]] name = "same-file" version = "1.0.6" @@ -3205,6 +5654,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "saphyr-parser-bw" +version = "0.0.605" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1aee7486406df3541b5a657204a11be97175a467d77bc98e6d94a66289fb80" +dependencies = [ + "arraydeque", + "smallvec 2.0.0-alpha.12", + "thiserror 2.0.18", +] + [[package]] name = "schannel" version = "0.1.29" @@ -3222,11 +5682,11 @@ checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ "dyn-clone", "indexmap 1.9.3", - "schemars_derive", + "schemars_derive 0.8.22", "serde", "serde_json", "url", - "uuid", + "uuid 1.23.4", ] [[package]] @@ -3249,6 +5709,7 @@ checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", + "schemars_derive 1.2.1", "serde", "serde_json", ] @@ -3265,12 +5726,39 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "schemars_derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.118", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93cecd86d6259499c844440546d02f55f3e17bd286e529e48d1f9f67e92315cb" +dependencies = [ + "cssparser", + "ego-tree", + "getopts", + "html5ever 0.36.1", + "precomputed-hash", + "selectors 0.33.0", + "tendril 0.4.3", +] + [[package]] name = "secret-service" version = "4.0.0" @@ -3284,7 +5772,7 @@ dependencies = [ "hkdf", "num", "once_cell", - "rand", + "rand 0.8.6", "serde", "sha2", "zbus", @@ -3326,6 +5814,25 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feef350c36147532e1b79ea5c1f3791373e61cbd9a6a2615413b3807bb164fb7" +dependencies = [ + "bitflags 2.13.0", + "cssparser", + "derive_more", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "rustc-hash 2.1.2", + "servo_arc", + "smallvec 1.15.2", +] + [[package]] name = "selectors" version = "0.36.1" @@ -3340,9 +5847,9 @@ dependencies = [ "phf", "phf_codegen", "precomputed-hash", - "rustc-hash", + "rustc-hash 2.1.2", "servo_arc", - "smallvec", + "smallvec 1.15.2", ] [[package]] @@ -3355,6 +5862,12 @@ dependencies = [ "serde_core", ] +[[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.228" @@ -3365,6 +5878,35 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[package]] +name = "serde-saphyr" +version = "0.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4db5a4a562bcc0017c34cd0efbabf447be783f00576a2a516947f884e6a7ed57" +dependencies = [ + "ahash", + "annotate-snippets", + "base64 0.22.1", + "encoding_rs_io", + "nohash-hasher", + "num-traits", + "regex", + "saphyr-parser-bw", + "serde", + "serde_json", + "smallvec 2.0.0-alpha.12", + "zmij", +] + [[package]] name = "serde-untagged" version = "0.1.9" @@ -3414,6 +5956,7 @@ version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ + "indexmap 2.14.0", "itoa", "memchr", "serde", @@ -3421,6 +5964,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_plain" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" +dependencies = [ + "serde", +] + [[package]] name = "serde_repr" version = "0.1.20" @@ -3450,6 +6002,18 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + [[package]] name = "serde_with" version = "3.21.0" @@ -3476,7 +6040,7 @@ version = "3.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84d57bc0c8b9a17920c178daa6bb924850d54a9c97ab45194bb8c17ad66bb660" dependencies = [ - "darling", + "darling 0.23.0", "proc-macro2", "quote", "syn 2.0.118", @@ -3535,12 +6099,42 @@ dependencies = [ "digest", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shlex" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" +dependencies = [ + "libc", + "mio 0.8.11", + "signal-hook", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -3551,6 +6145,19 @@ dependencies = [ "libc", ] +[[package]] +name = "simba" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c99284beb21666094ba2b75bbceda012e610f5479dfcc2d6e2426f53197ffd95" +dependencies = [ + "approx", + "num-complex", + "num-traits", + "paste", + "wide", +] + [[package]] name = "simd-adler32" version = "0.3.9" @@ -3567,6 +6174,15 @@ dependencies = [ "simdutf8", ] +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "simdutf8" version = "0.1.5" @@ -3591,6 +6207,12 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "smallvec" +version = "2.0.0-alpha.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef784004ca8777809dcdad6ac37629f0a97caee4c685fcea805278d81dd8b857" + [[package]] name = "socket2" version = "0.6.4" @@ -3601,6 +6223,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "socks" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0c3dbbd9ae980613c6dd8e28a9407b50509d3803b57624d5dfe8315218cd58b" +dependencies = [ + "byteorder", + "libc", + "winapi", +] + [[package]] name = "softbuffer" version = "0.4.8" @@ -3649,6 +6282,29 @@ dependencies = [ "system-deps", ] +[[package]] +name = "sparsevec" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b4a8ce3045f0fe173fb5ae3c6b7dcfbec02bfa650bb8618b2301f52af0134d" +dependencies = [ + "num-traits", + "packedvec", + "vob", +] + +[[package]] +name = "spm_precompiled" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5851699c4033c63636f7ea4cf7b7c1f1bf06d0cc03cfb42e711de5a5c46cf326" +dependencies = [ + "base64 0.13.1", + "nom 7.1.3", + "serde", + "unicode-segmentation", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3661,6 +6317,33 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statrs" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3fe7c28c6512e766b0874335db33c94ad7b8f9054228ae1c2abd47ce7d335e" +dependencies = [ + "approx", + "nalgebra", + "num-traits", + "rand 0.8.6", +] + +[[package]] +name = "stop-words" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645a3d441ccf4bf47f2e4b7681461986681a6eeea9937d4c3bc9febd61d17c71" +dependencies = [ + "serde_json", +] + +[[package]] +name = "strength_reduce" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe895eb47f22e2ddd4dabc02bce419d2e643c8e3b585c78158b349195bc24d82" + [[package]] name = "string_cache" version = "0.9.0" @@ -3685,12 +6368,60 @@ dependencies = [ "quote", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros 0.27.2", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] + +[[package]] +name = "strum_macros" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "subtle" version = "2.6.1" @@ -3708,6 +6439,141 @@ dependencies = [ "serde_json", ] +[[package]] +name = "symphonia" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" +dependencies = [ + "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-ogg", + "symphonia-format-riff", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-bundle-flac" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-bundle-mp3" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" +dependencies = [ + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-codec-pcm" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95" +dependencies = [ + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-codec-vorbis" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73" +dependencies = [ + "log", + "symphonia-core", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] + +[[package]] +name = "symphonia-format-isomp4" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243739585d11f81daf8dac8d9f3d18cc7898f6c09a259675fc364b382c30e0a5" +dependencies = [ + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-ogg" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] + +[[package]] +name = "symphonia-format-riff" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] + +[[package]] +name = "symphonia-metadata" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] + +[[package]] +name = "symphonia-utils-xiph" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] + [[package]] name = "syn" version = "1.0.109" @@ -3715,6 +6581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ "proc-macro2", + "quote", "unicode-ident", ] @@ -3749,6 +6616,55 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "sysctl" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" +dependencies = [ + "bitflags 2.13.0", + "byteorder", + "enum-as-inner", + "libc", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "sysinfo" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + +[[package]] +name = "system-configuration" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" +dependencies = [ + "bitflags 2.13.0", + "core-foundation 0.9.4", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "system-deps" version = "6.2.2" @@ -3860,7 +6776,7 @@ dependencies = [ "percent-encoding", "plist", "raw-window-handle", - "reqwest", + "reqwest 0.13.4", "serde", "serde_json", "serde_repr", @@ -3925,7 +6841,7 @@ dependencies = [ "thiserror 2.0.18", "time", "url", - "uuid", + "uuid 1.23.4", "walkdir", ] @@ -4017,7 +6933,7 @@ dependencies = [ "minisign-verify", "osakit", "percent-encoding", - "reqwest", + "reqwest 0.13.4", "rustls", "semver", "serde", @@ -4031,7 +6947,7 @@ dependencies = [ "tokio", "url", "windows-sys 0.60.2", - "zip", + "zip 4.6.1", ] [[package]] @@ -4119,7 +7035,7 @@ dependencies = [ "toml 1.1.2+spec-1.1.0", "url", "urlpattern", - "uuid", + "uuid 1.23.4", "walkdir", ] @@ -4147,6 +7063,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "tendril" version = "0.5.0" @@ -4157,6 +7084,16 @@ dependencies = [ "utf-8", ] +[[package]] +name = "terminal_size" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" +dependencies = [ + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -4197,6 +7134,29 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + [[package]] name = "time" version = "0.3.51" @@ -4252,6 +7212,72 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokenizers" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a620b996116a59e184c2fa2dfd8251ea34a36d0a514758c6f966386bd2e03476" +dependencies = [ + "ahash", + "aho-corasick", + "compact_str", + "dary_heap", + "derive_builder", + "esaxx-rs", + "fancy-regex 0.14.0", + "getrandom 0.3.4", + "itertools", + "log", + "macro_rules_attribute", + "monostate", + "paste", + "rand 0.9.4", + "rayon", + "rayon-cond", + "regex", + "regex-syntax", + "serde", + "serde_json", + "spm_precompiled", + "thiserror 2.0.18", + "unicode-normalization-alignments", + "unicode-segmentation", + "unicode_categories", +] + +[[package]] +name = "tokenizers" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b238e22d44a15349529690fb07bd645cf58149a1b1e44d6cb5bd1641ff1a6223" +dependencies = [ + "ahash", + "aho-corasick", + "compact_str", + "dary_heap", + "derive_builder", + "esaxx-rs", + "getrandom 0.3.4", + "itertools", + "log", + "macro_rules_attribute", + "monostate", + "onig", + "paste", + "rand 0.9.4", + "rayon", + "rayon-cond", + "regex", + "regex-syntax", + "serde", + "serde_json", + "spm_precompiled", + "thiserror 2.0.18", + "unicode-normalization-alignments", + "unicode-segmentation", + "unicode_categories", +] + [[package]] name = "tokio" version = "1.52.3" @@ -4260,12 +7286,36 @@ checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", - "mio", + "mio 1.2.1", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "tokio-rayon" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cf33a76e0b1dd03b778f83244137bd59887abf25c0e87bc3e7071105f457693" +dependencies = [ + "rayon", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.4" @@ -4276,6 +7326,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -4289,6 +7351,33 @@ dependencies = [ "tokio", ] +[[package]] +name = "toktrie" +version = "1.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "472bdd1540b864dc5654fd49ab2f9182ceb2112b9c0d3710a04136bacca30d4f" +dependencies = [ + "anyhow", + "bytemuck", + "bytemuck_derive", + "serde", + "serde_json", +] + +[[package]] +name = "toktrie_hf_tokenizers" +version = "1.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d198ef73712282678d05249ad65b0a011fcad7996caa26d70978e13ea513fe81" +dependencies = [ + "anyhow", + "log", + "serde", + "serde_json", + "tokenizers 0.21.4", + "toktrie", +] + [[package]] name = "toml" version = "0.8.2" @@ -4454,6 +7543,17 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tqdm" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b316d5c2ac649ca856dacd487d0ebb94f3b746bada51355d93dd2c007ab62a2e" +dependencies = [ + "anyhow", + "crossterm", + "once_cell", +] + [[package]] name = "tracing" version = "0.1.44" @@ -4483,6 +7583,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec 1.15.2", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "transpose" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad61aed86bc3faea4300c7aee358b4c6d0c8d6ccc36524c96e4c92ccf26e77e" +dependencies = [ + "num-integer", + "strength_reduce", ] [[package]] @@ -4513,6 +7653,29 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.4", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typeid" version = "1.0.3" @@ -4536,6 +7699,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "unchecked-index" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeba86d422ce181a719445e51872fa30f1f7413b62becb52e95ec91aa262d85c" + [[package]] name = "unic-char-property" version = "0.9.0" @@ -4577,24 +7746,76 @@ dependencies = [ "unic-common", ] +[[package]] +name = "unicase" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-normalization-alignments" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f613e4fa046e69818dd287fdc4bc78175ff20331479dab6e1b0f98d57062de" +dependencies = [ + "smallvec 1.15.2", +] + [[package]] name = "unicode-segmentation" version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "ureq" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" +dependencies = [ + "base64 0.22.1", + "flate2", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "socks", + "url", + "webpki-roots 0.26.11", +] + [[package]] name = "url" version = "2.5.8" @@ -4608,6 +7829,12 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "urlpattern" version = "0.3.0" @@ -4632,6 +7859,44 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "utoipa" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bde15df68e80b16c7d16b9616e80770ad158988daa56a27dccd1e55558b0160" +dependencies = [ + "indexmap 2.14.0", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "5.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0b99ee52df3028635d93840c797102da61f8a7bb3cf751032455895b52ef8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.118", +] + +[[package]] +name = "uuid" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +dependencies = [ + "getrandom 0.2.17", +] + [[package]] name = "uuid" version = "1.23.4" @@ -4644,6 +7909,37 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "variantly" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72a332341ba79a179d9e9b33c0d72fbf3dc2c80e1be79416401a08d2b820ef56" +dependencies = [ + "Inflector", + "darling 0.11.0", + "proc-macro2", + "quote", + "syn 1.0.109", + "uuid 0.8.2", +] + [[package]] name = "version-compare" version = "0.2.1" @@ -4656,6 +7952,15 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "vob" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc936b5a7202a703aeaf7ce05e7931db2e0c8126813f97db3e9e06d867b0bb38" +dependencies = [ + "num-traits", +] + [[package]] name = "vswhom" version = "0.1.0" @@ -4765,6 +8070,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasm-streams" version = "0.5.0" @@ -4788,6 +8106,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "web_atoms" version = "0.2.5" @@ -4853,6 +8181,24 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.8", +] + +[[package]] +name = "webpki-roots" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf85cb06032201fa7c6f829d7db5a7e5aa45bcc0655327713065f6f0576731bf" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.38.2" @@ -4889,6 +8235,28 @@ dependencies = [ "windows-core 0.61.2", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + +[[package]] +name = "wide" +version = "0.7.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce5da8ecb62bcd8ec8b7ea19f69a51275e91299be594ea5cc6ef7819e16cd03" +dependencies = [ + "bytemuck", + "safe_arch", +] + +[[package]] +name = "widestring" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" + [[package]] name = "winapi" version = "0.3.9" @@ -5038,6 +8406,17 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -5083,6 +8462,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -5134,6 +8522,21 @@ dependencies = [ "windows_x86_64_msvc 0.42.2", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -5191,6 +8594,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -5209,6 +8618,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -5227,6 +8642,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -5257,6 +8678,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -5275,6 +8702,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -5293,6 +8726,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -5311,6 +8750,12 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -5454,6 +8899,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + [[package]] name = "yoke" version = "0.8.3" @@ -5501,7 +8952,7 @@ dependencies = [ "hex", "nix", "ordered-stream", - "rand", + "rand 0.8.6", "serde", "serde_repr", "sha1", @@ -5645,12 +9096,48 @@ dependencies = [ "memchr", ] +[[package]] +name = "zip" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" +dependencies = [ + "crc32fast", + "indexmap 2.14.0", + "memchr", + "typed-path", +] + [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] + [[package]] name = "zvariant" version = "4.2.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index acc7789..c5e6a29 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -2,16 +2,23 @@ name = "git_lite" version = "0.1.0" description = "Rust backend for a lightweight Git desktop client" -edition = "2021" -rust-version = "1.77" +edition = "2024" +rust-version = "1.88" build = "build.rs" +[workspace] +members = [".", "crates/commit_ai"] + +[workspace.package] +edition = "2024" + [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" tauri = { version = "2", features = [] } tauri-plugin-dialog = "=2.7.0" keyring = { version = "3", features = ["apple-native", "windows-native", "async-secret-service", "crypto-rust", "async-io"] } +commit_ai = { path = "crates/commit_ai" } [build-dependencies] tauri-build = { version = "2", features = [] } diff --git a/src-tauri/crates/commit_ai/Cargo.toml b/src-tauri/crates/commit_ai/Cargo.toml new file mode 100644 index 0000000..09b00e1 --- /dev/null +++ b/src-tauri/crates/commit_ai/Cargo.toml @@ -0,0 +1,10 @@ + +[package] +name = "commit_ai" +version = "0.1.0" +edition = "2024" + +[dependencies] +mistralrs = "0.8" +tokio = { version = "1", features = ["sync"] } +serde = { version = "1", features = ["derive"] } diff --git a/src-tauri/crates/commit_ai/src/lib.rs b/src-tauri/crates/commit_ai/src/lib.rs new file mode 100644 index 0000000..6f4f2e6 --- /dev/null +++ b/src-tauri/crates/commit_ai/src/lib.rs @@ -0,0 +1,157 @@ +use std::sync::Arc; + +use mistralrs::{GgufModelBuilder, Model, TextMessageRole, TextMessages}; +use tokio::sync::RwLock; + +// Small instruct model, quantized to keep the one-time download reasonable (~1 GB) while +// still being fast enough for short, structured generations like a commit message on CPU. +const HF_REPO: &str = "Qwen/Qwen2.5-1.5B-Instruct-GGUF"; +const GGUF_FILE: &str = "qwen2.5-1.5b-instruct-q4_k_m.gguf"; +const TOKENIZER_MODEL_ID: &str = "Qwen/Qwen2.5-1.5B-Instruct"; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)] +#[serde(rename_all = "lowercase")] +pub enum CommitAiPhase { + /// Nothing has been requested yet. + Idle, + /// Downloading (first run only, then cached by hf-hub) and/or loading into memory. + Loading, + Ready, + Error, +} + +#[derive(Debug, Clone, serde::Serialize)] +pub struct CommitAiStatus { + pub phase: CommitAiPhase, + pub error: Option, +} + +struct Inner { + phase: CommitAiPhase, + error: Option, + model: Option>, +} + +/// Cheap to clone: shares one model instance across the app via an inner `Arc`. +#[derive(Clone)] +pub struct CommitAiEngine { + inner: Arc>, +} + +impl Default for CommitAiEngine { + fn default() -> Self { + Self { + inner: Arc::new(RwLock::new(Inner { + phase: CommitAiPhase::Idle, + error: None, + model: None, + })), + } + } +} + +impl CommitAiEngine { + pub fn new() -> Self { + Self::default() + } + + pub async fn status(&self) -> CommitAiStatus { + let guard = self.inner.read().await; + CommitAiStatus { + phase: guard.phase, + error: guard.error.clone(), + } + } + + /// Downloads (first run only; hf-hub caches the files afterwards) and loads the model. + /// Safe to call multiple times — only the first caller actually triggers a load, later + /// callers just return once the in-flight or previous attempt is done. + pub async fn ensure_loaded(&self) { + { + let mut guard = self.inner.write().await; + if guard.phase != CommitAiPhase::Idle { + return; + } + guard.phase = CommitAiPhase::Loading; + guard.error = None; + } + + let result = GgufModelBuilder::new(HF_REPO, vec![GGUF_FILE]) + .with_tok_model_id(TOKENIZER_MODEL_ID) + .with_logging() + .build() + .await; + + let mut guard = self.inner.write().await; + match result { + Ok(model) => { + guard.model = Some(Arc::new(model)); + guard.phase = CommitAiPhase::Ready; + guard.error = None; + } + Err(err) => { + guard.phase = CommitAiPhase::Error; + guard.error = Some(err.to_string()); + } + } + } + + pub async fn generate_commit_message( + &self, + diff: &str, + notes: Option<&str>, + ) -> Result { + let model = { + let guard = self.inner.read().await; + match (guard.phase, &guard.model) { + (CommitAiPhase::Ready, Some(model)) => model.clone(), + _ => return Err("Das KI-Modell ist noch nicht bereit.".to_string()), + } + }; + + if diff.trim().is_empty() { + return Err("Keine gestagten Änderungen für eine Commit-Message vorhanden.".to_string()); + } + + let (system, user) = build_messages(diff, notes); + let messages = TextMessages::new() + .add_message(TextMessageRole::System, system) + .add_message(TextMessageRole::User, user); + + let response = model + .send_chat_request(messages) + .await + .map_err(|err| err.to_string())?; + + let content = response + .choices + .first() + .and_then(|choice| choice.message.content.clone()) + .ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string())?; + + Ok(content.trim().to_string()) + } +} + +fn build_messages(diff: &str, notes: Option<&str>) -> (String, String) { + // grobe Token-Schätzung, kleine Modelle haben oft 8–32k Kontext + const MAX_CHARS: usize = 24_000; + let diff = if diff.len() > MAX_CHARS { + format!("{}\n\n[... Diff gekürzt ...]", &diff[..MAX_CHARS]) + } else { + diff.to_string() + }; + + let system = "Du bist ein Werkzeug, das Git-Commit-Messages erzeugt. \ +Antworte ausschließlich mit der Commit-Message im Conventional-Commits-Format \ +((): ), optional gefolgt von einem Body nach einer Leerzeile. \ +Subject imperativ, max. 72 Zeichen. Kein Vorspann, keine Erklärung, keine Code-Fences, in Englisch antworten" + .to_string(); + + let mut user = String::new(); + if let Some(n) = notes.filter(|n| !n.trim().is_empty()) { + user.push_str(&format!("Anmerkungen des Entwicklers:\n{n}\n\n")); + } + user.push_str(&format!("Staged diff:\n{diff}")); + (system, user) +} diff --git a/src-tauri/src/git.rs b/src-tauri/src/git.rs index 4b8d8a2..39da2c1 100644 --- a/src-tauri/src/git.rs +++ b/src-tauri/src/git.rs @@ -479,6 +479,37 @@ pub fn get_file_patch(path: String, file: String, staged: bool) -> Result, +) -> Result { + Ok(engine.status().await) +} + +#[tauri::command] +pub async fn commit_ai_generate( + path: String, + notes: Option, + engine: tauri::State<'_, commit_ai::CommitAiEngine>, +) -> Result { + let repo = resolve_repo(&path)?; + let diff = run_git( + &repo, + [ + "diff", + "--cached", + "--no-ext-diff", + "--no-textconv", + "--unified=3", + ], + )?; + let diff = String::from_utf8_lossy(&diff).to_string(); + + engine + .generate_commit_message(&diff, notes.as_deref()) + .await +} + #[tauri::command] pub fn apply_file_patch( path: String, @@ -1573,6 +1604,7 @@ fn status_for_repo(repo: &Path) -> Result { let (branch, mut files) = parse_status_output(&output)?; detect_worktree_renames(repo, &mut files); + Ok(GitStatus { repo_path: repo.to_string_lossy().to_string(), current_branch: branch.current_branch, diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 20145bb..8fa6a28 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,21 +4,33 @@ mod git; use git::{ apply_file_patch, cancel_code_search, cancel_file_history, checkout_branch, commit, - compare_commits, compare_file_to_head, compare_file_to_parent, create_branch, cred_delete, - cred_load, cred_save, delete_branch, diff_file_against_working_tree, get_file_patch, - get_remote_url, get_status, list_branches, list_commits, list_file_history, - list_repository_files, merge_branch, open_repo_in_explorer, open_repository, - open_repository_bundle, open_repository_file, pull, push, read_conflict, rename_branch, - resolve_conflict, resolve_conflict_side, restore_file_from_commit, restore_files, - restore_to_commit, search_code_introductions, stage_files, unstage_files, + commit_ai_generate, commit_ai_status, compare_commits, compare_file_to_head, + compare_file_to_parent, create_branch, cred_delete, cred_load, cred_save, delete_branch, + diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, list_branches, + list_commits, list_file_history, list_repository_files, merge_branch, open_repo_in_explorer, + open_repository, open_repository_bundle, open_repository_file, pull, push, read_conflict, + rename_branch, resolve_conflict, resolve_conflict_side, restore_file_from_commit, + restore_files, restore_to_commit, search_code_introductions, stage_files, unstage_files, SearchCancellationState, }; fn main() { + let commit_ai_engine = commit_ai::CommitAiEngine::new(); + tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) .manage(SearchCancellationState::default()) + .manage(commit_ai_engine.clone()) .plugin(tauri_plugin_dialog::init()) + .setup(move |_app| { + // Kick off the (first-run-only) download and model load in the background so the + // "Generate with AI" button becomes enabled once it's ready, without blocking startup. + let engine = commit_ai_engine.clone(); + tauri::async_runtime::spawn(async move { + engine.ensure_loaded().await; + }); + Ok(()) + }) .invoke_handler(tauri::generate_handler![ open_repository, open_repo_in_explorer, @@ -35,6 +47,8 @@ fn main() { get_file_patch, apply_file_patch, commit, + commit_ai_status, + commit_ai_generate, pull, push, list_commits, diff --git a/src/App.svelte b/src/App.svelte index 8b3efd2..b7b89eb 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -25,6 +25,8 @@ import { checkoutBranch, commit, + commitAiGenerate, + commitAiStatus, compareCommits, cancelCodeSearch, cancelFileHistory, @@ -62,6 +64,7 @@ } from "./lib/git"; import type { + CommitAiPhase, ConflictFile, ExplorerNode, ExplorerNodeKind, @@ -122,7 +125,11 @@ let fileHistoryLoading = false; let fileHistoryRequestId = 0; let activeFileHistoryRequestId = ""; + let lastFileHistoryHeadHash = ""; let commitMessage = ""; + let commitAiPhase: CommitAiPhase = "idle"; + let commitAiGenerating = false; + let commitAiPollTimer: ReturnType | undefined; let errorMessage = ""; let operation = ""; let compareFrom = ""; @@ -206,10 +213,12 @@ loadRepoLists(); autoRefreshTimer = setInterval(() => { void autoRefreshTick(); }, AUTO_REFRESH_INTERVAL); void checkForUpdates(); + startCommitAiPolling(); }); onDestroy(() => { if (autoRefreshTimer) clearInterval(autoRefreshTimer); + if (commitAiPollTimer) clearInterval(commitAiPollTimer); if (activeFileHistoryRequestId) void cancelFileHistory(activeFileHistoryRequestId); }); @@ -229,15 +238,54 @@ applyStatus(nextStatus); // Something changed — reload branches, commits and files in one bundled call. const bundle = await openRepositoryBundle(activeRepoPath, 100); + const previousHeadHash = lastFileHistoryHeadHash; await refreshBranchList(activeRepoPath, bundle.branches); await refreshCommitHistory(activeRepoPath, bundle.commits); await refreshExplorerFiles(activeRepoPath, bundle.files); - await refreshFileHistory(activeRepoPath); + // File history reflects `git log`, which only changes when HEAD actually moves + // (new commit, checkout, merge, ...) — skip the reload otherwise so a plain + // working-tree/status change (staging, edits) doesn't keep re-fetching and + // flickering the currently viewed file's history. + if (lastFileHistoryHeadHash !== previousHeadHash) { + await refreshFileHistory(activeRepoPath); + } } catch { /* ignore transient errors */ } finally { autoRefreshInFlight = false; } } + // ── Commit AI ────────────────────────────────────────────────────────────── + + async function pollCommitAiStatus() { + try { + const result = await commitAiStatus(); + commitAiPhase = result.phase; + } catch { /* ignore transient errors */ } + if (commitAiPhase === "ready" || commitAiPhase === "error") { + if (commitAiPollTimer) { clearInterval(commitAiPollTimer); commitAiPollTimer = undefined; } + } + } + + function startCommitAiPolling() { + // The model downloads (first run only) and loads in the background on app start; + // poll until it's ready (or failed) so the "AI" button can enable itself. + void pollCommitAiStatus(); + commitAiPollTimer = setInterval(() => { void pollCommitAiStatus(); }, 2000); + } + + async function generateCommitMessageWithAi() { + if (!activeRepoPath || commitAiPhase !== "ready" || commitAiGenerating) return; + commitAiGenerating = true; + errorMessage = ""; + try { + commitMessage = await commitAiGenerate(activeRepoPath, commitMessage.trim() || undefined); + } catch (error) { + errorMessage = errorToMessage(error); + } finally { + commitAiGenerating = false; + } + } + function toggleAutoRefresh() { autoRefreshEnabled = !autoRefreshEnabled; if (autoRefreshEnabled) void autoRefreshTick(); @@ -430,6 +478,7 @@ } branches = []; commits = []; + lastFileHistoryHeadHash = ""; repoFiles = []; selectedExplorerPath = ""; selectedExplorerKind = "file"; @@ -520,6 +569,7 @@ async function refreshCommitHistory(path = activeRepoPath, prefetched?: GitCommit[]) { commits = prefetched ?? (await listCommits(path, 100)); + lastFileHistoryHeadHash = commits[0]?.hash ?? ""; const hashes = new Set(commits.map((c) => c.hash)); if (compareFrom && !hashes.has(compareFrom)) compareFrom = ""; if (compareTo && !hashes.has(compareTo)) compareTo = ""; @@ -1692,8 +1742,11 @@ {isBusy} {operation} {stagedCount} + {commitAiPhase} + {commitAiGenerating} onCommit={commitChanges} onCommitMessageChange={(msg) => { commitMessage = msg; }} + onGenerateCommitMessage={generateCommitMessageWithAi} /> diff --git a/src/app.css b/src/app.css index 9560379..7813a8a 100644 --- a/src/app.css +++ b/src/app.css @@ -1332,6 +1332,8 @@ .commit-form { display: flex; flex-direction: column; flex: 1 1 0; min-height: 0; gap: 8px; padding: 10px; } .commit-form textarea { flex: 1 1 0; min-height: 80px; resize: none; } + .commit-actions-row { display: flex; gap: 8px; } + .commit-ai-button { flex: 0 0 auto; min-width: 64px; justify-content: center; } .commit-block-reason { margin: 0; padding: 8px 10px; diff --git a/src/lib/components/CommitPanel.svelte b/src/lib/components/CommitPanel.svelte index 9cb6ebd..c813f20 100644 --- a/src/lib/components/CommitPanel.svelte +++ b/src/lib/components/CommitPanel.svelte @@ -1,5 +1,6 @@
@@ -50,13 +68,29 @@ {#if commitBlockReason}

{commitBlockReason}

{/if} - +
+ + +
diff --git a/src/lib/git.ts b/src/lib/git.ts index 870919b..2660783 100644 --- a/src/lib/git.ts +++ b/src/lib/git.ts @@ -1,6 +1,7 @@ import { invoke } from "@tauri-apps/api/core"; import type { + CommitAiStatus, ConflictFile, GitBranch, GitCommit, @@ -94,6 +95,14 @@ export function commit(path: string, message: string): Promise { return invoke("commit", { path, message }); } +export function commitAiStatus(): Promise { + return invoke("commit_ai_status"); +} + +export function commitAiGenerate(path: string, notes?: string): Promise { + return invoke("commit_ai_generate", { path, notes }); +} + export function pull(path: string, username?: string, password?: string): Promise { return invoke("pull", { path, username: username ?? null, password: password ?? null }); } diff --git a/src/lib/types.ts b/src/lib/types.ts index 1b13e54..5a9f48d 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -7,6 +7,13 @@ export type FileStatusKind = | "conflicted" | "unknown"; +export type CommitAiPhase = "idle" | "loading" | "ready" | "error"; + +export interface CommitAiStatus { + phase: CommitAiPhase; + error: string | null; +} + export interface GitStatus { repo_path: string; current_branch: string | null; -- 2.54.0 From d415cbd3a19e12b4e68c4563604a2088fd84131e Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Thu, 2 Jul 2026 20:24:46 +0200 Subject: [PATCH 2/4] add upstream --- src-tauri/crates/commit_ai/src/lib.rs | 4 +- src-tauri/src/git.rs | 190 +++++++++++++++++++++----- src-tauri/src/main.rs | 18 +-- 3 files changed, 168 insertions(+), 44 deletions(-) diff --git a/src-tauri/crates/commit_ai/src/lib.rs b/src-tauri/crates/commit_ai/src/lib.rs index 6f4f2e6..20ef80a 100644 --- a/src-tauri/crates/commit_ai/src/lib.rs +++ b/src-tauri/crates/commit_ai/src/lib.rs @@ -110,7 +110,9 @@ impl CommitAiEngine { }; if diff.trim().is_empty() { - return Err("Keine gestagten Änderungen für eine Commit-Message vorhanden.".to_string()); + return Err( + "Keine gestagten Änderungen für eine Commit-Message vorhanden.".to_string(), + ); } let (system, user) = build_messages(diff, notes); diff --git a/src-tauri/src/git.rs b/src-tauri/src/git.rs index 39da2c1..b090d1d 100644 --- a/src-tauri/src/git.rs +++ b/src-tauri/src/git.rs @@ -5,8 +5,8 @@ use std::{ path::{Path, PathBuf}, process::{Command, Output, Stdio}, sync::{ - atomic::{AtomicU64, Ordering}, Arc, Mutex, + atomic::{AtomicU64, Ordering}, }, thread, time::Duration, @@ -606,12 +606,13 @@ pub fn push( password: Option, ) -> Result { let repo = resolve_repo(&path)?; + let push_args = push_args_for_repo(&repo)?; match (username.as_deref(), password.as_deref()) { (Some(u), Some(p)) if !u.is_empty() || !p.is_empty() => { - run_git_authenticated(&repo, ["push"], u, p)?; + run_git_authenticated(&repo, push_args, u, p)?; } _ => { - run_git(&repo, ["push"])?; + run_git(&repo, push_args)?; } } status_for_repo(&repo) @@ -670,19 +671,11 @@ fn remote_url_for(repo: &Path, remote: &str) -> Option { return None; } let url = String::from_utf8_lossy(&out.stdout).trim().to_string(); - if url.is_empty() { - None - } else { - Some(url) - } + if url.is_empty() { None } else { Some(url) } } fn upstream_remote_name(repo: &Path) -> Option { - let branch = run_git(repo, ["rev-parse", "--abbrev-ref", "HEAD"]).ok()?; - let branch = String::from_utf8_lossy(&branch).trim().to_string(); - if branch.is_empty() || branch == "HEAD" { - return None; - } + let branch = current_branch_name(repo).ok()?; let out = git_command() .arg("-C") .arg(repo) @@ -693,11 +686,7 @@ fn upstream_remote_name(repo: &Path) -> Option { return None; } let name = String::from_utf8_lossy(&out.stdout).trim().to_string(); - if name.is_empty() { - None - } else { - Some(name) - } + if name.is_empty() { None } else { Some(name) } } fn first_remote_name(repo: &Path) -> Option { @@ -709,6 +698,50 @@ fn first_remote_name(repo: &Path) -> Option { .map(str::to_string) } +fn current_branch_name(repo: &Path) -> Result { + let branch = run_git(repo, ["rev-parse", "--abbrev-ref", "HEAD"])?; + let branch = String::from_utf8_lossy(&branch).trim().to_string(); + if branch.is_empty() || branch == "HEAD" { + return Err("Aktueller Branch konnte nicht ermittelt werden.".to_string()); + } + Ok(branch) +} + +fn branch_has_upstream(repo: &Path) -> bool { + git_command() + .arg("-C") + .arg(repo) + .args(["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"]) + .output() + .map(|output| output.status.success()) + .unwrap_or(false) +} + +fn initial_push_remote_name(repo: &Path) -> Result { + if remote_url_for(repo, "origin").is_some() { + return Ok("origin".to_string()); + } + + first_remote_name(repo).ok_or_else(|| { + "Dieser Branch hat keinen Upstream und es ist kein Remote konfiguriert.".to_string() + }) +} + +fn push_args_for_repo(repo: &Path) -> Result, String> { + if branch_has_upstream(repo) { + return Ok(vec![OsString::from("push")]); + } + + let branch = current_branch_name(repo)?; + let remote = initial_push_remote_name(repo)?; + Ok(vec![ + OsString::from("push"), + OsString::from("--set-upstream"), + OsString::from(remote), + OsString::from(branch), + ]) +} + #[tauri::command] pub fn cred_load(key: String) -> Result, String> { let entry = cred_entry(&key)?; @@ -1604,7 +1637,6 @@ fn status_for_repo(repo: &Path) -> Result { let (branch, mut files) = parse_status_output(&output)?; detect_worktree_renames(repo, &mut files); - Ok(GitStatus { repo_path: repo.to_string_lossy().to_string(), current_branch: branch.current_branch, @@ -3170,6 +3202,22 @@ mod tests { } fn init_temp_repo(name: &str) -> TempRepo { + let repo = temp_dir(name); + + run_git_test(&repo.path, ["init", "-q"]); + run_git_test(&repo.path, ["config", "user.email", "test@example.com"]); + run_git_test(&repo.path, ["config", "user.name", "Tester"]); + + repo + } + + fn init_bare_temp_repo(name: &str) -> TempRepo { + let repo = temp_dir(name); + run_git_test(&repo.path, ["init", "--bare", "-q"]); + repo + } + + fn temp_dir(name: &str) -> TempRepo { let nanos = SystemTime::now() .duration_since(UNIX_EPOCH) .expect("system time should be after Unix epoch") @@ -3181,9 +3229,6 @@ mod tests { )); fs::create_dir_all(&path).expect("temp repo directory should be created"); - run_git_test(&path, ["init", "-q"]); - run_git_test(&path, ["config", "user.email", "test@example.com"]); - run_git_test(&path, ["config", "user.name", "Tester"]); TempRepo { path } } @@ -3504,14 +3549,18 @@ mod tests { ) .unwrap(); - assert!(comparison - .files - .iter() - .any(|file| file.path == "old.txt" && file.status == FileStatusKind::Modified)); - assert!(comparison - .files - .iter() - .any(|file| file.path == "added.txt" && file.status == FileStatusKind::Added)); + assert!( + comparison + .files + .iter() + .any(|file| file.path == "old.txt" && file.status == FileStatusKind::Modified) + ); + assert!( + comparison + .files + .iter() + .any(|file| file.path == "added.txt" && file.status == FileStatusKind::Added) + ); assert!(comparison.patch.contains("second line")); } @@ -3568,10 +3617,12 @@ mod tests { assert_eq!(comparison.to_short, "working tree"); assert!(comparison.to_hash.is_empty()); - assert!(comparison - .files - .iter() - .any(|file| file.path == "old.txt" && file.status == FileStatusKind::Modified)); + assert!( + comparison + .files + .iter() + .any(|file| file.path == "old.txt" && file.status == FileStatusKind::Modified) + ); assert!(comparison.patch.contains("working tree change")); } @@ -3705,6 +3756,77 @@ mod tests { assert_eq!(parent_count, 2); } + #[test] + fn push_args_use_set_upstream_for_branch_without_tracking_remote() { + let repo = init_temp_repo("push_sets_upstream"); + let remote = init_bare_temp_repo("push_sets_upstream_remote"); + commit_initial_file(&repo.path); + run_git_test( + &repo.path, + ["checkout", "-q", "-b", "features/ai_commits_local"], + ); + fs::write(repo.path.join("feature.txt"), "feature\n") + .expect("feature file should be written"); + run_git_test(&repo.path, ["add", "feature.txt"]); + run_git_test(&repo.path, ["commit", "-q", "-m", "feature work"]); + run_git_test( + &repo.path, + ["remote", "add", "origin", remote.path.to_str().unwrap()], + ); + + let args = push_args_for_repo(&repo.path).unwrap(); + let args = args + .iter() + .map(|arg| arg.to_string_lossy().to_string()) + .collect::>(); + + assert_eq!( + args, + vec![ + "push", + "--set-upstream", + "origin", + "features/ai_commits_local" + ] + ); + } + + #[test] + #[cfg_attr( + windows, + ignore = "Git for Windows can fail local push tests with a sh signal pipe error" + )] + fn push_sets_upstream_for_branch_without_tracking_remote() { + let repo = init_temp_repo("push_sets_upstream_integration"); + let remote = init_bare_temp_repo("push_sets_upstream_integration_remote"); + commit_initial_file(&repo.path); + run_git_test( + &repo.path, + ["checkout", "-q", "-b", "features/ai_commits_local"], + ); + fs::write(repo.path.join("feature.txt"), "feature\n") + .expect("feature file should be written"); + run_git_test(&repo.path, ["add", "feature.txt"]); + run_git_test(&repo.path, ["commit", "-q", "-m", "feature work"]); + run_git_test( + &repo.path, + ["remote", "add", "origin", remote.path.to_str().unwrap()], + ); + + let status = push(repo.path.to_string_lossy().to_string(), None, None).unwrap(); + + assert_eq!( + status.upstream.as_deref(), + Some("origin/features/ai_commits_local") + ); + let local_head = git_output_test(&repo.path, ["rev-parse", "HEAD"]); + let remote_head = git_output_test( + &remote.path, + ["rev-parse", "refs/heads/features/ai_commits_local"], + ); + assert_eq!(remote_head, local_head); + } + #[test] fn read_and_resolve_conflict_round_trip() { let repo = init_temp_repo("resolve_conflict"); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8fa6a28..8fd5f5c 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -3,15 +3,15 @@ mod git; use git::{ - apply_file_patch, cancel_code_search, cancel_file_history, checkout_branch, commit, - commit_ai_generate, commit_ai_status, compare_commits, compare_file_to_head, - compare_file_to_parent, create_branch, cred_delete, cred_load, cred_save, delete_branch, - diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, list_branches, - list_commits, list_file_history, list_repository_files, merge_branch, open_repo_in_explorer, - open_repository, open_repository_bundle, open_repository_file, pull, push, read_conflict, - rename_branch, resolve_conflict, resolve_conflict_side, restore_file_from_commit, - restore_files, restore_to_commit, search_code_introductions, stage_files, unstage_files, - SearchCancellationState, + SearchCancellationState, apply_file_patch, cancel_code_search, cancel_file_history, + checkout_branch, commit, commit_ai_generate, commit_ai_status, compare_commits, + compare_file_to_head, compare_file_to_parent, create_branch, cred_delete, cred_load, cred_save, + delete_branch, diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, + list_branches, list_commits, list_file_history, list_repository_files, merge_branch, + open_repo_in_explorer, open_repository, open_repository_bundle, open_repository_file, pull, + push, read_conflict, rename_branch, resolve_conflict, resolve_conflict_side, + restore_file_from_commit, restore_files, restore_to_commit, search_code_introductions, + stage_files, unstage_files, }; fn main() { -- 2.54.0 From 6b7186d040c844baeaa14d8a4f6adc9e8c21ae23 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Thu, 2 Jul 2026 21:19:16 +0200 Subject: [PATCH 3/4] feat(ai): add cloud providers and local model selection Add OpenAI-compatible, Anthropic, and custom endpoint support while keeping the local model path intact. The UI now lets users choose the provider and local model, and staged diffs are prepared more carefully so generated commit messages stay focused and usable. - src-tauri/crates/commit_ai/* - Add HTTP-based generators for OpenAI, Anthropic, and custom APIs. - Introduce shared request/response handling and message sanitizing. - Expand prompt building to require a body and trim long diffs safely. - Expose selectable local model metadata and loading by model ID. - src-tauri/src/git.rs - Add commands for listing local models and loading them in background. - Route generation by provider and include staged file lists in prompts. - Exclude noisy lockfiles from detailed staged diffs. - src-tauri/src/main.rs - Wire the new AI commands into the Tauri app setup. - src/lib/components/* - Add an AI settings dialog and update the commit panel for provider and model selection. - src/lib/git.ts, src/lib/types.ts, src/App.svelte, src/app.css - Extend frontend state, types, and styling for AI provider settings. - src-tauri/Cargo.lock, src-tauri/crates/commit_ai/Cargo.toml - Add reqwest and serde_json for cloud API requests. --- .claude/settings.local.json | 12 +- src-tauri/Cargo.lock | 2 + src-tauri/crates/commit_ai/Cargo.toml | 2 + src-tauri/crates/commit_ai/src/cloud.rs | 203 ++++++++++++++++ src-tauri/crates/commit_ai/src/lib.rs | 160 ++++++++++--- src-tauri/src/git.rs | 90 +++++++- src-tauri/src/main.rs | 31 +-- src/App.svelte | 124 +++++++++- src/app.css | 43 ++++ src/lib/components/AiSettingsDialog.svelte | 256 +++++++++++++++++++++ src/lib/components/CommitPanel.svelte | 35 ++- src/lib/git.ts | 29 ++- src/lib/types.ts | 17 ++ 13 files changed, 924 insertions(+), 80 deletions(-) create mode 100644 src-tauri/crates/commit_ai/src/cloud.rs create mode 100644 src/lib/components/AiSettingsDialog.svelte diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 3356e50..aba8357 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -48,7 +48,17 @@ "Bash(curl -sI \"https://huggingface.co/Qwen/Qwen2.5-1.5B-Instruct-GGUF/resolve/main/qwen2.5-1.5b-instruct-q4_k_m.gguf\")", "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-1.5B-Instruct-GGUF?blobs=true\")", "Bash(grep -n 'from \"\\\\./lib/git\"\\\\|from \"\\\\./lib/types\"\\\\|^ commit,$' src/App.svelte)", - "Bash(kill 24343 24363 24375 24376)" + "Bash(kill 24343 24363 24375 24376)", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-0.5B-Instruct-GGUF?blobs=true\")", + "Bash(curl -s \"https://huggingface.co/api/models/bartowski/Llama-3.2-3B-Instruct-GGUF?blobs=true\")", + "Bash(curl -s \"https://huggingface.co/api/models/bartowski/Llama-3.2-3B-Instruct-GGUF\")", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-3B-Instruct-GGUF\")", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-3B-Instruct-GGUF?blobs=true\")", + "Bash(curl -s \"https://huggingface.co/api/models/Qwen/Qwen2.5-3B-Instruct\")", + "Bash(: *)", + "Bash(exit 0 *)", + "Bash(rustc -O sanitize_test.rs -o sanitize_test)", + "Bash(./sanitize_test)" ] } } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 945e55a..1048794 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1028,7 +1028,9 @@ name = "commit_ai" version = "0.1.0" dependencies = [ "mistralrs", + "reqwest 0.12.28", "serde", + "serde_json", "tokio", ] diff --git a/src-tauri/crates/commit_ai/Cargo.toml b/src-tauri/crates/commit_ai/Cargo.toml index 09b00e1..501deb3 100644 --- a/src-tauri/crates/commit_ai/Cargo.toml +++ b/src-tauri/crates/commit_ai/Cargo.toml @@ -8,3 +8,5 @@ edition = "2024" mistralrs = "0.8" tokio = { version = "1", features = ["sync"] } serde = { version = "1", features = ["derive"] } +serde_json = "1" +reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } diff --git a/src-tauri/crates/commit_ai/src/cloud.rs b/src-tauri/crates/commit_ai/src/cloud.rs new file mode 100644 index 0000000..39377e3 --- /dev/null +++ b/src-tauri/crates/commit_ai/src/cloud.rs @@ -0,0 +1,203 @@ +use std::time::Duration; + +use serde::{Deserialize, Serialize}; + +use crate::{build_messages, sanitize_message}; + +// Großzügig bemessen, damit ein ausführlicher Body mit Stichpunkten nicht abgeschnitten wird. +const DEFAULT_MAX_TOKENS: u32 = 1500; +// Ohne Timeout würde ein hängender Endpoint den "AI"-Button dauerhaft blockieren. +const REQUEST_TIMEOUT: Duration = Duration::from_secs(60); + +fn http_client() -> Result { + reqwest::Client::builder() + .timeout(REQUEST_TIMEOUT) + .build() + .map_err(|err| format!("HTTP-Client konnte nicht erstellt werden: {err}")) +} + +#[derive(Serialize)] +struct OpenAiMessage { + role: &'static str, + content: String, +} + +#[derive(Serialize)] +struct OpenAiRequest { + model: String, + messages: Vec, + temperature: f32, +} + +#[derive(Deserialize)] +struct OpenAiResponseMessage { + content: Option, +} + +#[derive(Deserialize)] +struct OpenAiChoice { + message: OpenAiResponseMessage, +} + +#[derive(Deserialize)] +struct OpenAiResponse { + #[serde(default)] + choices: Vec, +} + +async fn openai_compatible_request( + url: String, + bearer: Option<&str>, + model: &str, + diff: &str, + notes: Option<&str>, +) -> Result { + let (system, user) = build_messages(diff, notes)?; + let body = OpenAiRequest { + model: model.to_string(), + messages: vec![ + OpenAiMessage { role: "system", content: system }, + OpenAiMessage { role: "user", content: user }, + ], + temperature: 0.3, + }; + + let client = http_client()?; + let mut request = client.post(url).json(&body); + if let Some(key) = bearer.filter(|k| !k.trim().is_empty()) { + request = request.bearer_auth(key); + } + + let response = request + .send() + .await + .map_err(|err| format!("Anfrage an das KI-Modell fehlgeschlagen: {err}"))?; + let status = response.status(); + let text = response + .text() + .await + .map_err(|err| format!("Antwort konnte nicht gelesen werden: {err}"))?; + + if !status.is_success() { + return Err(format!("API-Fehler ({status}): {text}")); + } + + let parsed: OpenAiResponse = serde_json::from_str(&text) + .map_err(|err| format!("Antwort konnte nicht verarbeitet werden: {err}"))?; + + parsed + .choices + .into_iter() + .next() + .and_then(|choice| choice.message.content) + .map(|content| sanitize_message(&content)) + .filter(|content| !content.is_empty()) + .ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string()) +} + +pub async fn generate_openai( + api_key: &str, + model: &str, + diff: &str, + notes: Option<&str>, +) -> Result { + if api_key.trim().is_empty() { + return Err("OpenAI-API-Key fehlt.".to_string()); + } + openai_compatible_request( + "https://api.openai.com/v1/chat/completions".to_string(), + Some(api_key), + model, + diff, + notes, + ) + .await +} + +pub async fn generate_custom( + base_url: &str, + api_key: Option<&str>, + model: &str, + diff: &str, + notes: Option<&str>, +) -> Result { + if base_url.trim().is_empty() { + return Err("Endpoint-URL fehlt.".to_string()); + } + let url = format!("{}/chat/completions", base_url.trim_end_matches('/')); + openai_compatible_request(url, api_key, model, diff, notes).await +} + +#[derive(Serialize)] +struct AnthropicMessage { + role: &'static str, + content: String, +} + +#[derive(Serialize)] +struct AnthropicRequest { + model: String, + max_tokens: u32, + system: String, + messages: Vec, +} + +#[derive(Deserialize)] +struct AnthropicContentBlock { + #[serde(default)] + text: Option, +} + +#[derive(Deserialize)] +struct AnthropicResponse { + #[serde(default)] + content: Vec, +} + +pub async fn generate_anthropic( + api_key: &str, + model: &str, + diff: &str, + notes: Option<&str>, +) -> Result { + if api_key.trim().is_empty() { + return Err("Anthropic-API-Key fehlt.".to_string()); + } + let (system, user) = build_messages(diff, notes)?; + let body = AnthropicRequest { + model: model.to_string(), + max_tokens: DEFAULT_MAX_TOKENS, + system, + messages: vec![AnthropicMessage { role: "user", content: user }], + }; + + let client = http_client()?; + let response = client + .post("https://api.anthropic.com/v1/messages") + .header("x-api-key", api_key) + .header("anthropic-version", "2023-06-01") + .json(&body) + .send() + .await + .map_err(|err| format!("Anfrage an Anthropic fehlgeschlagen: {err}"))?; + let status = response.status(); + let text = response + .text() + .await + .map_err(|err| format!("Antwort konnte nicht gelesen werden: {err}"))?; + + if !status.is_success() { + return Err(format!("API-Fehler ({status}): {text}")); + } + + let parsed: AnthropicResponse = serde_json::from_str(&text) + .map_err(|err| format!("Antwort konnte nicht verarbeitet werden: {err}"))?; + + parsed + .content + .into_iter() + .find_map(|block| block.text) + .map(|text| sanitize_message(&text)) + .filter(|text| !text.is_empty()) + .ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string()) +} diff --git a/src-tauri/crates/commit_ai/src/lib.rs b/src-tauri/crates/commit_ai/src/lib.rs index 20ef80a..6ada392 100644 --- a/src-tauri/crates/commit_ai/src/lib.rs +++ b/src-tauri/crates/commit_ai/src/lib.rs @@ -1,13 +1,56 @@ +mod cloud; + +pub use cloud::{generate_anthropic, generate_custom, generate_openai}; + use std::sync::Arc; use mistralrs::{GgufModelBuilder, Model, TextMessageRole, TextMessages}; use tokio::sync::RwLock; -// Small instruct model, quantized to keep the one-time download reasonable (~1 GB) while -// still being fast enough for short, structured generations like a commit message on CPU. -const HF_REPO: &str = "Qwen/Qwen2.5-1.5B-Instruct-GGUF"; -const GGUF_FILE: &str = "qwen2.5-1.5b-instruct-q4_k_m.gguf"; -const TOKENIZER_MODEL_ID: &str = "Qwen/Qwen2.5-1.5B-Instruct"; +/// One selectable local (on-device) model. Larger models produce better commit messages +/// but take longer to download (first run only, then cached) and run slower on CPU. +#[derive(Debug, Clone, serde::Serialize)] +pub struct LocalModelOption { + pub id: &'static str, + pub label: &'static str, + pub approx_size_mb: u32, + repo: &'static str, + file: &'static str, + tokenizer_repo: &'static str, +} + +pub const DEFAULT_LOCAL_MODEL_ID: &str = "qwen2.5-1.5b"; + +pub const LOCAL_MODELS: &[LocalModelOption] = &[ + LocalModelOption { + id: "qwen2.5-0.5b", + label: "Qwen2.5 0.5B Instruct — schnell, geringere Qualität", + approx_size_mb: 490, + repo: "Qwen/Qwen2.5-0.5B-Instruct-GGUF", + file: "qwen2.5-0.5b-instruct-q4_k_m.gguf", + tokenizer_repo: "Qwen/Qwen2.5-0.5B-Instruct", + }, + LocalModelOption { + id: "qwen2.5-1.5b", + label: "Qwen2.5 1.5B Instruct — empfohlen", + approx_size_mb: 1050, + repo: "Qwen/Qwen2.5-1.5B-Instruct-GGUF", + file: "qwen2.5-1.5b-instruct-q4_k_m.gguf", + tokenizer_repo: "Qwen/Qwen2.5-1.5B-Instruct", + }, + LocalModelOption { + id: "qwen2.5-3b", + label: "Qwen2.5 3B Instruct — beste Qualität, langsamer", + approx_size_mb: 2100, + repo: "Qwen/Qwen2.5-3B-Instruct-GGUF", + file: "qwen2.5-3b-instruct-q4_k_m.gguf", + tokenizer_repo: "Qwen/Qwen2.5-3B-Instruct", + }, +]; + +fn find_local_model(model_id: &str) -> Option<&'static LocalModelOption> { + LOCAL_MODELS.iter().find(|option| option.id == model_id) +} #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)] #[serde(rename_all = "lowercase")] @@ -23,16 +66,19 @@ pub enum CommitAiPhase { #[derive(Debug, Clone, serde::Serialize)] pub struct CommitAiStatus { pub phase: CommitAiPhase, + pub model_id: Option, pub error: Option, } struct Inner { phase: CommitAiPhase, + model_id: Option, error: Option, model: Option>, } -/// Cheap to clone: shares one model instance across the app via an inner `Arc`. +/// Manages the local (on-device) model only. Cloud providers are stateless HTTP calls +/// (see [`cloud`]) and don't need this — there's nothing to download or keep loaded. #[derive(Clone)] pub struct CommitAiEngine { inner: Arc>, @@ -43,6 +89,7 @@ impl Default for CommitAiEngine { Self { inner: Arc::new(RwLock::new(Inner { phase: CommitAiPhase::Idle, + model_id: None, error: None, model: None, })), @@ -59,30 +106,52 @@ impl CommitAiEngine { let guard = self.inner.read().await; CommitAiStatus { phase: guard.phase, + model_id: guard.model_id.clone(), error: guard.error.clone(), } } - /// Downloads (first run only; hf-hub caches the files afterwards) and loads the model. - /// Safe to call multiple times — only the first caller actually triggers a load, later - /// callers just return once the in-flight or previous attempt is done. - pub async fn ensure_loaded(&self) { + /// Downloads (first run only; hf-hub caches the files afterwards) and loads the given + /// local model. Safe to call repeatedly — a call for the model that's already + /// ready/loading is a no-op; a call for a *different* model switches to it (the + /// previous one is dropped once no generation is still using it). + pub async fn ensure_loaded(&self, model_id: &str) { { - let mut guard = self.inner.write().await; - if guard.phase != CommitAiPhase::Idle { + let guard = self.inner.read().await; + let same_model = guard.model_id.as_deref() == Some(model_id); + if same_model && matches!(guard.phase, CommitAiPhase::Ready | CommitAiPhase::Loading) { return; } - guard.phase = CommitAiPhase::Loading; - guard.error = None; } - let result = GgufModelBuilder::new(HF_REPO, vec![GGUF_FILE]) - .with_tok_model_id(TOKENIZER_MODEL_ID) + let Some(option) = find_local_model(model_id) else { + let mut guard = self.inner.write().await; + guard.phase = CommitAiPhase::Error; + guard.model_id = Some(model_id.to_string()); + guard.error = Some(format!("Unbekanntes lokales Modell: {model_id}")); + return; + }; + + { + let mut guard = self.inner.write().await; + guard.phase = CommitAiPhase::Loading; + guard.model_id = Some(model_id.to_string()); + guard.error = None; + guard.model = None; + } + + let result = GgufModelBuilder::new(option.repo, vec![option.file]) + .with_tok_model_id(option.tokenizer_repo) .with_logging() .build() .await; let mut guard = self.inner.write().await; + // If the user switched to yet another model while this one was loading, drop this + // (now stale) result instead of overwriting the newer request's state. + if guard.model_id.as_deref() != Some(model_id) { + return; + } match result { Ok(model) => { guard.model = Some(Arc::new(model)); @@ -105,17 +174,11 @@ impl CommitAiEngine { let guard = self.inner.read().await; match (guard.phase, &guard.model) { (CommitAiPhase::Ready, Some(model)) => model.clone(), - _ => return Err("Das KI-Modell ist noch nicht bereit.".to_string()), + _ => return Err("Das lokale KI-Modell ist noch nicht bereit.".to_string()), } }; - if diff.trim().is_empty() { - return Err( - "Keine gestagten Änderungen für eine Commit-Message vorhanden.".to_string(), - ); - } - - let (system, user) = build_messages(diff, notes); + let (system, user) = build_messages(diff, notes)?; let messages = TextMessages::new() .add_message(TextMessageRole::System, system) .add_message(TextMessageRole::User, user); @@ -131,23 +194,60 @@ impl CommitAiEngine { .and_then(|choice| choice.message.content.clone()) .ok_or_else(|| "Das Modell hat keine Antwort geliefert.".to_string())?; - Ok(content.trim().to_string()) + let message = sanitize_message(&content); + if message.is_empty() { + return Err("Das Modell hat keine Antwort geliefert.".to_string()); + } + Ok(message) } } -fn build_messages(diff: &str, notes: Option<&str>) -> (String, String) { +/// Models occasionally ignore the "no code fences" instruction (small local models +/// especially) — strip a wrapping ``` fence and wrapping quotes so the result can go +/// straight into the commit-message box. +pub(crate) fn sanitize_message(raw: &str) -> String { + let mut text = raw.trim().to_string(); + if text.starts_with("```") { + text = match text.split_once('\n') { + // Drop the opening fence line (which may carry a language tag) and the closing fence. + Some((_fence, rest)) => rest.trim_end().trim_end_matches("```").trim().to_string(), + None => text.trim_matches('`').trim().to_string(), + }; + } + let trimmed = text.trim(); + if trimmed.len() >= 2 && trimmed.starts_with('"') && trimmed.ends_with('"') { + return trimmed[1..trimmed.len() - 1].trim().to_string(); + } + trimmed.to_string() +} + +pub(crate) fn build_messages(diff: &str, notes: Option<&str>) -> Result<(String, String), String> { + if diff.trim().is_empty() { + return Err("Keine gestagten Änderungen für eine Commit-Message vorhanden.".to_string()); + } + // grobe Token-Schätzung, kleine Modelle haben oft 8–32k Kontext const MAX_CHARS: usize = 24_000; let diff = if diff.len() > MAX_CHARS { - format!("{}\n\n[... Diff gekürzt ...]", &diff[..MAX_CHARS]) + // Byte-Index auf eine gültige UTF-8-Zeichengrenze zurückziehen, sonst + // paniken Slices mitten in einem Umlaut o. Ä. + let mut cut = MAX_CHARS; + while !diff.is_char_boundary(cut) { + cut -= 1; + } + format!("{}\n\n[... Diff gekürzt ...]", &diff[..cut]) } else { diff.to_string() }; let system = "Du bist ein Werkzeug, das Git-Commit-Messages erzeugt. \ Antworte ausschließlich mit der Commit-Message im Conventional-Commits-Format \ -((): ), optional gefolgt von einem Body nach einer Leerzeile. \ -Subject imperativ, max. 72 Zeichen. Kein Vorspann, keine Erklärung, keine Code-Fences, in Englisch antworten" +((): ), gefolgt von einem Body nach einer Leerzeile. \ +Subject imperativ, max. 72 Zeichen. \ +Der Body ist Pflicht: Fasse in einem kurzen Absatz zusammen, was und warum geändert wurde, \ +und liste danach die wesentlichen Änderungen als Stichpunkte (- ...) auf, \ +gruppiert nach betroffenem Bereich/Datei. Zeilen im Body max. 72 Zeichen. \ +Kein Vorspann, keine Erklärung, keine Code-Fences, in Englisch antworten" .to_string(); let mut user = String::new(); @@ -155,5 +255,5 @@ Subject imperativ, max. 72 Zeichen. Kein Vorspann, keine Erklärung, keine Code- user.push_str(&format!("Anmerkungen des Entwicklers:\n{n}\n\n")); } user.push_str(&format!("Staged diff:\n{diff}")); - (system, user) + Ok((system, user)) } diff --git a/src-tauri/src/git.rs b/src-tauri/src/git.rs index b090d1d..bab89be 100644 --- a/src-tauri/src/git.rs +++ b/src-tauri/src/git.rs @@ -479,6 +479,11 @@ pub fn get_file_patch(path: String, file: String, staged: bool) -> Result Vec { + commit_ai::LOCAL_MODELS.to_vec() +} + #[tauri::command] pub async fn commit_ai_status( engine: tauri::State<'_, commit_ai::CommitAiEngine>, @@ -486,28 +491,91 @@ pub async fn commit_ai_status( Ok(engine.status().await) } +/// Kicks off the (first-run-only) download and model load in the background and returns +/// immediately; the frontend polls `commit_ai_status` to know when it's ready. #[tauri::command] -pub async fn commit_ai_generate( - path: String, - notes: Option, - engine: tauri::State<'_, commit_ai::CommitAiEngine>, -) -> Result { - let repo = resolve_repo(&path)?; +pub fn commit_ai_load(model_id: String, engine: tauri::State<'_, commit_ai::CommitAiEngine>) { + let engine = engine.inner().clone(); + tauri::async_runtime::spawn(async move { + engine.ensure_loaded(&model_id).await; + }); +} + +// The prompt is built from `git diff --cached` only, i.e. exactly the staged changes — +// unstaged edits and untracked files never influence the generated message. +fn staged_diff(repo: &Path) -> Result { + // Full staged file list (nothing excluded) so the model knows the complete scope + // even when the detailed diff below is filtered or truncated for context size. + let name_status = run_git(repo, ["diff", "--cached", "--name-status", "-M"])?; + let file_list = String::from_utf8_lossy(&name_status).trim().to_string(); + + // Generated lockfiles say nothing useful about intent but easily blow the small + // context window of local models, so keep them out of the detailed diff. let diff = run_git( - &repo, + repo, [ "diff", "--cached", "--no-ext-diff", "--no-textconv", "--unified=3", + "--", + ".", + ":(exclude)*package-lock.json", + ":(exclude)*pnpm-lock.yaml", + ":(exclude)*yarn.lock", + ":(exclude)*bun.lockb", + ":(exclude)*Cargo.lock", + ":(exclude)*composer.lock", + ":(exclude)*Gemfile.lock", + ":(exclude)*poetry.lock", + ":(exclude)*go.sum", ], )?; - let diff = String::from_utf8_lossy(&diff).to_string(); + let diff = String::from_utf8_lossy(&diff); - engine - .generate_commit_message(&diff, notes.as_deref()) - .await + if file_list.is_empty() { + return Ok(diff.to_string()); + } + Ok(format!("Staged files:\n{file_list}\n\n{diff}")) +} + +#[tauri::command] +pub async fn commit_ai_generate( + path: String, + notes: Option, + provider: String, + model: Option, + api_key: Option, + base_url: Option, + engine: tauri::State<'_, commit_ai::CommitAiEngine>, +) -> Result { + let repo = resolve_repo(&path)?; + let diff = staged_diff(&repo)?; + let notes = notes.as_deref(); + let model = model.filter(|value| !value.trim().is_empty()); + let api_key = api_key.filter(|value| !value.trim().is_empty()); + let base_url = base_url.filter(|value| !value.trim().is_empty()); + + match provider.as_str() { + "local" => engine.generate_commit_message(&diff, notes).await, + "openai" => { + let api_key = api_key.ok_or_else(|| "OpenAI-API-Key fehlt.".to_string())?; + let model = model.unwrap_or_else(|| "gpt-4o-mini".to_string()); + commit_ai::generate_openai(&api_key, &model, &diff, notes).await + } + "anthropic" => { + let api_key = api_key.ok_or_else(|| "Anthropic-API-Key fehlt.".to_string())?; + let model = model.unwrap_or_else(|| "claude-3-5-haiku-latest".to_string()); + commit_ai::generate_anthropic(&api_key, &model, &diff, notes).await + } + "custom" => { + let base_url = base_url.ok_or_else(|| "Endpoint-URL fehlt.".to_string())?; + let model = model.ok_or_else(|| "Modellname fehlt.".to_string())?; + commit_ai::generate_custom(&base_url, api_key.as_deref(), &model, &diff, notes).await + } + other => Err(format!("Unbekannter KI-Provider: {other}")), + } } #[tauri::command] diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 8fd5f5c..1422785 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -4,33 +4,22 @@ mod git; use git::{ SearchCancellationState, apply_file_patch, cancel_code_search, cancel_file_history, - checkout_branch, commit, commit_ai_generate, commit_ai_status, compare_commits, - compare_file_to_head, compare_file_to_parent, create_branch, cred_delete, cred_load, cred_save, - delete_branch, diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, - list_branches, list_commits, list_file_history, list_repository_files, merge_branch, - open_repo_in_explorer, open_repository, open_repository_bundle, open_repository_file, pull, - push, read_conflict, rename_branch, resolve_conflict, resolve_conflict_side, - restore_file_from_commit, restore_files, restore_to_commit, search_code_introductions, - stage_files, unstage_files, + checkout_branch, commit, commit_ai_generate, commit_ai_load, commit_ai_local_models, + commit_ai_status, compare_commits, compare_file_to_head, compare_file_to_parent, + create_branch, cred_delete, cred_load, cred_save, delete_branch, + diff_file_against_working_tree, get_file_patch, get_remote_url, get_status, list_branches, + list_commits, list_file_history, list_repository_files, merge_branch, open_repo_in_explorer, + open_repository, open_repository_bundle, open_repository_file, pull, push, read_conflict, + rename_branch, resolve_conflict, resolve_conflict_side, restore_file_from_commit, + restore_files, restore_to_commit, search_code_introductions, stage_files, unstage_files, }; fn main() { - let commit_ai_engine = commit_ai::CommitAiEngine::new(); - tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) .manage(SearchCancellationState::default()) - .manage(commit_ai_engine.clone()) + .manage(commit_ai::CommitAiEngine::new()) .plugin(tauri_plugin_dialog::init()) - .setup(move |_app| { - // Kick off the (first-run-only) download and model load in the background so the - // "Generate with AI" button becomes enabled once it's ready, without blocking startup. - let engine = commit_ai_engine.clone(); - tauri::async_runtime::spawn(async move { - engine.ensure_loaded().await; - }); - Ok(()) - }) .invoke_handler(tauri::generate_handler![ open_repository, open_repo_in_explorer, @@ -48,6 +37,8 @@ fn main() { apply_file_patch, commit, commit_ai_status, + commit_ai_load, + commit_ai_local_models, commit_ai_generate, pull, push, diff --git a/src/App.svelte b/src/App.svelte index b7b89eb..e96df25 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -5,6 +5,7 @@ import { AlertCircle, BookOpen, FolderOpen, GitBranch, GitMerge, LoaderCircle, Plus, Search, X } from "@lucide/svelte"; import TitleBar from "./lib/TitleBar.svelte"; + import AiSettingsDialog from "./lib/components/AiSettingsDialog.svelte"; import BranchPanel from "./lib/components/BranchPanel.svelte"; import CommitPanel from "./lib/components/CommitPanel.svelte"; import CompareDialog from "./lib/components/CompareDialog.svelte"; @@ -26,6 +27,8 @@ checkoutBranch, commit, commitAiGenerate, + commitAiLoad, + commitAiLocalModels, commitAiStatus, compareCommits, cancelCodeSearch, @@ -64,6 +67,7 @@ } from "./lib/git"; import type { + AiSettings, CommitAiPhase, ConflictFile, ExplorerNode, @@ -77,6 +81,7 @@ GitRepositoryFile, GitSearchHit, GitStatus, + LocalModelOption, PatchApplyAction, PreparedResolution, StoredCredential, @@ -104,6 +109,7 @@ const OPEN_REPOS_KEY = "gitlite.openRepos.v1"; const RECENT_REPOS_KEY = "gitlite.recentRepos.v1"; + const AI_SETTINGS_KEY = "gitlite.aiSettings.v1"; // ── State ────────────────────────────────────────────────────────────────── @@ -130,6 +136,9 @@ let commitAiPhase: CommitAiPhase = "idle"; let commitAiGenerating = false; let commitAiPollTimer: ReturnType | undefined; + let aiSettings: AiSettings = defaultAiSettings(); + let aiSettingsOpen = false; + let localModelOptions: LocalModelOption[] = []; let errorMessage = ""; let operation = ""; let compareFrom = ""; @@ -213,7 +222,7 @@ loadRepoLists(); autoRefreshTimer = setInterval(() => { void autoRefreshTick(); }, AUTO_REFRESH_INTERVAL); void checkForUpdates(); - startCommitAiPolling(); + void initCommitAi(); }); onDestroy(() => { @@ -256,29 +265,85 @@ // ── Commit AI ────────────────────────────────────────────────────────────── + function stopCommitAiPolling() { + if (commitAiPollTimer) { clearInterval(commitAiPollTimer); commitAiPollTimer = undefined; } + } + async function pollCommitAiStatus() { try { const result = await commitAiStatus(); commitAiPhase = result.phase; } catch { /* ignore transient errors */ } - if (commitAiPhase === "ready" || commitAiPhase === "error") { - if (commitAiPollTimer) { clearInterval(commitAiPollTimer); commitAiPollTimer = undefined; } - } + if (commitAiPhase === "ready" || commitAiPhase === "error") stopCommitAiPolling(); } function startCommitAiPolling() { - // The model downloads (first run only) and loads in the background on app start; - // poll until it's ready (or failed) so the "AI" button can enable itself. + // Only the local model has a download/load phase worth polling — cloud providers are + // plain API calls with nothing to wait for. + stopCommitAiPolling(); + if (aiSettings.provider !== "local") return; void pollCommitAiStatus(); commitAiPollTimer = setInterval(() => { void pollCommitAiStatus(); }, 2000); } + async function initCommitAi() { + aiSettings = loadAiSettings(); + try { + localModelOptions = await commitAiLocalModels(); + } catch { /* AI features stay disabled if this fails; not fatal to the app */ } + if (aiSettings.provider === "local") { + try { await commitAiLoad(aiSettings.localModelId); } catch { /* surfaced via status polling */ } + } + startCommitAiPolling(); + } + + function saveAiSettings(next: AiSettings) { + const modelChanged = next.provider === "local" && next.localModelId !== aiSettings.localModelId; + aiSettings = next; + persistAiSettings(next); + aiSettingsOpen = false; + if (next.provider === "local" && (modelChanged || commitAiPhase === "idle")) { + commitAiPhase = "idle"; + void commitAiLoad(next.localModelId); + } + startCommitAiPolling(); + } + async function generateCommitMessageWithAi() { - if (!activeRepoPath || commitAiPhase !== "ready" || commitAiGenerating) return; + if (!activeRepoPath || commitAiGenerating) return; + if (aiSettings.provider === "local" && commitAiPhase !== "ready") return; commitAiGenerating = true; errorMessage = ""; try { - commitMessage = await commitAiGenerate(activeRepoPath, commitMessage.trim() || undefined); + const notes = commitMessage.trim() || undefined; + if (aiSettings.provider === "local") { + commitMessage = await commitAiGenerate(activeRepoPath, { provider: "local", notes }); + } else if (aiSettings.provider === "openai") { + const cred = await credLoad("ai:openai"); + commitMessage = await commitAiGenerate(activeRepoPath, { + provider: "openai", + notes, + model: aiSettings.openaiModel, + apiKey: cred?.password, + }); + } else if (aiSettings.provider === "anthropic") { + const cred = await credLoad("ai:anthropic"); + commitMessage = await commitAiGenerate(activeRepoPath, { + provider: "anthropic", + notes, + model: aiSettings.anthropicModel, + apiKey: cred?.password, + }); + } else { + const cred = await credLoad("ai:custom"); + commitMessage = await commitAiGenerate(activeRepoPath, { + provider: "custom", + notes, + model: aiSettings.customModel, + baseUrl: aiSettings.customBaseUrl, + apiKey: cred?.password, + }); + } } catch (error) { errorMessage = errorToMessage(error); } finally { @@ -446,6 +511,37 @@ } } + function defaultAiSettings(): AiSettings { + return { + provider: "local", + localModelId: "qwen2.5-1.5b", + openaiModel: "gpt-4o-mini", + anthropicModel: "claude-3-5-haiku-latest", + customBaseUrl: "", + customModel: "", + }; + } + + function loadAiSettings(): AiSettings { + try { + const stored = JSON.parse(localStorage.getItem(AI_SETTINGS_KEY) ?? "null") as unknown; + if (stored && typeof stored === "object") { + return { ...defaultAiSettings(), ...(stored as Partial) }; + } + } catch { + // Fall through to defaults below. + } + return defaultAiSettings(); + } + + function persistAiSettings(next: AiSettings) { + try { + localStorage.setItem(AI_SETTINGS_KEY, JSON.stringify(next)); + } catch { + // Local storage is best-effort only; AI generation must keep working without it. + } + } + function rememberRecentRepo(path: string) { recentRepoPaths = uniqueRepoPaths([path, ...recentRepoPaths]).slice(0, 40); persistRepoLists(); @@ -1742,11 +1838,13 @@ {isBusy} {operation} {stagedCount} + commitAiProvider={aiSettings.provider} {commitAiPhase} {commitAiGenerating} onCommit={commitChanges} onCommitMessageChange={(msg) => { commitMessage = msg; }} onGenerateCommitMessage={generateCommitMessageWithAi} + onOpenAiSettings={() => { aiSettingsOpen = true; }} /> @@ -1850,6 +1948,16 @@ /> {/if} + +{#if aiSettingsOpen} + { aiSettingsOpen = false; }} + /> +{/if} + {#if compareSelectOpen} + import { onMount } from "svelte"; + import { AlertCircle, Bot, Check, Cpu, Eye, EyeOff, Globe, Key, LoaderCircle, X } from "@lucide/svelte"; + import { credDelete, credLoad, credSave } from "../git"; + import type { AiSettings, CommitAiProvider, LocalModelOption } from "../types"; + + interface Props { + settings: AiSettings; + localModels: LocalModelOption[]; + onSave: (settings: AiSettings) => void; + onClose: () => void; + } + + let { settings, localModels = [], onSave, onClose }: Props = $props(); + + type CloudProvider = Exclude; + + const CRED_KEYS: Record = { + openai: "ai:openai", + anthropic: "ai:anthropic", + custom: "ai:custom", + }; + + let provider = $state("local"); + let localModelId = $state(""); + let openaiModel = $state(""); + let anthropicModel = $state(""); + let customBaseUrl = $state(""); + let customModel = $state(""); + + let openaiApiKey = $state(""); + let anthropicApiKey = $state(""); + let customApiKey = $state(""); + let showKey = $state(false); + let loadingKeys = $state(true); + let saving = $state(false); + let error = $state(""); + + $effect(() => { + provider = settings.provider; + localModelId = settings.localModelId; + openaiModel = settings.openaiModel; + anthropicModel = settings.anthropicModel; + customBaseUrl = settings.customBaseUrl; + customModel = settings.customModel; + }); + + onMount(() => { + (async () => { + try { + const [openai, anthropic, custom] = await Promise.all([ + credLoad(CRED_KEYS.openai), + credLoad(CRED_KEYS.anthropic), + credLoad(CRED_KEYS.custom), + ]); + openaiApiKey = openai?.password ?? ""; + anthropicApiKey = anthropic?.password ?? ""; + customApiKey = custom?.password ?? ""; + } catch (err) { + error = err instanceof Error ? err.message : String(err); + } finally { + loadingKeys = false; + } + })(); + }); + + async function persistKey(target: CloudProvider, value: string) { + const key = CRED_KEYS[target]; + const trimmed = value.trim(); + if (trimmed) { + await credSave(key, "api-key", trimmed, null); + } else { + await credDelete(key); + } + } + + async function handleSave() { + saving = true; + error = ""; + try { + await Promise.all([ + persistKey("openai", openaiApiKey), + persistKey("anthropic", anthropicApiKey), + persistKey("custom", customApiKey), + ]); + onSave({ + provider, + localModelId, + openaiModel: openaiModel.trim() || "gpt-4o-mini", + anthropicModel: anthropicModel.trim() || "claude-3-5-haiku-latest", + customBaseUrl: customBaseUrl.trim(), + customModel: customModel.trim(), + }); + } catch (err) { + error = err instanceof Error ? err.message : String(err); + } finally { + saving = false; + } + } + + function formatSize(mb: number): string { + return mb >= 1000 ? `${(mb / 1000).toFixed(1)} GB` : `${mb} MB`; + } + + let selectedLocalModel = $derived(localModels.find((option) => option.id === localModelId)); + + + diff --git a/src/lib/components/CommitPanel.svelte b/src/lib/components/CommitPanel.svelte index c813f20..7f60c53 100644 --- a/src/lib/components/CommitPanel.svelte +++ b/src/lib/components/CommitPanel.svelte @@ -1,6 +1,6 @@ @@ -82,15 +91,25 @@ type="button" onclick={onGenerateCommitMessage} disabled={!canGenerate} - title={aiButtonTitle(commitAiPhase, stagedCount)} + title={aiButtonTitle(commitAiProvider, commitAiPhase, stagedCount)} > - {#if commitAiGenerating || commitAiPhase === "loading"} + {#if commitAiGenerating || localModelLoading}