diff --git a/Cargo.lock b/Cargo.lock index b53bebe..a9b16a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,7 @@ dependencies = [ name = "ai-desktop-app" version = "0.1.0" dependencies = [ + "feshared", "serde", "serde_json", "shared", @@ -47,6 +48,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" @@ -58,9 +65,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "async-broadcast" @@ -216,6 +223,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -305,6 +321,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bitflags" version = "1.3.2" @@ -557,6 +579,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "convert_case" version = "0.4.0" @@ -641,6 +669,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.5.0" @@ -659,6 +702,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -716,8 +768,11 @@ dependencies = [ name = "daemon" version = "0.1.0" dependencies = [ + "anyhow", + "directories", "genai", "shared", + "sqlx", "tokio", "tonic", "tonic-reflection", @@ -758,6 +813,17 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.5.5" @@ -831,7 +897,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", + "subtle", +] + +[[package]] +name = "directories" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d" +dependencies = [ + "dirs-sys", ] [[package]] @@ -905,6 +982,12 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dpi" version = "0.1.2" @@ -946,6 +1029,9 @@ name = "either" version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] [[package]] name = "embed-resource" @@ -1030,6 +1116,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "5.4.1" @@ -1077,6 +1174,13 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "feshared" +version = "0.1.0" +dependencies = [ + "serde", +] + [[package]] name = "field-offset" version = "0.3.6" @@ -1109,6 +1213,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1215,6 +1330,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -1660,6 +1786,8 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ + "allocator-api2", + "equivalent", "foldhash", ] @@ -1669,6 +1797,15 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "heck" version = "0.4.1" @@ -1693,6 +1830,33 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "html5ever" version = "0.29.1" @@ -2167,6 +2331,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libappindicator" @@ -2208,6 +2375,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.12" @@ -2216,6 +2389,18 @@ checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ "bitflags 2.10.0", "libc", + "redox_syscall 0.7.0", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", ] [[package]] @@ -2294,6 +2479,16 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.6" @@ -2431,12 +2626,48 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2444,6 +2675,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2769,7 +3001,7 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link 0.2.1", ] @@ -2780,6 +3012,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2974,6 +3215,27 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.32" @@ -3406,6 +3668,15 @@ dependencies = [ "bitflags 2.10.0", ] +[[package]] +name = "redox_syscall" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f3fe0889e69e2ae9e41f4d6c4c0181701d00e4697b356fb1f74173a5e0ee27" +dependencies = [ + "bitflags 2.10.0", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -3558,6 +3829,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-hash" version = "2.1.1" @@ -3969,6 +4260,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -4007,6 +4309,16 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.8" @@ -4036,6 +4348,9 @@ name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] [[package]] name = "socket2" @@ -4062,7 +4377,7 @@ dependencies = [ "objc2-foundation", "objc2-quartz-core", "raw-window-handle", - "redox_syscall", + "redox_syscall 0.5.18", "tracing", "wasm-bindgen", "web-sys", @@ -4095,6 +4410,213 @@ dependencies = [ "system-deps", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64 0.22.1", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.5", + "hashlink", + "indexmap 2.13.0", + "log", + "memchr", + "once_cell", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.114", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.114", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.10.0", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.18", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.10.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.18", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror 2.0.18", + "tracing", + "url", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -4126,6 +4648,17 @@ dependencies = [ "quote", ] +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -4966,6 +5499,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5089,12 +5623,33 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -5173,6 +5728,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version-compare" version = "0.2.1" @@ -5245,6 +5806,12 @@ dependencies = [ "wit-bindgen", ] +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + [[package]] name = "wasm-bindgen" version = "0.2.108" @@ -5439,6 +6006,16 @@ dependencies = [ "windows-core 0.61.2", ] +[[package]] +name = "whoami" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" +dependencies = [ + "libredox", + "wasite", +] + [[package]] name = "winapi" version = "0.3.9" @@ -5644,6 +6221,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" @@ -5695,6 +6281,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" @@ -5752,6 +6353,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" @@ -5770,6 +6377,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" @@ -5788,6 +6401,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" @@ -5818,6 +6437,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" @@ -5836,6 +6461,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" @@ -5854,6 +6485,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" @@ -5872,6 +6509,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" diff --git a/Cargo.toml b/Cargo.toml index e8ac883..c57bea6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] -members = ["frontend/src-tauri", "crates/shared", "crates/daemon"] +members = ["frontend/src-tauri", "crates/shared", "crates/daemon", "crates/feshared"] resolver = "2" diff --git a/crates/daemon/Cargo.toml b/crates/daemon/Cargo.toml index d284f3b..c0c657e 100644 --- a/crates/daemon/Cargo.toml +++ b/crates/daemon/Cargo.toml @@ -4,8 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1.0.101" +directories = "6.0.0" genai = "0.5.3" shared = { path = "../shared" } +sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite", "macros"] } tokio = { version = "1.49.0", features = ["full"] } tonic = "0.14.2" tonic-reflection = "0.14.2" diff --git a/crates/daemon/src/chatpersistence.rs b/crates/daemon/src/chatpersistence.rs new file mode 100644 index 0000000..535982b --- /dev/null +++ b/crates/daemon/src/chatpersistence.rs @@ -0,0 +1,83 @@ +use anyhow::Result; +use directories::ProjectDirs; +use sqlx::sqlite::SqliteConnectOptions; +use sqlx::Row; +use sqlx::SqlitePool; +use tokio::fs; +use tonic::async_trait; + +pub struct ChatMessage { + pub id: i64, + pub text: String, + pub is_user: bool, +} + +#[async_trait] +pub trait ChatRepository { + async fn save_message(&self, text: &str, is_user: &bool) -> Result<()>; + async fn get_all_messages(&self) -> Result>; +} + +pub struct SqliteChatRepository { + pool: SqlitePool, +} + +impl SqliteChatRepository { + pub async fn new() -> Result { + let project_dirs = ProjectDirs::from("com", "jarno", "wsagent") + .ok_or_else(|| anyhow::anyhow!("Could not find home directory!"))?; + let config_dir = project_dirs.config_dir(); + fs::create_dir_all(config_dir).await?; + let db_path = config_dir.join("agent.db"); + let connection_str = format!("sqlite:{}", db_path.display()); + println!("Connection string: {}", connection_str); + + let pool = SqlitePool::connect_with( + SqliteConnectOptions::new() + .filename(&db_path) + .create_if_missing(true), + ) + .await?; + + sqlx::query( + "CREATE TABLE IF NOT EXISTS message ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + text TEXT NOT NULL, + is_user BOOL NOT NULL + )", + ) + .execute(&pool) + .await?; + + Ok(Self { pool }) + } +} + +#[async_trait] +impl ChatRepository for SqliteChatRepository { + async fn save_message(&self, text: &str, is_user: &bool) -> Result<()> { + sqlx::query("INSERT INTO messages (text, is_user) values (?, ?)") + .bind(text) + .bind(is_user) + .execute(&self.pool) + .await?; + Ok(()) + } + + async fn get_all_messages(&self) -> Result> { + let rows = sqlx::query("SELECT id, text, is_user FROM messages ORDER BY id DESC LIMIT 10") + .fetch_all(&self.pool) + .await?; + + let messages = rows + .into_iter() + .map(|row| ChatMessage { + id: row.get(0), + text: row.get(1), + is_user: row.get(2), + }) + .collect(); + + Ok(messages) + } +} diff --git a/crates/daemon/src/main.rs b/crates/daemon/src/main.rs index f023a7b..3381f55 100644 --- a/crates/daemon/src/main.rs +++ b/crates/daemon/src/main.rs @@ -1,9 +1,16 @@ -use genai::chat::{ChatMessage, ChatRequest}; +mod chatpersistence; + +use genai::chat::{ChatMessage, ChatRequest, ChatResponse}; use genai::Client; use shared::ai::ai_daemon_server::{AiDaemon, AiDaemonServer}; -use shared::ai::{PromptRequest, PromptResponse}; +use shared::ai::{ + ChatHistoryRequest, ChatHistoryResponse, ChatRequest as CRequest, ChatResponse as CResponse, + PromptRequest, PromptResponse, +}; use tonic::{transport::Server, Request, Response, Status}; +use chatpersistence::SqliteChatRepository; + #[derive(Default)] pub struct DaemonServer {} @@ -24,6 +31,27 @@ impl AiDaemon for DaemonServer { let reply = PromptResponse { response: response }; Ok(Response::new(reply)) } + + async fn chat(&self, request: Request) -> Result, Status> { + let response = CResponse { + id: 1, + chat_id: 1, + text: "asdf".to_string(), + is_user: false, + }; + return Ok(Response::new(response)); + } + + async fn chat_history( + &self, + request: Request, + ) -> Result, Status> { + let response = ChatHistoryResponse { + chat_id: 1, + history: vec![], + }; + Ok(Response::new(response)) + } } async fn prompt_ollama( @@ -42,6 +70,8 @@ async fn prompt_ollama( #[tokio::main] async fn main() -> Result<(), Box> { + let chat_repo = SqliteChatRepository::new().await?; + let addr_s = "[::1]:50051"; let addr = addr_s.parse().unwrap(); let daemon = DaemonServer::default(); diff --git a/crates/feshared/Cargo.toml b/crates/feshared/Cargo.toml new file mode 100644 index 0000000..45ff87c --- /dev/null +++ b/crates/feshared/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "feshared" +version = "0.1.0" +edition = "2021" + +[dependencies] +serde = "1.0.228" diff --git a/crates/feshared/src/lib.rs b/crates/feshared/src/lib.rs new file mode 100644 index 0000000..ab15901 --- /dev/null +++ b/crates/feshared/src/lib.rs @@ -0,0 +1,16 @@ +pub mod chatmessage { + use serde::{Deserialize, Serialize}; + + #[derive(Clone, Debug, Deserialize, Serialize)] + pub struct Message { + pub id: i64, + pub text: String, + pub is_user: bool, + } + + #[derive(Clone, Debug, Deserialize, Serialize)] + pub struct MessageHistory { + pub chat_id: i64, + pub history: Vec, + } +} diff --git a/crates/shared/proto/api.proto b/crates/shared/proto/api.proto index 70122ef..f62e766 100644 --- a/crates/shared/proto/api.proto +++ b/crates/shared/proto/api.proto @@ -2,13 +2,37 @@ syntax = "proto3"; package ai_daemon; service AiDaemon { - rpc Prompt (PromptRequest) returns (PromptResponse); + rpc Prompt(PromptRequest) returns (PromptResponse); + rpc Chat(ChatRequest) returns (ChatResponse); + rpc ChatHistory(ChatHistoryRequest) returns (ChatHistoryResponse); +} + +message ChatResponse { + int64 id = 1; + int64 chat_id = 2; + string text = 10; + bool is_user = 20; +} + +message ChatRequest { + optional int64 chat_id = 1; + optional string text = 10; +} + +message ChatHistoryRequest { + // If not set last chat is returned + optional int64 chat_id = 1; +} + +message ChatHistoryResponse { + int64 chat_id = 1; + repeated ChatResponse history = 10; } message PromptRequest { - string prompt = 1; + string prompt = 1; } message PromptResponse { - string response = 1; + string response = 1; } diff --git a/crates/shared/src/lib.rs b/crates/shared/src/lib.rs index cd6d7c9..68dc2e0 100644 --- a/crates/shared/src/lib.rs +++ b/crates/shared/src/lib.rs @@ -1,5 +1,6 @@ pub mod ai { tonic::include_proto!("ai_daemon"); - pub const FILE_DESCRIPTOR_SET: &[u8] = tonic::include_file_descriptor_set!("ai_service_descriptor"); -} \ No newline at end of file + pub const FILE_DESCRIPTOR_SET: &[u8] = + tonic::include_file_descriptor_set!("ai_service_descriptor"); +} diff --git a/frontend/Cargo.lock b/frontend/Cargo.lock index f488245..5f0baad 100644 --- a/frontend/Cargo.lock +++ b/frontend/Cargo.lock @@ -21,6 +21,7 @@ dependencies = [ name = "ai-desktop-app" version = "0.1.0" dependencies = [ + "feshared", "serde", "serde_json", "shared", @@ -37,6 +38,7 @@ name = "ai-desktop-app-ui" version = "0.1.0" dependencies = [ "console_error_panic_hook", + "feshared", "js-sys", "leptos", "leptos_router", @@ -1159,6 +1161,13 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "feshared" +version = "0.1.0" +dependencies = [ + "serde", +] + [[package]] name = "field-offset" version = "0.3.6" diff --git a/frontend/Cargo.toml b/frontend/Cargo.toml index 4b1e4f6..7475cff 100644 --- a/frontend/Cargo.toml +++ b/frontend/Cargo.toml @@ -14,6 +14,7 @@ serde-wasm-bindgen = "0.6" console_error_panic_hook = "0.1.7" leptos_router = "0.8.11" serde_json = "1.0.149" +feshared = {path = "../crates/feshared"} [workspace] members = ["src-tauri"] diff --git a/frontend/src-tauri/Cargo.toml b/frontend/src-tauri/Cargo.toml index 9a8e1df..4b64d71 100644 --- a/frontend/src-tauri/Cargo.toml +++ b/frontend/src-tauri/Cargo.toml @@ -23,6 +23,7 @@ tauri-plugin-opener = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" shared = { path = "../../crates/shared" } +feshared = { path = "../../crates/feshared" } tonic = "0.14.2" tokio = "1.49.0" diff --git a/frontend/src-tauri/src/main.rs b/frontend/src-tauri/src/main.rs index ee3fc7b..edd9d45 100644 --- a/frontend/src-tauri/src/main.rs +++ b/frontend/src-tauri/src/main.rs @@ -1,12 +1,11 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use tokio::sync::Mutex; - -use tauri::{Emitter, Manager, State, WindowEvent}; -use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState}; - +use feshared::chatmessage::{Message, MessageHistory}; use shared::ai::{ai_daemon_client::AiDaemonClient, PromptRequest}; +use tauri::{Emitter, Manager, State}; +use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState}; +use tokio::sync::Mutex; struct AppState { grpc_client: Mutex>, @@ -42,6 +41,25 @@ async fn prompt_llm(state: State<'_, AppState>, prompt: String) -> Result, + chat_id: Option, +) -> Result { + let history = MessageHistory { + chat_id: match chat_id { + Some(id) => id, + None => -1, + }, + history: vec![Message { + id: 1, + text: String::from("asd"), + is_user: false, + }], + }; + Ok(history) +} + #[tokio::main] async fn main() { let channel = tonic::transport::Channel::from_static("http://[::1]:50051") @@ -56,7 +74,11 @@ async fn main() { grpc_client: Mutex::new(client), }) .plugin(tauri_plugin_global_shortcut::Builder::new().build()) - .invoke_handler(tauri::generate_handler![toggle_popup, prompt_llm]) + .invoke_handler(tauri::generate_handler![ + toggle_popup, + prompt_llm, + chat_history + ]) .setup(|app| { /* Auto-hide popup when focus is lost if let Some(window) = app.get_webview_window("popup") { diff --git a/frontend/src/popup.rs b/frontend/src/popup.rs index d0433dd..a90c8c5 100644 --- a/frontend/src/popup.rs +++ b/frontend/src/popup.rs @@ -1,15 +1,9 @@ use crate::bridge::invoke; +use feshared::chatmessage::{Message, MessageHistory}; use leptos::{ev::keydown, html::Input, prelude::*}; use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; use wasm_bindgen_futures::spawn_local; -#[derive(Clone, Debug)] -struct Message { - id: usize, - text: String, - is_user: bool, -} - #[component] pub fn Popup() -> impl IntoView { // Prompt signals and and action @@ -34,7 +28,7 @@ pub fn Popup() -> impl IntoView { if let Some(result) = prompt_action.value().get() { set_messages.update(|previous| { previous.push(Message { - id: previous.len(), + id: previous.len() as i64, text: result, is_user: false, }); @@ -66,6 +60,12 @@ pub fn Popup() -> impl IntoView { } }); + spawn_local(async move { + let response = invoke("chat_history", JsValue::bigint_from_str("1")).await; + let history: MessageHistory = serde_wasm_bindgen::from_value(response).unwrap(); + set_messages.set(history.history.clone()); + }); + view! {

"AI quick action"

@@ -79,7 +79,7 @@ pub fn Popup() -> impl IntoView { if ev.key() == "Enter" { set_messages.update(|previous| { previous.push(Message { - id: previous.len(), + id: previous.len() as i64, text: prompt_text.get(), is_user: true, }); diff --git a/frontend/styles.css b/frontend/styles.css index 73e4320..bbc52c2 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -25,14 +25,27 @@ body { .response-area { width: 100%; height: 300px; - overflow-y: scroll; + overflow-y: auto; } .msg { margin: 1px; border: solid 1px #808080; + animation: slideIn 0.3s ease-out; + max-width: 70%; } .msg-user { text-align: end; } + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(10px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +}