diff --git a/deno.lock b/deno.lock index ee9f35c..a43a3c3 100644 --- a/deno.lock +++ b/deno.lock @@ -12,8 +12,10 @@ "npm:@tailwindcss/vite@^4.1.12": "4.1.12_vite@6.3.5__picomatch@4.0.3", "npm:@tauri-apps/api@2": "2.8.0", "npm:@tauri-apps/cli@2": "2.8.2", + "npm:@tauri-apps/plugin-http@~2.5.2": "2.5.2", "npm:@tauri-apps/plugin-opener@2": "2.5.0", "npm:@tauri-apps/plugin-positioner@2.3": "2.3.0", + "npm:@tauri-apps/plugin-store@2.4": "2.4.0", "npm:@tauri-apps/plugin-window-state@2.4": "2.4.0", "npm:svelte-check@4": "4.3.1_svelte@5.38.3__acorn@8.15.0_typescript@5.6.3", "npm:svelte@5": "5.38.3_acorn@8.15.0", @@ -614,6 +616,12 @@ ], "bin": true }, + "@tauri-apps/plugin-http@2.5.2": { + "integrity": "sha512-x1mQKHSLDk4mS2S938OTeyk8L7QyLpCrKZCZcjkljGsvTvRMojCvI9SeJ1kaxc7t8xSilkC7WdId8xER9TIGLg==", + "dependencies": [ + "@tauri-apps/api" + ] + }, "@tauri-apps/plugin-opener@2.5.0": { "integrity": "sha512-B0LShOYae4CZjN8leiNDbnfjSrTwoZakqKaWpfoH6nXiJwt6Rgj6RnVIffG3DoJiKsffRhMkjmBV9VeilSb4TA==", "dependencies": [ @@ -626,6 +634,12 @@ "@tauri-apps/api" ] }, + "@tauri-apps/plugin-store@2.4.0": { + "integrity": "sha512-PjBnlnH6jyI71MGhrPaxUUCsOzc7WO1mbc4gRhME0m2oxLgCqbksw6JyeKQimuzv4ysdpNO3YbmaY2haf82a3A==", + "dependencies": [ + "@tauri-apps/api" + ] + }, "@tauri-apps/plugin-window-state@2.4.0": { "integrity": "sha512-hRSzPNi2NG0lPFthfVY0V5C1MyWN/gGaQtQYw7i9zZhLzrhZveHZ2omHG1rIiIsjfTGbO7fhjydSoeTTK9GqLw==", "dependencies": [ @@ -1112,8 +1126,10 @@ "npm:@tailwindcss/vite@^4.1.12", "npm:@tauri-apps/api@2", "npm:@tauri-apps/cli@2", + "npm:@tauri-apps/plugin-http@~2.5.2", "npm:@tauri-apps/plugin-opener@2", "npm:@tauri-apps/plugin-positioner@2.3", + "npm:@tauri-apps/plugin-store@2.4", "npm:@tauri-apps/plugin-window-state@2.4", "npm:svelte-check@4", "npm:svelte@5", diff --git a/package.json b/package.json index 41fc4f2..9d1a1ce 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,10 @@ "@iconify/tailwind4": "^1.0.6", "@tailwindcss/vite": "^4.1.12", "@tauri-apps/api": "^2", + "@tauri-apps/plugin-http": "~2.5.2", "@tauri-apps/plugin-opener": "^2", "@tauri-apps/plugin-positioner": "~2.3.0", + "@tauri-apps/plugin-store": "~2.4.0", "@tauri-apps/plugin-window-state": "~2.4.0", "tailwindcss": "^4.1.12" }, diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 886a73e..1f56196 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -539,10 +539,29 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" dependencies = [ + "percent-encoding", "time", "version_check", ] +[[package]] +name = "cookie_store" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" +dependencies = [ + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -873,6 +892,12 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +[[package]] +name = "data-url" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be1e0bca6c3637f992fc1cc7cbc52a78c1ef6db076dbf1059c4323d6a2048376" + [[package]] name = "dbus" version = "0.9.9" @@ -998,6 +1023,15 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + [[package]] name = "dpi" version = "0.1.2" @@ -1054,6 +1088,15 @@ version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef6b89e5b37196644d8796de5268852ff179b44e96276cf4290264843743bb7" +[[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 = "endi" version = "1.1.0" @@ -1451,8 +1494,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -1462,9 +1507,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", ] [[package]] @@ -1621,6 +1668,25 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "h2" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.11.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1719,6 +1785,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2", "http", "http-body", "httparse", @@ -1730,6 +1797,39 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.16" @@ -1749,9 +1849,11 @@ dependencies = [ "percent-encoding", "pin-project-lite", "socket2", + "system-configuration", "tokio", "tower-service", "tracing", + "windows-registry", ] [[package]] @@ -2176,6 +2278,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +[[package]] +name = "litrs" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" + [[package]] name = "lock_api" version = "0.4.13" @@ -2192,6 +2300,12 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[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" @@ -2288,14 +2402,17 @@ dependencies = [ "dasp", "futures-util", "keyring", + "reqwest", "serde", "serde_json", "strum", "tauri", "tauri-build", + "tauri-plugin-http", "tauri-plugin-opener", "tauri-plugin-positioner", "tauri-plugin-single-instance", + "tauri-plugin-store", "tauri-plugin-window-state", "tokio", "tokio-tungstenite", @@ -3170,6 +3287,22 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" +dependencies = [ + "idna", + "psl-types", +] + [[package]] name = "quick-xml" version = "0.38.3" @@ -3179,6 +3312,61 @@ dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.16", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.16", + "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.40" @@ -3387,22 +3575,35 @@ checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" dependencies = [ "base64 0.22.1", "bytes", + "cookie", + "cookie_store", + "encoding_rs", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", "hyper", + "hyper-rustls", + "hyper-tls", "hyper-util", "js-sys", "log", + "mime", + "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -3412,6 +3613,21 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] @@ -3420,6 +3636,12 @@ version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -3442,6 +3664,41 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "rustls" +version = "0.23.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -3940,6 +4197,12 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "swift-rs" version = "1.0.7" @@ -3993,6 +4256,27 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.3", + "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" @@ -4195,6 +4479,52 @@ dependencies = [ "walkdir", ] +[[package]] +name = "tauri-plugin-fs" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "315784ec4be45e90a987687bae7235e6be3d6e9e350d2b75c16b8a4bf22c1db7" +dependencies = [ + "anyhow", + "dunce", + "glob", + "percent-encoding", + "schemars 0.8.22", + "serde", + "serde_json", + "serde_repr", + "tauri", + "tauri-plugin", + "tauri-utils", + "thiserror 2.0.16", + "toml 0.9.5", + "url", +] + +[[package]] +name = "tauri-plugin-http" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "938a3d7051c9a82b431e3a0f3468f85715b3442b3c3a3913095e9fa509e2652c" +dependencies = [ + "bytes", + "cookie_store", + "data-url", + "http", + "regex", + "reqwest", + "schemars 0.8.22", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "tauri-plugin-fs", + "thiserror 2.0.16", + "tokio", + "url", + "urlpattern", +] + [[package]] name = "tauri-plugin-opener" version = "2.5.0" @@ -4247,6 +4577,22 @@ dependencies = [ "zbus", ] +[[package]] +name = "tauri-plugin-store" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d85dd80d60a76ee2c2fdce09e9ef30877b239c2a6bb76e6d7d03708aa5f13a19" +dependencies = [ + "dunce", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 2.0.16", + "tokio", + "tracing", +] + [[package]] name = "tauri-plugin-window-state" version = "2.4.0" @@ -4467,6 +4813,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.47.1" @@ -4481,9 +4842,21 @@ dependencies = [ "pin-project-lite", "slab", "socket2", + "tokio-macros", "windows-sys 0.59.0", ] +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "tokio-native-tls" version = "0.3.1" @@ -4494,6 +4867,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-tungstenite" version = "0.27.0" @@ -4814,6 +5197,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.7" @@ -5034,6 +5423,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 = "webkit2gtk" version = "2.0.1" @@ -5078,6 +5477,15 @@ dependencies = [ "system-deps", ] +[[package]] +name = "webpki-roots" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "webview2-com" version = "0.38.0" @@ -5264,6 +5672,17 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link", + "windows-result 0.3.4", + "windows-strings", +] + [[package]] name = "windows-result" version = "0.1.2" @@ -5300,6 +5719,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ae7e95b..ef36bff 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -30,6 +30,9 @@ tokio = "1.47.1" dasp = { version = "0.11.0", features = ["all"] } keyring = { version = "3.6.3", features = ["apple-native", "windows-native", "sync-secret-service"] } strum = {version = "0.27.2", features = ["derive"] } +tauri-plugin-store = "2" +tauri-plugin-http = "2" +reqwest = { version = "0.12.23", features = ["json"]} [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] tauri-plugin-positioner = "2" diff --git a/src-tauri/src/letta/commands.rs b/src-tauri/src/letta/commands.rs new file mode 100644 index 0000000..8e31716 --- /dev/null +++ b/src-tauri/src/letta/commands.rs @@ -0,0 +1,40 @@ +use crate::{ + letta::{LettaAgentInfo, LettaConfig}, + state::AppState, +}; + +#[tauri::command] +pub async fn list_agents(state: tauri::State<'_, AppState>) -> Result, ()> { + Ok(state.letta_manager.list_agents().await) +} + +#[tauri::command] +pub async fn get_config(state: tauri::State<'_, AppState>) -> Result { + let config = state.letta_manager.config.lock().await; + + Ok(config.clone()) +} + +#[tauri::command] +pub async fn update_config( + state: tauri::State<'_, AppState>, + base_url: Option, + agent_id: Option, +) -> Result<(), ()> { + let mut config = state.letta_manager.config.lock().await; + + *config = LettaConfig { + base_url: if base_url.is_some() { + base_url.unwrap() + } else { + config.base_url.clone() + }, + agent_id: if agent_id.is_some() { + agent_id.unwrap() + } else { + config.agent_id.clone() + }, + }; + + Ok(()) +} diff --git a/src-tauri/src/letta/mod.rs b/src-tauri/src/letta/mod.rs new file mode 100644 index 0000000..6ece33e --- /dev/null +++ b/src-tauri/src/letta/mod.rs @@ -0,0 +1,85 @@ +use std::sync::Arc; + +use reqwest::Client; +use serde::{Deserialize, Serialize}; +use serde_json::from_value; +use tauri::async_runtime::Mutex; +use tauri::Wry; +use tauri_plugin_store::Store; + +use crate::secrets::SecretsManager; + +pub mod commands; + +#[derive(Serialize, Deserialize, Clone)] +struct LettaConfig { + base_url: String, + agent_id: String, +} + +#[derive(Serialize, Deserialize)] +pub struct LettaAgentInfo { + id: String, + name: String, +} + +pub struct LettaManager { + http_client: Client, + secrets_manager: Arc, + store: Arc>, + config: Arc>, +} +impl LettaManager { + pub fn new( + http_client: Client, + store: Arc>, + secrets_manager: Arc, + ) -> Self { + match store.get("letta-config") { + Some(config) => Self { + http_client, + secrets_manager, + store, + config: Arc::new(Mutex::new( + from_value::(config).expect("failed to deserialize Letta config"), + )), + }, + None => Self { + http_client, + secrets_manager, + store, + config: Arc::new(Mutex::new(LettaConfig { + base_url: "https://api.letta.com".to_string(), + agent_id: "".to_string(), + })), + }, + } + } + + pub async fn list_agents(&self) -> Vec { + match self + .secrets_manager + .get_secret(crate::secrets::SecretName::LettaApiKey) + { + Ok(api_key) => { + let config = self.config.lock().await; + let base_url = config.base_url.clone(); + let req = self + .http_client + .get(format!("{base_url}/api/v1/agents")) + .header("Authorization", format!("Bearer {api_key}")); + + let res = req + .send() + .await + .expect("failed to list Letta agents") + .json::>() + .await + .expect("failed to parse agent list result"); + + res + } + Err(_) => Vec::new(), + } + } +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index d22f3fb..50f2401 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,22 +1,20 @@ use crate::state::AppState; use tauri::{Manager, WebviewUrl, WebviewWindowBuilder}; use tauri_plugin_positioner::{Position, WindowExt}; +use tauri_plugin_store::StoreExt; use tauri_plugin_window_state::{StateFlags, WindowExt as StateWindowExt}; mod cartesia; mod devices; +mod letta; mod secrets; mod state; -// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/ -#[tauri::command] -fn greet(name: &str) -> String { - format!("Hello, {}! You've been greeted from Rust!", name) -} - #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let mut builder = tauri::Builder::default() + .plugin(tauri_plugin_http::init()) + .plugin(tauri_plugin_store::Builder::new().build()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_window_state::Builder::new().build()) .plugin(tauri_plugin_positioner::init()); @@ -35,7 +33,8 @@ pub fn run() { builder .setup(|app| { - let app_state = AppState::new().expect("failed to initialize application state"); + let store = app.store("config.json")?; + let app_state = AppState::new(store).expect("failed to initialize application state"); app.manage(app_state); @@ -69,6 +68,9 @@ pub fn run() { .invoke_handler(tauri::generate_handler![ cartesia::commands::start_stt, cartesia::commands::stop_stt, + letta::commands::list_agents, + letta::commands::get_config, + letta::commands::update_config, secrets::commands::has_secret, secrets::commands::set_secret, secrets::commands::delete_secret, diff --git a/src-tauri/src/secrets/mod.rs b/src-tauri/src/secrets/mod.rs index a9f380d..ebda7c4 100644 --- a/src-tauri/src/secrets/mod.rs +++ b/src-tauri/src/secrets/mod.rs @@ -7,6 +7,8 @@ pub mod commands; pub enum SecretName { #[strum(to_string = "cartesia_api_key")] CartesiaApiKey, + #[strum(to_string = "letta_api_key")] + LettaApiKey, } const SERVICE_NAME: &'static str = "miwiwi"; diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index 84bb02d..e842296 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -1,24 +1,38 @@ use std::sync::Arc; +use tauri::Wry; +use tauri_plugin_http::reqwest::Client; +use tauri_plugin_store::Store; + use crate::{ cartesia::{client::CartesiaClient, stt::SttManager}, devices::{input::InputDeviceManager, output::OutputDeviceManager, types::AudioDeviceError}, + letta::LettaManager, secrets::SecretsManager, }; pub struct AppState { pub cartesia_client: Arc, pub stt_manager: Arc, + pub letta_manager: Arc, pub secrets_manager: Arc, pub input_device_manager: Arc, pub output_device_manager: Arc, } impl AppState { - pub fn new() -> Result { + pub fn new(store: Arc>) -> Result { let input_device_manager = Arc::new(InputDeviceManager::new()?); let output_device_manager = Arc::new(OutputDeviceManager::new()?); let secrets_manager = Arc::new(SecretsManager::new()); + + let http_client = Client::new(); + let letta_manager = Arc::new(LettaManager::new( + http_client, + store.clone(), + secrets_manager.clone(), + )); + let cartesia_client = Arc::new(CartesiaClient::new(secrets_manager.clone())); let stt_manager = Arc::new(SttManager::new( cartesia_client.clone(), @@ -29,6 +43,7 @@ impl AppState { input_device_manager, output_device_manager, secrets_manager, + letta_manager, cartesia_client, stt_manager, })