diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..1943d61 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +* +!llm.py +!kitt.py \ No newline at end of file diff --git a/meet/.eslintrc.json b/.eslintrc.json similarity index 100% rename from meet/.eslintrc.json rename to .eslintrc.json diff --git a/meet/.prettierignore b/.prettierignore similarity index 100% rename from meet/.prettierignore rename to .prettierignore diff --git a/meet/.prettierrc b/.prettierrc similarity index 100% rename from meet/.prettierrc rename to .prettierrc diff --git a/.taplo.toml b/.taplo.toml deleted file mode 100644 index 2aea1c0..0000000 --- a/.taplo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[[rule]] -keys = ["dependencies", "*-dependencies"] - -[rule.formatting] -reorder_keys = true -indent_tables = true diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 916339a..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,6850 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "ab_glyph" -version = "0.2.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80179d7dd5d7e8c285d67c4a1e652972a92de7475beddfb92028c76463b13225" -dependencies = [ - "ab_glyph_rasterizer", - "owned_ttf_parser", -] - -[[package]] -name = "ab_glyph_rasterizer" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" - -[[package]] -name = "accesskit" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cb10ed32c63247e4e39a8f42e8e30fb9442fbf7878c8e4a9849e7e381619bea" - -[[package]] -name = "accesskit_consumer" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c17cca53c09fbd7288667b22a201274b9becaa27f0b91bf52a526db95de45e6" -dependencies = [ - "accesskit", -] - -[[package]] -name = "accesskit_macos" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3b6ae1eabbfbced10e840fd3fce8a93ae84f174b3e4ba892ab7bcb42e477a7" -dependencies = [ - "accesskit", - "accesskit_consumer", - "objc2", - "once_cell", -] - -[[package]] -name = "accesskit_windows" -version = "0.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcae27ec0974fc7c3b0b318783be89fd1b2e66dd702179fe600166a38ff4a0b" -dependencies = [ - "accesskit", - "accesskit_consumer", - "once_cell", - "paste", - "static_assertions", - "windows 0.48.0", -] - -[[package]] -name = "accesskit_winit" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88e39fcec2e10971e188730b7a76bab60647dacc973d4591855ebebcadfaa738" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_windows", - "winit", -] - -[[package]] -name = "actix-codec" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" -dependencies = [ - "bitflags 1.3.2", - "bytes", - "futures-core", - "futures-sink", - "memchr", - "pin-project-lite", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "actix-http" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129d4c88e98860e1758c5de288d1632b07970a16d59bdf7b8d66053d582bb71f" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "ahash 0.8.7", - "base64 0.21.7", - "bitflags 2.4.1", - "brotli", - "bytes", - "bytestring", - "derive_more", - "encoding_rs", - "flate2", - "futures-core", - "h2", - "http", - "httparse", - "httpdate", - "itoa", - "language-tags", - "local-channel", - "mime", - "percent-encoding", - "pin-project-lite", - "rand", - "sha1", - "smallvec", - "tokio", - "tokio-util", - "tracing", - "zstd 0.13.0", -] - -[[package]] -name = "actix-macros" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" -dependencies = [ - "quote", - "syn 2.0.48", -] - -[[package]] -name = "actix-router" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22475596539443685426b6bdadb926ad0ecaefdfc5fb05e5e3441f15463c511" -dependencies = [ - "bytestring", - "http", - "regex", - "serde", - "tracing", -] - -[[package]] -name = "actix-rt" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" -dependencies = [ - "futures-core", - "tokio", -] - -[[package]] -name = "actix-server" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" -dependencies = [ - "actix-rt", - "actix-service", - "actix-utils", - "futures-core", - "futures-util", - "mio", - "socket2 0.5.5", - "tokio", - "tracing", -] - -[[package]] -name = "actix-service" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" -dependencies = [ - "futures-core", - "paste", - "pin-project-lite", -] - -[[package]] -name = "actix-utils" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" -dependencies = [ - "local-waker", - "pin-project-lite", -] - -[[package]] -name = "actix-web" -version = "4.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e43428f3bf11dee6d166b00ec2df4e3aa8cc1606aaa0b7433c146852e2f4e03b" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-utils", - "actix-web-codegen", - "ahash 0.8.7", - "bytes", - "bytestring", - "cfg-if", - "cookie", - "derive_more", - "encoding_rs", - "futures-core", - "futures-util", - "itoa", - "language-tags", - "log", - "mime", - "once_cell", - "pin-project-lite", - "regex", - "serde", - "serde_json", - "serde_urlencoded", - "smallvec", - "socket2 0.5.5", - "time", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1f50ebbb30eca122b188319a4398b3f7bb4a8cdf50ecfb73bfc6a3c3ce54f5" -dependencies = [ - "actix-router", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", - "zerocopy", -] - -[[package]] -name = "aho-corasick" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "alsa" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2562ad8dcf0f789f65c6fdaad8a8a9708ed6b488e649da28c01656ad66b8b47" -dependencies = [ - "alsa-sys", - "bitflags 1.3.2", - "libc", - "nix 0.24.3", -] - -[[package]] -name = "alsa-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "android-activity" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" -dependencies = [ - "android-properties", - "bitflags 1.3.2", - "cc", - "jni-sys", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum 0.6.1", -] - -[[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - -[[package]] -name = "android_log-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937" - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anyhow" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" - -[[package]] -name = "approx" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] - -[[package]] -name = "arboard" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafb29b107435aa276664c1db8954ac27a6e105cdad3c88287a199eb0e313c08" -dependencies = [ - "clipboard-win", - "core-graphics", - "image", - "log", - "objc", - "objc-foundation", - "objc_id", - "parking_lot", - "thiserror", - "winapi", - "x11rb", -] - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" - -[[package]] -name = "ash" -version = "0.37.3+1.3.251" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a" -dependencies = [ - "libloading 0.7.4", -] - -[[package]] -name = "async-broadcast" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" -dependencies = [ - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ca33f4bc4ed1babef42cad36cc1f51fa88be00420404e5b1e80ab1b18f7678c" -dependencies = [ - "concurrent-queue", - "event-listener 4.0.3", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-convert" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d416feee97712e43152cd42874de162b8f9b77295b1c85e5d92725cc8310bae" -dependencies = [ - "async-trait", -] - -[[package]] -name = "async-executor" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" -dependencies = [ - "async-lock 3.3.0", - "async-task", - "concurrent-queue", - "fastrand 2.0.1", - "futures-lite 2.2.0", - "slab", -] - -[[package]] -name = "async-fs" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06" -dependencies = [ - "async-lock 2.8.0", - "autocfg", - "blocking", - "futures-lite 1.13.0", -] - -[[package]] -name = "async-lock" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" -dependencies = [ - "event-listener 2.5.3", -] - -[[package]] -name = "async-lock" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" -dependencies = [ - "event-listener 4.0.3", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-openai" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b26209963c22f8607fca31865e62793954f1fdf265135131e614584a863b799" -dependencies = [ - "async-convert", - "backoff", - "base64 0.21.7", - "bytes", - "derive_builder", - "futures", - "rand", - "reqwest", - "reqwest-eventsource", - "secrecy", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-stream", - "tokio-util", - "tracing", -] - -[[package]] -name = "async-task" -version = "4.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" - -[[package]] -name = "async-trait" -version = "0.1.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atomic_enum" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6227a8d6fdb862bcb100c4314d0d9579e5cd73fa6df31a2e6f6e1acd3c5f1207" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backoff" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" -dependencies = [ - "futures-core", - "getrandom", - "instant", - "pin-project-lite", - "rand", - "tokio", -] - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - -[[package]] -name = "base64ct" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" - -[[package]] -name = "bevy" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4bc7e09282a82a48d70ade0c4c1154b0fd7882a735a39c66766a5d0f4718ea9" -dependencies = [ - "bevy_internal", -] - -[[package]] -name = "bevy-inspector-egui" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c3efee9165f9be9c6a180c6a9bbb4bd39ee0a98a594f4cb7127704e15415cdd" -dependencies = [ - "bevy-inspector-egui-derive", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_egui", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_time", - "bevy_utils", - "bevy_window", - "egui", - "image", - "once_cell", - "pretty-type-name", - "smallvec", -] - -[[package]] -name = "bevy-inspector-egui-derive" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec77479f56958ed1b2802c3129ebc704d12245627b2d4dae61f11e6ed5c21b1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_a11y" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68080288c932634f6563d3a8299efe0ddc9ea6787539c4c771ba250d089a94f0" -dependencies = [ - "accesskit", - "bevy_app", - "bevy_derive", - "bevy_ecs", -] - -[[package]] -name = "bevy_app" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d41731817993f92e4363dd3335558e779e290bc71eefc0b5547052b85810907e" -dependencies = [ - "bevy_derive", - "bevy_ecs", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "downcast-rs", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "bevy_asset" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "935984568f75867dd7357133b06f4b1502cd2be55e4642d483ce597e46e63bff" -dependencies = [ - "async-broadcast", - "async-fs", - "async-lock 2.8.0", - "bevy_app", - "bevy_asset_macros", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bevy_winit", - "blake3", - "crossbeam-channel", - "downcast-rs", - "futures-io", - "futures-lite 1.13.0", - "js-sys", - "parking_lot", - "ron", - "serde", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "bevy_asset_macros" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f48b9bbe4ec605e4910b5cd1e1a0acbfbe0b80af5f3bcc4489a9fdd1e80058c" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_core" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3daa24502a14839509f02407bc7e48299fe84d260877de23b60662de0f4f4b6c" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bytemuck", -] - -[[package]] -name = "bevy_core_pipeline" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b77c4fca6e90edbe2e72da7bc9aa7aed7dfdfded0920ae0a0c845f5e11084a" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_derive", - "bevy_ecs", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bitflags 2.4.1", - "radsort", - "serde", -] - -[[package]] -name = "bevy_derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f484318350462c58ba3942a45a656c1fd6b6e484a6b6b7abc3a787ad1a51e500" -dependencies = [ - "bevy_macro_utils", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_diagnostic" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa38ca5967d335cc1006a0e0f1a86c350e2f15fd1878449f61d04cd57a7c4060" -dependencies = [ - "bevy_app", - "bevy_core", - "bevy_ecs", - "bevy_log", - "bevy_time", - "bevy_utils", - "sysinfo", -] - -[[package]] -name = "bevy_easings" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d13de5afeee849a6f5a9f35eace1a41efe01fc005ad85671c54876909216f2e6" -dependencies = [ - "bevy", - "interpolation", -] - -[[package]] -name = "bevy_ecs" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709fbd22f81fb681534cd913c41e1cd18b17143368743281195d7f024b61aea" -dependencies = [ - "async-channel 1.9.0", - "bevy_ecs_macros", - "bevy_ptr", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "downcast-rs", - "event-listener 2.5.3", - "fixedbitset", - "rustc-hash", - "serde", - "thiserror", - "thread_local", -] - -[[package]] -name = "bevy_ecs_macros" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8843aa489f159f25cdcd9fee75cd7d221a7098a71eaa72cb2d6b40ac4e3f1ba" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_egui" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90c01202dbcebc03315a01ea71553b35e1f20b0da6b1cc8c2605344032a3d96" -dependencies = [ - "arboard", - "bevy", - "egui", - "thread_local", - "webbrowser", -] - -[[package]] -name = "bevy_encase_derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5328a3715e933ebbff07d0e99528dc423c4f7a53590ed1ac19a120348b028990" -dependencies = [ - "bevy_macro_utils", - "encase_derive_impl", -] - -[[package]] -name = "bevy_gaussian_splatting" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad2743463900d9da3df1df14714b9a07beff505caebc20232cbd2468d7d2748" -dependencies = [ - "bevy", - "bevy-inspector-egui", - "bevy_panorbit_camera", - "byte-unit", - "bytemuck", - "console_error_panic_hook", - "flexbuffers", - "half", - "kd-tree", - "ply-rs", - "rand", - "rayon", - "serde", - "static_assertions", - "typenum", - "wasm-bindgen", - "web-sys", - "wgpu", -] - -[[package]] -name = "bevy_gizmos" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db232274ddca2ae452eb2731b98267b795d133ddd14013121bc7daddde1c7491" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_transform", - "bevy_utils", -] - -[[package]] -name = "bevy_hierarchy" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06bd477152ce2ae1430f5e0a4f19216e5785c22fee1ab23788b5982dc59d1a55" -dependencies = [ - "bevy_app", - "bevy_core", - "bevy_ecs", - "bevy_log", - "bevy_reflect", - "bevy_utils", - "smallvec", -] - -[[package]] -name = "bevy_input" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab9a599189b2a694c182d60cd52219dd9364f9892ff542d87799b8e45d9e6dc" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_utils", - "thiserror", -] - -[[package]] -name = "bevy_internal" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f124bece9831afd80897815231072d51bfe3ac58c6bb58eca8880963b6d0487c" -dependencies = [ - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_core_pipeline", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_gizmos", - "bevy_hierarchy", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_ptr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_sprite", - "bevy_tasks", - "bevy_text", - "bevy_time", - "bevy_transform", - "bevy_ui", - "bevy_utils", - "bevy_window", - "bevy_winit", -] - -[[package]] -name = "bevy_log" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc10ba1d225a8477b9e80a1bf797d8a8b8274e83c9b24fb4d9351aec9229755" -dependencies = [ - "android_log-sys", - "bevy_app", - "bevy_ecs", - "bevy_utils", - "console_error_panic_hook", - "tracing-log 0.1.4", - "tracing-subscriber", - "tracing-wasm", -] - -[[package]] -name = "bevy_macro_utils" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e566640c6b6dced73d2006c764c2cffebe1a82be4809486c4a5d7b4b50efed4d" -dependencies = [ - "proc-macro2", - "quote", - "rustc-hash", - "syn 2.0.48", - "toml_edit 0.20.7", -] - -[[package]] -name = "bevy_math" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ddc2b76783939c530178f88e5711a1b01044d7b02db4033e2eb8b43b6cf4ec" -dependencies = [ - "glam", - "serde", -] - -[[package]] -name = "bevy_mikktspace" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec4962977a746d870170532fc92759e04d3dbcae8b7b82e7ca3bb83b1d75277" -dependencies = [ - "glam", -] - -[[package]] -name = "bevy_panorbit_camera" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd9b28bdcb7d0996bc015051b1bb6b0fabf8047920ebcfc4eefe721c474d0ea4" -dependencies = [ - "bevy", - "bevy_easings", -] - -[[package]] -name = "bevy_pbr" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520bfd2a898c74f84ea52cfb8eb061f37373ad15e623489d5f75d27ebd6138fe" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.4.1", - "bytemuck", - "fixedbitset", - "naga_oil", - "radsort", - "smallvec", - "thread_local", -] - -[[package]] -name = "bevy_ptr" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77ec20c8fafcdc196508ef5ccb4f0400a8d193cb61f7b14a36ed9a25ad423cf" - -[[package]] -name = "bevy_reflect" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7921f15fc944c9c8ad01d7dbcea6505b8909c6655cd9382bab1407181556038" -dependencies = [ - "bevy_math", - "bevy_ptr", - "bevy_reflect_derive", - "bevy_utils", - "downcast-rs", - "erased-serde", - "glam", - "serde", - "smallvec", - "smol_str", - "thiserror", -] - -[[package]] -name = "bevy_reflect_derive" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4a8c5475f216e751ef4452a1306b00711f33d2d04d9f149e4c845dfeb6753a0" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.48", - "uuid", -] - -[[package]] -name = "bevy_render" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdefdd3737125b0d94a6ff20bb70fa8cfe9d7d5dcd72ba4dfe6c5f1d30d9f6e4" -dependencies = [ - "async-channel 1.9.0", - "bevy_app", - "bevy_asset", - "bevy_core", - "bevy_derive", - "bevy_ecs", - "bevy_encase_derive", - "bevy_hierarchy", - "bevy_log", - "bevy_math", - "bevy_mikktspace", - "bevy_reflect", - "bevy_render_macros", - "bevy_tasks", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.4.1", - "bytemuck", - "codespan-reporting", - "downcast-rs", - "encase", - "futures-lite 1.13.0", - "hexasphere", - "image", - "js-sys", - "naga", - "naga_oil", - "serde", - "smallvec", - "thiserror", - "thread_local", - "wasm-bindgen", - "web-sys", - "wgpu", -] - -[[package]] -name = "bevy_render_macros" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d86bfc5a1e7fbeeaec0c4ceab18155530f5506624670965db3415f75826bea" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_scene" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7df078b5e406e37c8a1c6ba0d652bf105fde713ce3c3efda7263fe27467eee5" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "ron", - "serde", - "thiserror", - "uuid", -] - -[[package]] -name = "bevy_sprite" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7cc0c9d946e17e3e0aaa202f182837bc796c4f862b2e5a805134f873f21cf7f" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_transform", - "bevy_utils", - "bitflags 2.4.1", - "bytemuck", - "fixedbitset", - "guillotiere", - "radsort", - "rectangle-pack", - "thiserror", -] - -[[package]] -name = "bevy_tasks" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fefa7fe0da8923525f7500e274f1bd60dbd79918a25cf7d0dfa0a6ba15c1cf" -dependencies = [ - "async-channel 1.9.0", - "async-executor", - "async-task", - "concurrent-queue", - "futures-lite 1.13.0", - "wasm-bindgen-futures", -] - -[[package]] -name = "bevy_text" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9a79d49ca06170d69149949b134c14e8b99ace1444c1ca2cd4743b19d5b055" -dependencies = [ - "ab_glyph", - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_transform", - "bevy_utils", - "bevy_window", - "glyph_brush_layout", - "serde", - "thiserror", -] - -[[package]] -name = "bevy_time" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6250d76eed3077128b6a3d004f9f198b01107800b9824051e32bb658054e837" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_reflect", - "bevy_utils", - "crossbeam-channel", - "thiserror", -] - -[[package]] -name = "bevy_transform" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d541e0c292edbd96afae816ee680e02247422423ccd5dc635c1e211a20ed64be" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_hierarchy", - "bevy_math", - "bevy_reflect", - "thiserror", -] - -[[package]] -name = "bevy_ui" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d785e3b75dabcb2a8ad0d50933f8f3446d59e512cabc2d2a145e28c2bb8792ba" -dependencies = [ - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_reflect", - "bevy_render", - "bevy_sprite", - "bevy_text", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bytemuck", - "serde", - "smallvec", - "taffy", - "thiserror", -] - -[[package]] -name = "bevy_utils" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7915222f4a08ccc782e08d10b751b42e5f9d786e697d0cb3fd09333cb7e8b6ea" -dependencies = [ - "ahash 0.8.7", - "bevy_utils_proc_macros", - "getrandom", - "hashbrown 0.14.3", - "instant", - "nonmax", - "petgraph", - "thiserror", - "tracing", - "uuid", -] - -[[package]] -name = "bevy_utils_proc_macros" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aafecc952b6b8eb1a93c12590bd867d25df2f4ae1033a01dfdfc3c35ebccfff" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "bevy_web_asset" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc7e9b05e9baf4a0ed31e33fc056c0d179d2b6c07a9d63b7e425a847286456b3" -dependencies = [ - "bevy", - "isahc", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "bevy_window" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41ee72bf7f974000e9b31bb971a89387f1432ba9413f35c4fef59fef49767260" -dependencies = [ - "bevy_a11y", - "bevy_app", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_reflect", - "bevy_utils", - "raw-window-handle", -] - -[[package]] -name = "bevy_winit" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eb71f287eca9006dda998784c7b931e400ae2cc4c505da315882a8b082f21ad" -dependencies = [ - "accesskit_winit", - "approx", - "bevy_a11y", - "bevy_app", - "bevy_derive", - "bevy_ecs", - "bevy_hierarchy", - "bevy_input", - "bevy_math", - "bevy_tasks", - "bevy_utils", - "bevy_window", - "crossbeam-channel", - "raw-window-handle", - "wasm-bindgen", - "web-sys", - "winit", -] - -[[package]] -name = "bindgen" -version = "0.69.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c69fae65a523209d34240b60abe0c42d33d1045d445c0839d8a4894a736e2d" -dependencies = [ - "bitflags 2.4.1", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.48", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" -dependencies = [ - "serde", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "blake3" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq 0.3.0", -] - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - -[[package]] -name = "block-sys" -version = "0.1.0-beta.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.2.0-alpha.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" -dependencies = [ - "block-sys", - "objc2-encode", -] - -[[package]] -name = "blocking" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" -dependencies = [ - "async-channel 2.1.1", - "async-lock 3.3.0", - "async-task", - "fastrand 2.0.1", - "futures-io", - "futures-lite 2.2.0", - "piper", - "tracing", -] - -[[package]] -name = "borsh" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58b559fd6448c6e2fd0adb5720cd98a2506594cafa4737ff98c396f3e82f667" -dependencies = [ - "borsh-derive", - "cfg_aliases", -] - -[[package]] -name = "borsh-derive" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aadb5b6ccbd078890f6d7003694e33816e6b784358f18e15e7e6d9f065a57cd" -dependencies = [ - "once_cell", - "proc-macro-crate 3.0.0", - "proc-macro2", - "quote", - "syn 2.0.48", - "syn_derive", -] - -[[package]] -name = "brotli" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byte-unit" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbda27216be70d08546aa506cecabce0c5eb0d494aaaedbd7ec82c8ae1a60b46" -dependencies = [ - "rust_decimal", - "serde", - "utf8-width", -] - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bytecount" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e5f035d16fc623ae5f74981db80a439803888314e3a555fd6f04acd51a3205" - -[[package]] -name = "bytemuck" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" -dependencies = [ - "bytemuck_derive", -] - -[[package]] -name = "bytemuck_derive" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "bytes" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" - -[[package]] -name = "bytestring" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" -dependencies = [ - "bytes", -] - -[[package]] -name = "bzip2" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" -dependencies = [ - "bzip2-sys", - "libc", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.11+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "camino" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.14.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", -] - -[[package]] -name = "castaway" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2698f953def977c68f935bb0dfa959375ad4638570e969e2f1e9f433cbf1af6" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "jobserver", - "libc", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "chrono" -version = "0.4.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "wasm-bindgen", - "windows-targets 0.48.5", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading 0.8.1", -] - -[[package]] -name = "claxon" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bfbf56724aa9eca8afa4fcfadeb479e722935bb2a0900c2d37e0cc477af0688" - -[[package]] -name = "clipboard-win" -version = "4.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362" -dependencies = [ - "error-code", - "str-buf", - "winapi", -] - -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - -[[package]] -name = "color_quant" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" - -[[package]] -name = "com-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" - -[[package]] -name = "combine" -version = "4.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "concurrent-queue" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "const_panic" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6051f239ecec86fde3410901ab7860d458d160371533842974fc61f96d15879b" - -[[package]] -name = "const_soft_float" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - -[[package]] -name = "constant_time_eq" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" - -[[package]] -name = "constgebra" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd23e864550e6dafc1e41ac78ce4f1ccddc8672b40c403524a04ff3f0518420" -dependencies = [ - "const_soft_float", -] - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "cookie" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" -dependencies = [ - "percent-encoding", - "time", - "version_check", -] - -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" - -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - -[[package]] -name = "coreaudio-rs" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" -dependencies = [ - "bitflags 1.3.2", - "core-foundation-sys", - "coreaudio-sys", -] - -[[package]] -name = "coreaudio-sys" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f01585027057ff5f0a5bf276174ae4c1594a2c5bde93d5f46a016d76270f5a9" -dependencies = [ - "bindgen", -] - -[[package]] -name = "cpal" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d959d90e938c5493000514b446987c07aed46c668faaa7d34d6c7a67b1a578c" -dependencies = [ - "alsa", - "core-foundation-sys", - "coreaudio-rs", - "dasp_sample", - "jni 0.19.0", - "js-sys", - "libc", - "mach2", - "ndk", - "ndk-context", - "oboe", - "once_cell", - "parking_lot", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows 0.46.0", -] - -[[package]] -name = "cpufeatures" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" -dependencies = [ - "libc", -] - -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176dc175b78f56c0f321911d9c8eb2b77a78a4860b9c19db83835fea1a46649b" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" -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.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "curl" -version = "0.4.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509bd11746c7ac09ebd19f0b17782eae80aadee26237658a6b4808afb5c11a22" -dependencies = [ - "curl-sys", - "libc", - "openssl-probe", - "openssl-sys", - "schannel", - "socket2 0.4.10", - "winapi", -] - -[[package]] -name = "curl-sys" -version = "0.4.70+curl-8.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0333d8849afe78a4c8102a429a446bfdd055832af071945520e835ae2d841e" -dependencies = [ - "cc", - "libc", - "libnghttp2-sys", - "libz-sys", - "openssl-sys", - "pkg-config", - "vcpkg", - "windows-sys 0.48.0", -] - -[[package]] -name = "cxx" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de00f15a6fa069c99b88c5c78c4541d0e7899a33b86f7480e23df2431fce0bc" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a71e1e631fa2f2f5f92e8b0d860a00c198c6771623a6cefcc863e3554f0d8d6" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.48", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3fed61d56ba497c4efef9144dfdbaa25aa58f2f6b3a7cf441d4591c583745c" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.115" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8908e380a8efd42150c017b0cfa31509fc49b6d47f7cb6b33e93ffb8f4e3661e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "d3d12" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20" -dependencies = [ - "bitflags 2.4.1", - "libloading 0.8.1", - "winapi", -] - -[[package]] -name = "darling" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" -dependencies = [ - "darling_core", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "dasp_sample" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" - -[[package]] -name = "data-encoding" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" - -[[package]] -name = "deepgram" -version = "0.3.0-alpha.1" -source = "git+https://github.com/cs50victor/deepgram-rust-sdk.git?branch=live-fork#8ca4f758cf5a01276bc10e16cfed8faa32cb3a37" -dependencies = [ - "futures", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-tungstenite 0.17.2", - "uuid", -] - -[[package]] -name = "deranged" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_builder" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "derive_builder_macro" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" -dependencies = [ - "derive_builder_core", - "syn 1.0.109", -] - -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 1.0.109", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", - "subtle", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "downcast-rs" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" - -[[package]] -name = "ecolor" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7637fc2e74d17e52931bac90ff4fc061ac776ada9c7fa272f24cdca5991972" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "egui" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55bcb864b764eb889515a38b8924757657a250738ad15126637ee2df291ee6b" -dependencies = [ - "ahash 0.8.7", - "epaint", - "nohash-hasher", -] - -[[package]] -name = "either" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" - -[[package]] -name = "emath" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a045c6c0b44b35e98513fc1e9d183ab42881ac27caccb9fa345465601f56cce4" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "encase" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fce2eeef77fd4a293a54b62aa00ac9daebfbcda4bf8998c5a815635b004aa1c" -dependencies = [ - "const_panic", - "encase_derive", - "glam", - "thiserror", -] - -[[package]] -name = "encase_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e520cde08cbf4f7cc097f61573ec06ce467019803de8ae82fb2823fa1554a0e" -dependencies = [ - "encase_derive_impl", -] - -[[package]] -name = "encase_derive_impl" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe2568f851fd6144a45fa91cfed8fe5ca8fc0b56ba6797bfc1ed2771b90e37c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "encoding_rs" -version = "0.8.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "enfync" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce8c1fbec15a38aced3838c4d7ea90a1403bd50364b5cfe8008e679df0c8dde" -dependencies = [ - "async-trait", - "futures", - "tokio", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasmtimer", -] - -[[package]] -name = "env_logger" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" -dependencies = [ - "humantime", - "is-terminal", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "epaint" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d1b9e000d21bab9b535ce78f9f7745be28b3f777f6c7223936561c5c7fefab8" -dependencies = [ - "ab_glyph", - "ahash 0.8.7", - "bytemuck", - "ecolor", - "emath", - "nohash-hasher", - "parking_lot", -] - -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "erased-serde" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" -dependencies = [ - "serde", -] - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "error-chain" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" -dependencies = [ - "version_check", -] - -[[package]] -name = "error-code" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21" -dependencies = [ - "libc", - "str-buf", -] - -[[package]] -name = "euclid" -version = "0.22.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" -dependencies = [ - "num-traits", -] - -[[package]] -name = "event-listener" -version = "2.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" - -[[package]] -name = "event-listener" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" -dependencies = [ - "concurrent-queue", - "parking", - "pin-project-lite", -] - -[[package]] -name = "event-listener-strategy" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" -dependencies = [ - "event-listener 4.0.3", - "pin-project-lite", -] - -[[package]] -name = "eventsource-stream" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" -dependencies = [ - "futures-core", - "nom", - "pin-project-lite", -] - -[[package]] -name = "ezsockets" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab2935707532c19357939ce9649a0ca45eb02c2295bf37990f4601cb3a8afd4" -dependencies = [ - "async-channel 1.9.0", - "async-trait", - "atomic_enum", - "base64 0.21.7", - "cfg-if", - "enfync", - "futures", - "futures-util", - "getrandom", - "http", - "tokio", - "tokio-rustls", - "tokio-tungstenite 0.20.1", - "tokio-tungstenite-wasm", - "tracing", - "tungstenite 0.20.1", - "url", - "wasm-bindgen-futures", - "wasmtimer", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fdeflate" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flexbuffers" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d14128f06405808ce75bfebe11e9b0f9da18719ede6d7bdb1702d6bfe0f7e8" -dependencies = [ - "bitflags 1.3.2", - "byteorder", - "num_enum 0.5.11", - "serde", - "serde_derive", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared 0.3.1", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "fs2" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" - -[[package]] -name = "futures-executor" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" -dependencies = [ - "futures-core", - "futures-task", - "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.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" - -[[package]] -name = "futures-lite" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" -dependencies = [ - "fastrand 1.9.0", - "futures-core", - "futures-io", - "memchr", - "parking", - "pin-project-lite", - "waker-fn", -] - -[[package]] -name = "futures-lite" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445ba825b27408685aaecefd65178908c36c6e96aaf6d8599419d46e624192ba" -dependencies = [ - "fastrand 2.0.1", - "futures-core", - "futures-io", - "parking", - "pin-project-lite", -] - -[[package]] -name = "futures-macro" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "futures-sink" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" - -[[package]] -name = "futures-task" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" - -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - -[[package]] -name = "futures-util" -version = "0.3.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "gethostname" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "getrandom" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glam" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" -dependencies = [ - "bytemuck", - "serde", -] - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "glow" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" -dependencies = [ - "js-sys", - "slotmap", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "glyph_brush_layout" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc32c2334f00ca5ac3695c5009ae35da21da8c62d255b5b96d56e2597a637a38" -dependencies = [ - "ab_glyph", - "approx", - "xi-unicode", -] - -[[package]] -name = "gpu-alloc" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" -dependencies = [ - "bitflags 2.4.1", - "gpu-alloc-types", -] - -[[package]] -name = "gpu-alloc-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" -dependencies = [ - "bitflags 2.4.1", -] - -[[package]] -name = "gpu-allocator" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" -dependencies = [ - "backtrace", - "log", - "thiserror", - "winapi", - "windows 0.44.0", -] - -[[package]] -name = "gpu-descriptor" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c" -dependencies = [ - "bitflags 2.4.1", - "gpu-descriptor-types", - "hashbrown 0.14.3", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf0b36e6f090b7e1d8a4b49c0cb81c1f8376f72198c65dd3ad9ff3556b8b78c" -dependencies = [ - "bitflags 2.4.1", -] - -[[package]] -name = "grid" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eec1c01eb1de97451ee0d60de7d81cf1e72aabefb021616027f3d1c3ec1c723c" - -[[package]] -name = "guillotiere" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62d5865c036cb1393e23c50693df631d3f5d7bcca4c04fe4cc0fd592e74a782" -dependencies = [ - "euclid", - "svg_fmt", -] - -[[package]] -name = "h2" -version = "0.3.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b553656127a00601c8ae5590fcfdc118e4083a7924b6cf4ffc1ea4b99dc429d7" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap 2.1.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872" -dependencies = [ - "cfg-if", - "crunchy", - "serde", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash 0.8.7", - "allocator-api2", - "serde", -] - -[[package]] -name = "hassle-rs" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" -dependencies = [ - "bitflags 1.3.2", - "com-rs", - "libc", - "libloading 0.7.4", - "thiserror", - "widestring", - "winapi", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hexasphere" -version = "9.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cb3df16a7bcb1b5bc092abd55e14f77ca70aea14445026e264586fc62889a10" -dependencies = [ - "constgebra", - "glam", -] - -[[package]] -name = "hexf-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "hound" -version = "3.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62adaabb884c94955b19907d60019f4e145d091c75345379e70d1ee696f7854f" - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.5", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http", - "hyper", - "rustls", - "tokio", - "tokio-rustls", -] - -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.59" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "image" -version = "0.24.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "num-rational", - "num-traits", - "png", - "tiff", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", -] - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown 0.14.3", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "interpolation" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9c13ae9d91148fcb4aab6654c4c2a7d02a15395ea9e23f65170f175f8b269ce" - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is-terminal" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" -dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "isahc" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334e04b4d781f436dc315cb1e7515bd96826426345d498149e4bde36b67f8ee9" -dependencies = [ - "async-channel 1.9.0", - "castaway", - "crossbeam-utils", - "curl", - "curl-sys", - "encoding_rs", - "event-listener 2.5.3", - "futures-lite 1.13.0", - "http", - "log", - "mime", - "once_cell", - "polling", - "slab", - "sluice", - "tracing", - "tracing-futures", - "url", - "waker-fn", -] - -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" - -[[package]] -name = "jni" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039022cdf4d7b1cf548d31f60ae783138e5fd42013f6271049d7df7afadef96c" -dependencies = [ - "cesu8", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", -] - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" -dependencies = [ - "libc", -] - -[[package]] -name = "jpeg-decoder" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" - -[[package]] -name = "js-sys" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonwebtoken" -version = "9.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" -dependencies = [ - "base64 0.21.7", - "js-sys", - "ring", - "serde", - "serde_json", -] - -[[package]] -name = "kd-tree" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c12a5c8da4557f8573c26673f1db6fab935255c5cf62a82d2df33d1fba07a409" -dependencies = [ - "num-traits", - "ordered-float", - "paste", - "pdqselect", - "typenum", -] - -[[package]] -name = "khronos-egl" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" -dependencies = [ - "libc", - "libloading 0.7.4", - "pkg-config", -] - -[[package]] -name = "language-tags" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lewton" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "777b48df9aaab155475a83a7df3070395ea1ac6902f5cd062b8f2b028075c030" -dependencies = [ - "byteorder", - "ogg", - "tinyvec", -] - -[[package]] -name = "libc" -version = "0.2.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "libnghttp2-sys" -version = "0.1.9+1.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57e858af2798e167e709b9d969325b6d8e9d50232fcbc494d7d54f976854a64" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "libredox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall 0.4.1", -] - -[[package]] -name = "libwebrtc" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "cxx", - "jni 0.21.1", - "js-sys", - "lazy_static", - "livekit-protocol", - "log", - "parking_lot", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-stream", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webrtc-sys", -] - -[[package]] -name = "libz-sys" -version = "1.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295c17e837573c8c821dbaeb3cceb3d745ad082f7572191409e69cbc1b3fd050" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "link-cplusplus" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d240c6f7e1ba3a28b0249f774e6a9dd0175054b52dfbb61b16eb8505c3785c9" -dependencies = [ - "cc", -] - -[[package]] -name = "linked-hash-map" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" - -[[package]] -name = "linux-raw-sys" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" - -[[package]] -name = "livekit" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "futures-util", - "lazy_static", - "libwebrtc", - "livekit-api", - "livekit-protocol", - "log", - "parking_lot", - "prost", - "serde", - "serde_json", - "thiserror", - "tokio", -] - -[[package]] -name = "livekit-api" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "base64 0.21.7", - "futures-util", - "jsonwebtoken", - "livekit-protocol", - "log", - "parking_lot", - "prost", - "reqwest", - "scopeguard", - "serde", - "serde_json", - "sha2", - "thiserror", - "tokio", - "tokio-tungstenite 0.20.1", - "url", -] - -[[package]] -name = "livekit-protocol" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "futures-util", - "parking_lot", - "pbjson", - "pbjson-types", - "prost", - "prost-types", - "serde", - "thiserror", - "tokio", -] - -[[package]] -name = "lkgpt" -version = "0.0.1" -dependencies = [ - "actix-web", - "anyhow", - "async-openai", - "async-trait", - "base64 0.21.7", - "bevy", - "bevy_gaussian_splatting", - "bevy_panorbit_camera", - "bevy_web_asset", - "bytes", - "chrono", - "crossbeam-channel", - "deepgram", - "dotenvy", - "ezsockets", - "futures", - "futures-intrusive", - "image", - "livekit", - "livekit-api", - "livekit-protocol", - "log", - "parking_lot", - "pollster", - "pretty_env_logger", - "rodio", - "serde", - "serde_json", - "tokio", - "url", - "wgpu", -] - -[[package]] -name = "local-channel" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" -dependencies = [ - "futures-core", - "futures-sink", - "local-waker", -] - -[[package]] -name = "local-waker" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "matchers" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" -dependencies = [ - "regex-automata 0.1.10", -] - -[[package]] -name = "memchr" -version = "2.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" - -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - -[[package]] -name = "metal" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623b5e6cefd76e58f774bd3cc0c6f5c7615c58c03a97815245a25c3c9bdee318" -dependencies = [ - "bitflags 2.4.1", - "block", - "core-graphics-types", - "foreign-types 0.5.0", - "log", - "objc", - "paste", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "multimap" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" - -[[package]] -name = "naga" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ceaaa4eedaece7e4ec08c55c640ba03dbb73fb812a6570a59bcf1930d0f70e" -dependencies = [ - "bit-set", - "bitflags 2.4.1", - "codespan-reporting", - "hexf-parse", - "indexmap 1.9.3", - "log", - "num-traits", - "pp-rs", - "rustc-hash", - "spirv", - "termcolor", - "thiserror", - "unicode-xid", -] - -[[package]] -name = "naga_oil" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac54c77b3529887f9668d3dd81e955e58f252b31a333f836e3548c06460b958" -dependencies = [ - "bit-set", - "codespan-reporting", - "data-encoding", - "indexmap 1.9.3", - "naga", - "once_cell", - "regex", - "regex-syntax 0.7.5", - "rustc-hash", - "thiserror", - "tracing", - "unicode-ident", -] - -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - -[[package]] -name = "ndk" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" -dependencies = [ - "bitflags 1.3.2", - "jni-sys", - "ndk-sys", - "num_enum 0.5.11", - "raw-window-handle", - "thiserror", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.4.1+23.1.7779620" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - -[[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 = "nonmax" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - -[[package]] -name = "num-derive" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" -dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc-sys" -version = "0.2.0-beta.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" - -[[package]] -name = "objc2" -version = "0.3.0-beta.3.patch-leaks.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" -dependencies = [ - "block2", - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2-encode" -version = "2.0.0-pre.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "object" -version = "0.32.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" -dependencies = [ - "memchr", -] - -[[package]] -name = "oboe" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8868cc237ee02e2d9618539a23a8d228b9bb3fc2e7a5b11eed3831de77c395d0" -dependencies = [ - "jni 0.20.0", - "ndk", - "ndk-context", - "num-derive", - "num-traits", - "oboe-sys", -] - -[[package]] -name = "oboe-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f44155e7fb718d3cfddcf70690b2b51ac4412f347cd9e4fbe511abe9cd7b5f2" -dependencies = [ - "cc", -] - -[[package]] -name = "ogg" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6951b4e8bf21c8193da321bcce9c9dd2e13c858fe078bf9054a288b419ae5d6e" -dependencies = [ - "byteorder", -] - -[[package]] -name = "once_cell" -version = "1.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" - -[[package]] -name = "openssl" -version = "0.10.62" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cde4d2d9200ad5909f8dac647e29482e07c3a35de8a13fce7c9c7747ad9f671" -dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1665caf8ab2dc9aef43d1c0023bd904633a6a05cb30b0ad59bec2ae986e57a7" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "orbclient" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" -dependencies = [ - "libredox", -] - -[[package]] -name = "ordered-float" -version = "3.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" -dependencies = [ - "num-traits", -] - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "owned_ttf_parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7" -dependencies = [ - "ttf-parser", -] - -[[package]] -name = "parking" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.4.1", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "pbjson" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1030c719b0ec2a2d25a5df729d6cff1acf3cc230bf766f4f97833591f7577b90" -dependencies = [ - "base64 0.21.7", - "serde", -] - -[[package]] -name = "pbjson-build" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735" -dependencies = [ - "heck", - "itertools", - "prost", - "prost-types", -] - -[[package]] -name = "pbjson-types" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f596653ba4ac51bdecbb4ef6773bc7f56042dc13927910de1684ad3d32aa12" -dependencies = [ - "bytes", - "chrono", - "pbjson", - "pbjson-build", - "prost", - "prost-build", - "serde", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest", - "hmac", - "password-hash", - "sha2", -] - -[[package]] -name = "pdqselect" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7778906d9321dd56cde1d1ffa69a73e59dcf5fda6d366f62727adf2bd4193aee" - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "peg" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f76678828272f177ac33b7e2ac2e3e73cc6c1cd1e3e387928aa69562fa51367" -dependencies = [ - "peg-macros", - "peg-runtime", -] - -[[package]] -name = "peg-macros" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "636d60acf97633e48d266d7415a9355d4389cea327a193f87df395d88cd2b14d" -dependencies = [ - "peg-runtime", - "proc-macro2", - "quote", -] - -[[package]] -name = "peg-runtime" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555b1514d2d99d78150d3c799d4c357a3e2c2a8062cd108e93a06d9057629c5" - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap 2.1.0", -] - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" -dependencies = [ - "atomic-waker", - "fastrand 2.0.1", - "futures-io", -] - -[[package]] -name = "pkg-config" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" - -[[package]] -name = "ply-rs" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbadf9cb4a79d516de4c64806fe64ffbd8161d1ac685d000be789fb628b88963" -dependencies = [ - "byteorder", - "linked-hash-map", - "peg", - "skeptic", -] - -[[package]] -name = "png" -version = "0.17.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "polling" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" -dependencies = [ - "autocfg", - "bitflags 1.3.2", - "cfg-if", - "concurrent-queue", - "libc", - "log", - "pin-project-lite", - "windows-sys 0.48.0", -] - -[[package]] -name = "pollster" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "pp-rs" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb458bb7f6e250e6eb79d5026badc10a3ebb8f9a15d1fff0f13d17c71f4d6dee" -dependencies = [ - "unicode-xid", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "pretty-type-name" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f73cdaf19b52e6143685c3606206e114a4dfa969d6b14ec3894c88eb38bd4b" - -[[package]] -name = "pretty_env_logger" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" -dependencies = [ - "env_logger", - "log", -] - -[[package]] -name = "prettyplease" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" -dependencies = [ - "proc-macro2", - "syn 2.0.48", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b2685dd208a3771337d8d386a89840f0f43cd68be8dae90a5f8c2384effc9cd" -dependencies = [ - "toml_edit 0.21.0", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.76" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "profiling" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d135ede8821cf6376eb7a64148901e1690b788c11ae94dc297ae917dbc91dc0e" - -[[package]] -name = "prost" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55e02e35260070b6f716a2423c2ff1c3bb1642ddca6f99e1f26d06268a0e2d2" -dependencies = [ - "bytes", - "heck", - "itertools", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn 2.0.48", - "tempfile", - "which", -] - -[[package]] -name = "prost-derive" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" -dependencies = [ - "anyhow", - "itertools", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "prost-types" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" -dependencies = [ - "prost", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "pulldown-cmark" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998" -dependencies = [ - "bitflags 1.3.2", - "memchr", - "unicase", -] - -[[package]] -name = "quote" -version = "1.0.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "radsort" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fd96390ed3feda12e1dfe2645ed587e0bea749e319333f104a33ff62f77a0b" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "rayon" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "rectangle-pack" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.3", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "rend" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2571463863a6bd50c32f94402933f03457a3fbaf697a707c5be741e459f08fd" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "renderdoc-sys" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216080ab382b992234dda86873c18d4c48358f5cfcb70fd693d7f6f2131b628b" - -[[package]] -name = "reqwest" -version = "0.11.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "hyper-tls", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls", - "rustls-native-certs", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tokio-util", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "winreg", -] - -[[package]] -name = "reqwest-eventsource" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f03f570355882dd8d15acc3a313841e6e90eddbc76a93c748fd82cc13ba9f51" -dependencies = [ - "eventsource-stream", - "futures-core", - "futures-timer", - "mime", - "nom", - "pin-project-lite", - "reqwest", - "thiserror", -] - -[[package]] -name = "ring" -version = "0.17.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" -dependencies = [ - "cc", - "getrandom", - "libc", - "spin", - "untrusted", - "windows-sys 0.48.0", -] - -[[package]] -name = "rkyv" -version = "0.7.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527a97cdfef66f65998b5f3b637c26f5a5ec09cc52a3f9932313ac645f4190f5" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5c462a1328c8e67e4d6dbad1eb0355dd43e8ab432c6e227a43657f16ade5033" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rodio" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1bb7b48ee48471f55da122c0044fcc7600cfcc85db88240b89cb832935e611" -dependencies = [ - "claxon", - "cpal", - "hound", - "lewton", - "symphonia", -] - -[[package]] -name = "ron" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" -dependencies = [ - "base64 0.21.7", - "bitflags 2.4.1", - "serde", - "serde_derive", -] - -[[package]] -name = "rust_decimal" -version = "1.33.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06676aec5ccb8fc1da723cc8c0f9a46549f21ebb8753d3915c6c41db1e7f1dc4" -dependencies = [ - "arrayvec", - "borsh", - "bytes", - "num-traits", - "rand", - "rkyv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.38.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" -dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.52.0", -] - -[[package]] -name = "rustls" -version = "0.21.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-native-certs" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" -dependencies = [ - "openssl-probe", - "rustls-pemfile", - "schannel", - "security-framework", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "ryu" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "scratch" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cf7c11c38cb994f3d40e8a8cde3bbd1f72a435e4c49e85d6553d8312306152" - -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "secrecy" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" -dependencies = [ - "serde", - "zeroize", -] - -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "semver" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" -dependencies = [ - "serde", -] - -[[package]] -name = "serde" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.195" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "serde_json" -version = "1.0.111" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[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 = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[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.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "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 = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "skeptic" -version = "0.13.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "tempfile", - "walkdir", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "version_check", -] - -[[package]] -name = "sluice" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7400c0eff44aa2fcb5e31a5f24ba9716ed90138769e4977a2ba6014ae63eb5" -dependencies = [ - "async-channel 1.9.0", - "futures-core", - "futures-io", -] - -[[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" -dependencies = [ - "serde", -] - -[[package]] -name = "smol_str" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" - -[[package]] -name = "spirv" -version = "0.2.0+1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" -dependencies = [ - "bitflags 1.3.2", - "num-traits", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "str-buf" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "subtle" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "svg_fmt" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1df15f412ee2e9dfc1c504260fa695c1c3f10fe9f4a6ee2d2184d7d6450e2" - -[[package]] -name = "symphonia" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e48dba70095f265fdb269b99619b95d04c89e619538138383e63310b14d941" -dependencies = [ - "lazy_static", - "symphonia-bundle-mp3", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-bundle-mp3" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f31d7fece546f1e6973011a9eceae948133bbd18fd3d52f6073b1e38ae6368a" -dependencies = [ - "bitflags 1.3.2", - "lazy_static", - "log", - "symphonia-core", - "symphonia-metadata", -] - -[[package]] -name = "symphonia-core" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c73eb88fee79705268cc7b742c7bc93a7b76e092ab751d0833866970754142" -dependencies = [ - "arrayvec", - "bitflags 1.3.2", - "bytemuck", - "lazy_static", - "log", -] - -[[package]] -name = "symphonia-metadata" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c3e1937e31d0e068bbe829f66b2f2bfaa28d056365279e0ef897172c3320c0" -dependencies = [ - "encoding_rs", - "lazy_static", - "log", - "symphonia-core", -] - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "sysinfo" -version = "0.29.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd727fc423c2060f6c92d9534cef765c65a6ed3f428a03d7def74a8c4348e666" -dependencies = [ - "cfg-if", - "core-foundation-sys", - "libc", - "ntapi", - "once_cell", - "winapi", -] - -[[package]] -name = "system-configuration" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", -] - -[[package]] -name = "system-configuration-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "taffy" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2287b6d7f721ada4cddf61ade5e760b2c6207df041cac9bfaa192897362fd3" -dependencies = [ - "arrayvec", - "grid", - "num-traits", - "slotmap", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "tempfile" -version = "3.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" -dependencies = [ - "cfg-if", - "fastrand 2.0.1", - "redox_syscall 0.4.1", - "rustix", - "windows-sys 0.52.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "thiserror" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "tiff" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d172b0f4d3fba17ba89811858b9d3d97f928aece846475bbda076ca46736211" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - -[[package]] -name = "time" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" -dependencies = [ - "deranged", - "itoa", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" - -[[package]] -name = "time-macros" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" -dependencies = [ - "time-core", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -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.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.5", - "tokio-macros", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-macros" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "native-tls", - "tokio", - "tokio-native-tls", - "tungstenite 0.17.3", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" -dependencies = [ - "futures-util", - "log", - "native-tls", - "rustls", - "tokio", - "tokio-native-tls", - "tokio-rustls", - "tungstenite 0.20.1", - "webpki-roots", -] - -[[package]] -name = "tokio-tungstenite-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ec8c7cf09b20184f946f114e3d8c0deca34368912c90100812861c14bb63b66" -dependencies = [ - "futures-channel", - "futures-util", - "http", - "httparse", - "js-sys", - "thiserror", - "tokio", - "tokio-tungstenite 0.20.1", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "tokio-util" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" -dependencies = [ - "indexmap 2.1.0", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "tracing-core" -version = "0.1.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - -[[package]] -name = "tracing-log" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log 0.2.0", -] - -[[package]] -name = "tracing-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "ttf-parser" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4" - -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "native-tls", - "rand", - "sha-1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "tungstenite" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "native-tls", - "rand", - "rustls", - "sha1", - "thiserror", - "url", - "utf-8", -] - -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-width" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf8-width" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" - -[[package]] -name = "uuid" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "waker-fn" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" - -[[package]] -name = "walkdir" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.90" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" - -[[package]] -name = "wasm-streams" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4609d447824375f43e1ffbc051b50ad8f4b3ae8219680c94452ea05eb240ac7" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "wasmtimer" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f656cd8858a5164932d8a90f936700860976ec21eb00e0fe2aa8cab13f6b4cf" -dependencies = [ - "futures", - "js-sys", - "parking_lot", - "pin-utils", - "slab", - "wasm-bindgen", -] - -[[package]] -name = "wayland-scanner" -version = "0.29.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" -dependencies = [ - "proc-macro2", - "quote", - "xml-rs", -] - -[[package]] -name = "web-sys" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2391658b02c27719fc5a0a73d6e696285138e8b12fba9d4baa70451023c71" -dependencies = [ - "core-foundation", - "home", - "jni 0.21.1", - "log", - "ndk-context", - "objc", - "raw-window-handle", - "url", - "web-sys", -] - -[[package]] -name = "webpki-roots" -version = "0.25.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" - -[[package]] -name = "webrtc-sys" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "cc", - "cxx", - "cxx-build", - "glob", - "log", - "webrtc-sys-build", -] - -[[package]] -name = "webrtc-sys-build" -version = "0.3.0" -source = "git+https://github.com/cs50victor/livekit-rust-sdks.git?branch=update-proto#a568a8414a98a22f8f6fff0de2567d4a6a8e1945" -dependencies = [ - "fs2", - "regex", - "reqwest", - "scratch", - "semver", - "zip", -] - -[[package]] -name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - -[[package]] -name = "wgpu" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "752e44d3998ef35f71830dd1ad3da513e628e2e4d4aedb0ab580f850827a0b41" -dependencies = [ - "arrayvec", - "cfg-if", - "js-sys", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "smallvec", - "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "wgpu-core", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-core" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8a44dd301a30ceeed3c27d8c0090433d3da04d7b2a4042738095a424d12ae7" -dependencies = [ - "arrayvec", - "bit-vec", - "bitflags 2.4.1", - "codespan-reporting", - "log", - "naga", - "parking_lot", - "profiling", - "raw-window-handle", - "rustc-hash", - "smallvec", - "thiserror", - "web-sys", - "wgpu-hal", - "wgpu-types", -] - -[[package]] -name = "wgpu-hal" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80bf0e3c77399bb52850cb0830af9bad073d5cfcb9dd8253bef8125c42db17" -dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.4.1", - "block", - "core-graphics-types", - "d3d12", - "glow", - "gpu-alloc", - "gpu-allocator", - "gpu-descriptor", - "hassle-rs", - "js-sys", - "khronos-egl", - "libc", - "libloading 0.8.1", - "log", - "metal", - "naga", - "objc", - "parking_lot", - "profiling", - "range-alloc", - "raw-window-handle", - "renderdoc-sys", - "rustc-hash", - "smallvec", - "thiserror", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winapi", -] - -[[package]] -name = "wgpu-types" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee64d7398d0c2f9ca48922c902ef69c42d000c759f3db41e355f4a570b052b67" -dependencies = [ - "bitflags 2.4.1", - "js-sys", - "web-sys", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] - -[[package]] -name = "widestring" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-targets 0.48.5", -] - -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-implement" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "windows-interface" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -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" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" -dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -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.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winit" -version = "0.28.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" -dependencies = [ - "android-activity", - "bitflags 1.3.2", - "cfg_aliases", - "core-foundation", - "core-graphics", - "dispatch", - "instant", - "libc", - "log", - "ndk", - "objc2", - "once_cell", - "orbclient", - "raw-window-handle", - "redox_syscall 0.3.5", - "wasm-bindgen", - "wayland-scanner", - "web-sys", - "windows-sys 0.45.0", -] - -[[package]] -name = "winnow" -version = "0.5.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] - -[[package]] -name = "x11rb" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" -dependencies = [ - "gethostname", - "nix 0.26.4", - "winapi", - "winapi-wsapoll", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix 0.26.4", -] - -[[package]] -name = "xi-unicode" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a" - -[[package]] -name = "xml-rs" -version = "0.8.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" - -[[package]] -name = "zip" -version = "0.6.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "760394e246e4c28189f19d488c058bf16f564016aefac5d32bb1f3b51d5e9261" -dependencies = [ - "aes", - "byteorder", - "bzip2", - "constant_time_eq 0.1.5", - "crc32fast", - "crossbeam-utils", - "flate2", - "hmac", - "pbkdf2", - "sha1", - "time", - "zstd 0.11.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.11.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" -dependencies = [ - "zstd-safe 5.0.2+zstd.1.5.2", -] - -[[package]] -name = "zstd" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" -dependencies = [ - "zstd-safe 7.0.0", -] - -[[package]] -name = "zstd-safe" -version = "5.0.2+zstd.1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" -dependencies = [ - "libc", - "zstd-sys", -] - -[[package]] -name = "zstd-safe" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.9+zstd.1.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" -dependencies = [ - "cc", - "pkg-config", -] diff --git a/Cargo.toml b/Cargo.toml deleted file mode 100644 index 38763db..0000000 --- a/Cargo.toml +++ /dev/null @@ -1,21 +0,0 @@ -[workspace] -resolver = "2" -members = ["lkgpt"] - -package.rust-version = "1.75.0" - -[profile.dev] -opt-level = 1 # Small amount of optimizations - -[profile.dev.package."*"] -opt-level = 3 - -[profile.release] -opt-level = "z" # Optimize for binanry size. -lto = true # Enable link-time optimization. -codegen-units = 1 # Only use one codegen unit, to imcrease optimization. -panic = "abort" # Abort on panic, instead of unwinding the stack. - -[profile.prod] -inherits = "release" -strip = true # Automatically strip symbols from the binary. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..93f9ca3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,36 @@ +# syntax=docker/dockerfile:1 + +ARG PYTHON_VERSION=3.11.6 +FROM python:${PYTHON_VERSION}-slim as base + +# Prevents Python from writing pyc files. +ENV PYTHONDONTWRITEBYTECODE=1 + +# Keeps Python from buffering stdout and stderr to avoid situations where +# the application crashes without emitting any logs due to buffering. +ENV PYTHONUNBUFFERED=1 + +WORKDIR /app + +# Create a non-privileged user that the app will run under. +# See https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#user +ARG UID=10001 +RUN adduser \ + --disabled-password \ + --gecos "" \ + --home "/nonexistent" \ + --shell "/sbin/nologin" \ + --no-create-home \ + --uid "${UID}" \ + appuser + +# Copy the source code into the container. +COPY . . + +RUN python -m pip install -r requirements.txt + +# Switch to the non-privileged user to run the application. +USER appuser + +# Run the application. +CMD python kitt.py start \ No newline at end of file diff --git a/README.md b/README.md index 01a2b0d..9db7056 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,11 @@ # KITT V2 -DEMO +> Update: the graphics part (video rendering) of this project has been moved to [new media](https://github.com/cs50victor/new_media) -https://github.com/cs50victor/kitt2/assets/52110451/ef2f8b61-6870-4e44-8718-0f92ef90cefc +[![Preview Demo](https://i.stack.imgur.com/Vp2cE.png)](https://github.com/cs50victor/kitt2/assets/52110451/ef2f8b61-6870-4e44-8718-0f92ef90cefc) + +## Run Locally 1. `pnpm i` 2. `pnpm dev` 3. `ngrok http http:://localhost:6669` ( in a different terminal ) - -- stt ( deepgram ) -- tts ( eleven labs ) - -### Credits - -- [Bevy Gaussian Splatting](https://github.com/mosure/bevy_gaussian_splatting) 🎖️ -- [Bevy Deepgram](https://github.com/deepgram-devs/bevy-deepgram) diff --git a/meet/app/api/get-participant-token/route.ts b/app/api/get-participant-token/route.ts similarity index 100% rename from meet/app/api/get-participant-token/route.ts rename to app/api/get-participant-token/route.ts diff --git a/meet/app/api/url/route.ts b/app/api/url/route.ts similarity index 100% rename from meet/app/api/url/route.ts rename to app/api/url/route.ts diff --git a/app/global.css b/app/global.css new file mode 100644 index 0000000..fba3ebf --- /dev/null +++ b/app/global.css @@ -0,0 +1,45 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + + .repeating-square-background { + background-size: 18px 18px; + background-repeat: repeat; + background-image: url("data:image/svg+xml,%3Csvg width='18' height='18' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='0' width='2' height='2' fill='rgba(255, 255, 255, 0.03)' /%3E%3C/svg%3E"); + } + + .cursor-animation { + animation: fadeIn 0.5s ease-in-out alternate-reverse infinite; + } + + + ::-webkit-scrollbar-track { + background: rgba(255, 255, 255, 0.05); + border-radius: 5px; + } + + + ::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.1); + border-radius: 5px; + } + + + ::-webkit-scrollbar-thumb:hover { + background: #555; /* Even lighter grey thumb on hover */ + } + + ::-webkit-scrollbar { + width: 10px; + border-radius: 5px; + } + + @keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } + } + \ No newline at end of file diff --git a/meet/app/layout.tsx b/app/layout.tsx similarity index 86% rename from meet/app/layout.tsx rename to app/layout.tsx index 4f53ab2..7f7497b 100644 --- a/meet/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,5 @@ import type { Metadata } from 'next'; -import { Bricolage_Grotesque, Inter, Press_Start_2P } from 'next/font/google'; +import { Inter, Roboto } from 'next/font/google'; import { TailwindIndicator } from '~/components/TailwindIndicator'; import { tw } from '~/utils/tw'; @@ -11,9 +11,9 @@ const inter = Inter({ variable: '--font-sans', }); -const display = Press_Start_2P({ +const display = Roboto({ weight: '400', - subsets: ['cyrillic'], + subsets: ['latin'], variable: '--font-display', }); @@ -33,7 +33,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) lang="en" className={tw('font-display h-full min-h-dvh antialiased', inter.variable, display.variable)} > - + {children} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..21ed469 --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,119 @@ +'use client'; +import { generateRandomAlphanumeric } from '~/lib/util'; +import { LiveKitRoom, RoomAudioRenderer, StartAudio, useToken } from '@livekit/components-react'; +import { AnimatePresence, motion } from 'framer-motion'; +import { useCallback, useEffect, useMemo, useState } from 'react'; + +import Playground, { PlaygroundMeta, PlaygroundOutputs } from '~/components/Playground'; +import { PlaygroundToast, ToastType } from '~/components/PlaygroundToast'; +import { useAppConfig } from '~/hooks/useAppConfig'; + +const themeColors = ['cyan', 'green', 'amber', 'blue', 'violet', 'rose', 'pink', 'teal']; + +export default function Page() { + const [toastMessage, setToastMessage] = useState<{ + message: string; + type: ToastType; + } | null>(null); + const [shouldConnect, setShouldConnect] = useState(false); + const [liveKitUrl, setLiveKitUrl] = useState(process.env.NEXT_PUBLIC_LIVEKIT_URL); + const [metadata, setMetadata] = useState([]); + + const [roomName, setRoomName] = useState(createRoomName()); + + const tokenOptions = useMemo(() => { + return { + userInfo: { identity: generateRandomAlphanumeric(16) }, + }; + }, []); + + // set a new room name each time the user disconnects so that a new token gets fetched behind the scenes for a different room + useEffect(() => { + if (shouldConnect === false) { + setRoomName(createRoomName()); + } + }, [shouldConnect]); + + useEffect(() => { + const md: PlaygroundMeta[] = []; + if (liveKitUrl && liveKitUrl !== process.env.NEXT_PUBLIC_LIVEKIT_URL) { + md.push({ name: 'LiveKit URL', value: liveKitUrl }); + } + if (tokenOptions.userInfo?.identity) { + md.push({ name: 'Room Name', value: roomName }); + md.push({ + name: 'Participant Identity', + value: tokenOptions.userInfo.identity, + }); + } + setMetadata(md); + }, [liveKitUrl, roomName, tokenOptions]); + + const token = useToken('/api/token', roomName, tokenOptions); + const appConfig = useAppConfig(); + const outputs = [ + appConfig?.outputs.audio && PlaygroundOutputs.Audio, + appConfig?.outputs.video && PlaygroundOutputs.Video, + appConfig?.outputs.chat && PlaygroundOutputs.Chat, + ].filter((item) => typeof item !== 'boolean') as PlaygroundOutputs[]; + + const handleConnect = useCallback((connect: boolean, opts?: { url: string; token: string }) => { + if (connect && opts) { + setLiveKitUrl(opts.url); + } + setShouldConnect(connect); + }, []); + + return ( +
+ + {toastMessage && ( + + { + setToastMessage(null); + }} + /> + + )} + + { + setToastMessage({ message: e.message, type: 'error' }); + console.error(e); + }} + > + + + + +
+ ); +} + +function createRoomName() { + return [generateRandomAlphanumeric(4), generateRandomAlphanumeric(4)].join('-'); +} diff --git a/meet/components/ActiveRoom.tsx b/components/ActiveRoom.tsx similarity index 100% rename from meet/components/ActiveRoom.tsx rename to components/ActiveRoom.tsx diff --git a/components/AgentMultibandAudioVisualizer.tsx b/components/AgentMultibandAudioVisualizer.tsx new file mode 100644 index 0000000..4bfe8b1 --- /dev/null +++ b/components/AgentMultibandAudioVisualizer.tsx @@ -0,0 +1,105 @@ +import { AgentState } from '~/lib/types'; +import { useEffect, useState } from 'react'; + +type AgentMultibandAudioVisualizerProps = { + state: AgentState; + barWidth: number; + minBarHeight: number; + maxBarHeight: number; + accentColor: string; + accentShade?: number; + frequencies: Float32Array[]; + borderRadius: number; + gap: number; +}; + +export const AgentMultibandAudioVisualizer = ({ + state, + barWidth, + minBarHeight, + maxBarHeight, + accentColor, + accentShade, + frequencies, + borderRadius, + gap, +}: AgentMultibandAudioVisualizerProps) => { + const summedFrequencies = frequencies.map((bandFrequencies) => { + const sum = bandFrequencies.reduce((a, b) => a + b, 0); + return Math.sqrt(sum / bandFrequencies.length); + }); + + const [thinkingIndex, setThinkingIndex] = useState(Math.floor(summedFrequencies.length / 2)); + const [thinkingDirection, setThinkingDirection] = useState<'left' | 'right'>('right'); + + useEffect(() => { + if (state !== 'thinking') { + setThinkingIndex(Math.floor(summedFrequencies.length / 2)); + return; + } + const timeout = setTimeout(() => { + if (thinkingDirection === 'right') { + if (thinkingIndex === summedFrequencies.length - 1) { + setThinkingDirection('left'); + setThinkingIndex((prev) => prev - 1); + } else { + setThinkingIndex((prev) => prev + 1); + } + } else { + if (thinkingIndex === 0) { + setThinkingDirection('right'); + setThinkingIndex((prev) => prev + 1); + } else { + setThinkingIndex((prev) => prev - 1); + } + } + }, 200); + + return () => clearTimeout(timeout); + }, [state, summedFrequencies.length, thinkingDirection, thinkingIndex]); + + return ( +
+ {summedFrequencies.map((frequency, index) => { + const isCenter = index === Math.floor(summedFrequencies.length / 2); + + let color = `${accentColor}-${accentShade}`; + let shadow = `shadow-lg-${accentColor}`; + let transform; + + if (state === 'listening' || state === 'idle') { + color = isCenter ? `${accentColor}-${accentShade}` : 'gray-950'; + shadow = !isCenter ? '' : shadow; + transform = !isCenter ? 'scale(1.0)' : 'scale(1.2)'; + } else if (state === 'speaking') { + color = `${accentColor}${accentShade ? '-' + accentShade : ''}`; + } else if (state === 'thinking') { + color = index === thinkingIndex ? `${accentColor}-${accentShade}` : 'gray-950'; + shadow = ''; + transform = thinkingIndex !== index ? 'scale(1)' : 'scale(1.1)'; + } + + return ( +
+ ); + })} +
+ ); +}; diff --git a/components/AudioInputTile.tsx b/components/AudioInputTile.tsx new file mode 100644 index 0000000..8071ec6 --- /dev/null +++ b/components/AudioInputTile.tsx @@ -0,0 +1,25 @@ +import { AgentMultibandAudioVisualizer } from './AgentMultibandAudioVisualizer'; + +type AudioInputTileProps = { + frequencies: Float32Array[]; +}; + +export const AudioInputTile = ({ frequencies }: AudioInputTileProps) => { + return ( +
+ +
+ ); +}; diff --git a/components/Button.tsx b/components/Button.tsx new file mode 100644 index 0000000..ae2361a --- /dev/null +++ b/components/Button.tsx @@ -0,0 +1,27 @@ +import React, { ButtonHTMLAttributes, ReactNode } from 'react'; + +type ButtonProps = { + accentColor: string; + children: ReactNode; + className?: string; + disabled?: boolean; +} & ButtonHTMLAttributes; + +export const Button: React.FC = ({ + accentColor, + children, + className, + disabled, + ...allProps +}) => { + return ( + + ); +}; diff --git a/components/ChatMessage.tsx b/components/ChatMessage.tsx new file mode 100644 index 0000000..ea3f096 --- /dev/null +++ b/components/ChatMessage.tsx @@ -0,0 +1,27 @@ +type ChatMessageProps = { + message: string; + accentColor: string; + name: string; + isSelf: boolean; +}; + +export const ChatMessage = ({ name, message, accentColor, isSelf }: ChatMessageProps) => { + return ( +
+
+ {name} +
+
+ {message} +
+
+ ); +}; diff --git a/components/ChatMessageInput.tsx b/components/ChatMessageInput.tsx new file mode 100644 index 0000000..cdf2758 --- /dev/null +++ b/components/ChatMessageInput.tsx @@ -0,0 +1,119 @@ +'use client'; + +import { useWindowResize } from '~/hooks/useWindowResize'; +import { useCallback, useEffect, useRef, useState } from 'react'; + +type ChatMessageInput = { + placeholder: string; + accentColor: string; + height: number; + onSend?: (message: string) => void; +}; + +export const ChatMessageInput = ({ + placeholder, + accentColor, + height, + onSend, +}: ChatMessageInput) => { + const [message, setMessage] = useState(''); + const [inputTextWidth, setInputTextWidth] = useState(0); + const [inputWidth, setInputWidth] = useState(0); + const hiddenInputRef = useRef(null); + const inputRef = useRef(null); + const windowSize = useWindowResize(); + const [isTyping, setIsTyping] = useState(false); + const [inputHasFocus, setInputHasFocus] = useState(false); + + const handleSend = useCallback(() => { + if (!onSend) { + return; + } + if (message === '') { + return; + } + + onSend(message); + setMessage(''); + }, [onSend, message]); + + useEffect(() => { + setIsTyping(true); + const timeout = setTimeout(() => { + setIsTyping(false); + }, 500); + + return () => clearTimeout(timeout); + }, [message]); + + useEffect(() => { + if (hiddenInputRef.current) { + setInputTextWidth(hiddenInputRef.current.clientWidth); + } + }, [hiddenInputRef, message]); + + useEffect(() => { + if (inputRef.current) { + setInputWidth(inputRef.current.clientWidth); + } + }, [hiddenInputRef, message, windowSize.width]); + + return ( +
+
+
0 ? Math.min(inputTextWidth, inputWidth - 20) - 4 : 0) + + 'px)', + }} + >
+ 0 ? '12px' : '24px', + caretShape: 'block', + }} + placeholder={placeholder} + value={message} + onChange={(e) => { + setMessage(e.target.value); + }} + onFocus={() => { + setInputHasFocus(true); + }} + onBlur={() => { + setInputHasFocus(false); + }} + onKeyDown={(e) => { + if (e.key === 'Enter') { + handleSend(); + } + }} + > + + {message.replaceAll(' ', '\u00a0')} + + +
+
+ ); +}; diff --git a/components/ChatTile.tsx b/components/ChatTile.tsx new file mode 100644 index 0000000..228f871 --- /dev/null +++ b/components/ChatTile.tsx @@ -0,0 +1,59 @@ +'use client'; +import { ChatMessage } from '~/components/ChatMessage'; +import { ChatMessageInput } from '~/components/ChatMessageInput'; +import { ChatMessage as ComponentsChatMessage } from '@livekit/components-react'; +import { useEffect, useRef } from 'react'; + +const inputHeight = 48; + +export type ChatMessageType = { + name: string; + message: string; + isSelf: boolean; + timestamp: number; +}; + +type ChatTileProps = { + messages: ChatMessageType[]; + accentColor: string; + onSend?: (message: string) => Promise; +}; + +export const ChatTile = ({ messages, accentColor, onSend }: ChatTileProps) => { + const containerRef = useRef(null); + useEffect(() => { + if (containerRef.current) { + containerRef.current.scrollTop = containerRef.current.scrollHeight; + } + }, [containerRef, messages]); + + return ( +
+
+
+ {messages.map((message, index) => ( + + ))} +
+
+ +
+ ); +}; diff --git a/components/ColorPicker.tsx b/components/ColorPicker.tsx new file mode 100644 index 0000000..2bbcbbf --- /dev/null +++ b/components/ColorPicker.tsx @@ -0,0 +1,44 @@ +'use client'; +import { useState } from 'react'; + +type ColorPickerProps = { + colors: string[]; + selectedColor: string; + onSelect: (color: string) => void; +}; + +export const ColorPicker = ({ colors, selectedColor, onSelect }: ColorPickerProps) => { + const [isHovering, setIsHovering] = useState(false); + const onMouseEnter = () => { + setIsHovering(true); + }; + const onMouseLeave = () => { + setIsHovering(false); + }; + + return ( +
+ {colors.map((color) => { + const isSelected = color === selectedColor; + const saturation = !isHovering && !isSelected ? 'saturate-[0.25]' : ''; + const borderColor = isSelected ? `border border-${color}-800` : 'border-transparent'; + const opacity = isSelected ? `opacity-100` : 'opacity-20'; + return ( +
{ + onSelect(color); + }} + > +
+
+ ); + })} +
+ ); +}; diff --git a/components/ConfigurationPanelItem.tsx b/components/ConfigurationPanelItem.tsx new file mode 100644 index 0000000..23a9e42 --- /dev/null +++ b/components/ConfigurationPanelItem.tsx @@ -0,0 +1,35 @@ +import { PlaygroundDeviceSelector } from '~/components/PlaygroundDeviceSelector'; +import { TrackToggle } from '@livekit/components-react'; +import { Track } from 'livekit-client'; + +type ConfigurationPanelItemProps = { + title: string; + children?: React.ReactNode; + deviceSelectorKind?: MediaDeviceKind; +}; + +export const ConfigurationPanelItem: React.FC = ({ + children, + title, + deviceSelectorKind, +}) => { + return ( +
+
+

{title}

+ {deviceSelectorKind && ( + + + + + )} +
+
{children}
+
+ ); +}; diff --git a/meet/components/Debug.tsx b/components/Debug.tsx similarity index 100% rename from meet/components/Debug.tsx rename to components/Debug.tsx diff --git a/components/LoadingSVG.tsx b/components/LoadingSVG.tsx new file mode 100644 index 0000000..5cfd20d --- /dev/null +++ b/components/LoadingSVG.tsx @@ -0,0 +1,31 @@ +export const LoadingSVG = ({ + diameter = 20, + strokeWidth = 4, +}: { + diameter?: number; + strokeWidth?: number; +}) => ( + + + + +); diff --git a/components/NameValueRow.tsx b/components/NameValueRow.tsx new file mode 100644 index 0000000..f4f135b --- /dev/null +++ b/components/NameValueRow.tsx @@ -0,0 +1,18 @@ +type NameValueRowProps = { + name: string; + value?: React.ReactNode; + valueColor?: string; +}; + +export const NameValueRow: React.FC = ({ + name, + value, + valueColor = 'gray-300', +}) => { + return ( +
+
{name}
+
{value}
+
+ ); +}; diff --git a/components/Playground.tsx b/components/Playground.tsx new file mode 100644 index 0000000..4bf2c82 --- /dev/null +++ b/components/Playground.tsx @@ -0,0 +1,434 @@ +'use client'; + +import { LoadingSVG } from '~/components/LoadingSVG'; +import { ChatMessageType, ChatTile } from '~/components/ChatTile'; +import { ColorPicker } from '~/components/ColorPicker'; +import { AudioInputTile } from '~/components/AudioInputTile'; +import { ConfigurationPanelItem } from '~/components/ConfigurationPanelItem'; +import { NameValueRow } from '~/components/NameValueRow'; +import { PlaygroundTab, PlaygroundTabbedTile, PlaygroundTile } from '~/components/PlaygroundTile'; +import { AgentMultibandAudioVisualizer } from '~/components/AgentMultibandAudioVisualizer'; +import { useMultibandTrackVolume } from '~/hooks/useTrackVolume'; +import { AgentState } from '~/lib/types'; +import { + VideoTrack, + useChat, + useConnectionState, + useDataChannel, + useLocalParticipant, + useParticipantInfo, + useRemoteParticipant, + useRemoteParticipants, + useTracks, +} from '@livekit/components-react'; +import { ConnectionState, LocalParticipant, RoomEvent, Track } from 'livekit-client'; +import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'; +import { Button } from './Button'; + +export enum PlaygroundOutputs { + Video, + Audio, + Chat, +} + +export interface PlaygroundMeta { + name: string; + value: string; +} + +export interface PlaygroundProps { + logo?: ReactNode; + title?: string; + githubLink?: string; + themeColors: string[]; + defaultColor: string; + outputs?: PlaygroundOutputs[]; + showQR?: boolean; + onConnect: (connect: boolean, opts?: { token: string; url: string }) => void; + metadata?: PlaygroundMeta[]; + videoFit?: 'contain' | 'cover'; +} + +const headerHeight = 56; + +export default function Playground({ + logo, + title, + githubLink, + outputs, + showQR, + themeColors, + defaultColor, + onConnect, + metadata, + videoFit, +}: PlaygroundProps) { + const [agentState, setAgentState] = useState('offline'); + const [themeColor, setThemeColor] = useState(defaultColor); + const [messages, setMessages] = useState([]); + const [transcripts, setTranscripts] = useState([]); + const { localParticipant } = useLocalParticipant(); + + const participants = useRemoteParticipants({ + updateOnlyOn: [RoomEvent.ParticipantMetadataChanged], + }); + const agentParticipant = participants.find((p) => p.isAgent); + + const { send: sendChat, chatMessages } = useChat(); + const visualizerState = useMemo(() => { + if (agentState === 'thinking') { + return 'thinking'; + } else if (agentState === 'speaking') { + return 'talking'; + } + return 'idle'; + }, [agentState]); + + const roomState = useConnectionState(); + const tracks = useTracks(); + + const agentAudioTrack = tracks.find( + (trackRef) => trackRef.publication.kind === Track.Kind.Audio && trackRef.participant.isAgent, + ); + + const agentVideoTrack = tracks.find( + (trackRef) => trackRef.publication.kind === Track.Kind.Video && trackRef.participant.isAgent, + ); + + const subscribedVolumes = useMultibandTrackVolume(agentAudioTrack?.publication.track, 5); + + const localTracks = tracks.filter(({ participant }) => participant instanceof LocalParticipant); + const localVideoTrack = localTracks.find(({ source }) => source === Track.Source.Camera); + const localMicTrack = localTracks.find(({ source }) => source === Track.Source.Microphone); + + const localMultibandVolume = useMultibandTrackVolume(localMicTrack?.publication.track, 20); + + useEffect(() => { + if (!agentParticipant) { + setAgentState('offline'); + return; + } + let agentMd: any = {}; + if (agentParticipant.metadata) { + agentMd = JSON.parse(agentParticipant.metadata); + } + if (agentMd.agent_state) { + setAgentState(agentMd.agent_state); + } else { + setAgentState('starting'); + } + }, [agentParticipant, agentParticipant?.metadata]); + + const isAgentConnected = agentState !== 'offline'; + + const onDataReceived = useCallback( + (msg: any) => { + if (msg.topic === 'transcription') { + const decoded = JSON.parse(new TextDecoder('utf-8').decode(msg.payload)); + let timestamp = new Date().getTime(); + if ('timestamp' in decoded && decoded.timestamp > 0) { + timestamp = decoded.timestamp; + } + setTranscripts([ + ...transcripts, + { + name: 'You', + message: decoded.text, + timestamp: timestamp, + isSelf: true, + }, + ]); + } + }, + [transcripts], + ); + + // combine transcripts and chat together + useEffect(() => { + const allMessages = [...transcripts]; + for (const msg of chatMessages) { + const isAgent = msg.from?.identity === agentParticipant?.identity; + const isSelf = msg.from?.identity === localParticipant?.identity; + let name = msg.from?.name; + if (!name) { + if (isAgent) { + name = 'Agent'; + } else if (isSelf) { + name = 'You'; + } else { + name = 'Unknown'; + } + } + allMessages.push({ + name, + message: msg.message, + timestamp: msg?.timestamp, + isSelf: isSelf, + }); + } + allMessages.sort((a, b) => a.timestamp - b.timestamp); + setMessages(allMessages); + }, [transcripts, chatMessages, localParticipant, agentParticipant]); + + useDataChannel(onDataReceived); + + const videoTileContent = useMemo(() => { + const videoFitClassName = `object-${videoFit}`; + return ( +
+ {agentVideoTrack ? ( + + ) : ( +
+ + Waiting for video track +
+ )} +
+ ); + }, [agentVideoTrack, videoFit]); + + const audioTileContent = useMemo(() => { + return ( +
+ {agentAudioTrack ? ( + + ) : ( +
+ + Waiting for audio track +
+ )} +
+ ); + }, [agentAudioTrack, subscribedVolumes, themeColor, agentState]); + + const chatTileContent = useMemo(() => { + return ; + }, [messages, themeColor, sendChat]); + + const settingsTileContent = useMemo(() => { + return ( +
+ +
+ {metadata?.map((data, index) => ( + + ))} +
+
+ + + + +
+ + ) : ( + roomState + ) + } + valueColor={ + roomState === ConnectionState.Connected ? `${themeColor}-500` : 'gray-500' + } + /> + + ) : ( + 'false' + ) + } + valueColor={isAgentConnected ? `${themeColor}-500` : 'gray-500'} + /> + + + {agentState} +
+ ) : ( + agentState + ) + } + valueColor={agentState === 'speaking' ? `${themeColor}-500` : 'gray-500'} + /> +
+ + {localVideoTrack && ( + +
+ +
+
+ )} + {localMicTrack && ( + + + + )} +
+ + { + setThemeColor(color); + }} + /> + +
+ + ); + }, [ + agentState, + isAgentConnected, + localMicTrack, + localMultibandVolume, + localVideoTrack, + metadata, + roomState, + themeColor, + themeColors, + showQR, + ]); + + let mobileTabs: PlaygroundTab[] = []; + if (outputs?.includes(PlaygroundOutputs.Video)) { + mobileTabs.push({ + title: 'Video', + content: ( + + {videoTileContent} + + ), + }); + } + + if (outputs?.includes(PlaygroundOutputs.Audio)) { + mobileTabs.push({ + title: 'Audio', + content: ( + + {audioTileContent} + + ), + }); + } + + if (outputs?.includes(PlaygroundOutputs.Chat)) { + mobileTabs.push({ + title: 'Chat', + content: chatTileContent, + }); + } + + mobileTabs.push({ + title: 'Settings', + content: ( + + {settingsTileContent} + + ), + }); + + return ( + <> +
+
+ +
+ + + {outputs?.includes(PlaygroundOutputs.Chat) && ( + + {chatTileContent} + + )} + + {settingsTileContent} + +
+ + ); +} diff --git a/components/PlaygroundDeviceSelector.tsx b/components/PlaygroundDeviceSelector.tsx new file mode 100644 index 0000000..96164de --- /dev/null +++ b/components/PlaygroundDeviceSelector.tsx @@ -0,0 +1,86 @@ +'use client'; + +import { useMediaDeviceSelect } from '@livekit/components-react'; +import { useEffect, useState } from 'react'; + +type PlaygroundDeviceSelectorProps = { + kind: MediaDeviceKind; +}; + +export const PlaygroundDeviceSelector = ({ kind }: PlaygroundDeviceSelectorProps) => { + const [showMenu, setShowMenu] = useState(false); + const deviceSelect = useMediaDeviceSelect({ kind: kind }); + const [selectedDeviceName, setSelectedDeviceName] = useState(''); + + useEffect(() => { + deviceSelect.devices.forEach((device) => { + if (device.deviceId === deviceSelect.activeDeviceId) { + setSelectedDeviceName(device.label); + } + }); + }, [deviceSelect.activeDeviceId, deviceSelect.devices, selectedDeviceName]); + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (showMenu) { + setShowMenu(false); + } + }; + document.addEventListener('click', handleClickOutside); + return () => { + document.removeEventListener('click', handleClickOutside); + }; + }, [showMenu]); + + return ( +
+ +
+ {deviceSelect.devices.map((device, index) => { + return ( +
{ + deviceSelect.setActiveMediaDevice(device.deviceId); + setShowMenu(false); + }} + className={`${ + device.deviceId === deviceSelect.activeDeviceId ? 'text-white' : 'text-gray-500' + } bg-gray-900 text-xs py-2 px-2 cursor-pointer hover:bg-gray-800 hover:text-white`} + key={index} + > + {device.label} +
+ ); + })} +
+
+ ); +}; + +const ChevronSVG = () => ( + + + +); diff --git a/components/PlaygroundTile.tsx b/components/PlaygroundTile.tsx new file mode 100644 index 0000000..b2a25ab --- /dev/null +++ b/components/PlaygroundTile.tsx @@ -0,0 +1,104 @@ +'use client'; + +import { ReactNode, useState } from 'react'; + +const titleHeight = 32; + +type PlaygroundTileProps = { + title?: string; + children?: ReactNode; + className?: string; + childrenClassName?: string; + padding?: boolean; + backgroundColor?: string; +}; + +export type PlaygroundTab = { + title: string; + content: ReactNode; +}; + +export type PlaygroundTabbedTileProps = { + tabs: PlaygroundTab[]; + initialTab?: number; +} & PlaygroundTileProps; + +export const PlaygroundTile: React.FC = ({ + children, + title, + className, + childrenClassName, + padding = true, + backgroundColor = 'transparent', +}) => { + const contentPadding = padding ? 4 : 0; + return ( +
+ {title && ( +
+

{title}

+
+ )} +
+ {children} +
+
+ ); +}; + +export const PlaygroundTabbedTile: React.FC = ({ + tabs, + initialTab = 0, + className, + childrenClassName, + backgroundColor = 'transparent', +}) => { + const contentPadding = 4; + const [activeTab, setActiveTab] = useState(initialTab); + return ( +
+
+ {tabs.map((tab, index) => ( + + ))} +
+
+ {tabs[activeTab].content} +
+
+ ); +}; diff --git a/components/PlaygroundToast.tsx b/components/PlaygroundToast.tsx new file mode 100644 index 0000000..e278a3a --- /dev/null +++ b/components/PlaygroundToast.tsx @@ -0,0 +1,36 @@ +export type ToastType = 'error' | 'success' | 'info'; +export type ToastProps = { + message: string; + type: ToastType; + onDismiss: () => void; +}; + +export const PlaygroundToast = ({ message, type, onDismiss }: ToastProps) => { + const color = type === 'error' ? 'red' : type === 'success' ? 'green' : 'amber'; + return ( +
+ + {message} +
+ ); +}; diff --git a/meet/components/TailwindIndicator.tsx b/components/TailwindIndicator.tsx similarity index 100% rename from meet/components/TailwindIndicator.tsx rename to components/TailwindIndicator.tsx diff --git a/meet/components/ui/button.tsx b/components/ui/button.tsx similarity index 100% rename from meet/components/ui/button.tsx rename to components/ui/button.tsx diff --git a/hooks/useAppConfig.tsx b/hooks/useAppConfig.tsx new file mode 100644 index 0000000..23957c3 --- /dev/null +++ b/hooks/useAppConfig.tsx @@ -0,0 +1,54 @@ +import jsYaml from 'js-yaml'; + +const APP_CONFIG = process.env.NEXT_PUBLIC_APP_CONFIG; + +export type AppConfig = { + title: string; + description: string; + github_link?: string; + theme_color?: string; + video_fit?: 'cover' | 'contain'; + outputs: { + audio: boolean; + video: boolean; + chat: boolean; + }; + inputs: { + mic: boolean; + camera: boolean; + }; + show_qr?: boolean; +}; + +// Fallback if NEXT_PUBLIC_APP_CONFIG is not set +const defaultConfig: AppConfig = { + title: 'Agents Playground', + description: 'A playground for testing LiveKit Agents', + theme_color: 'cyan', + video_fit: 'cover', + outputs: { + audio: true, + video: true, + chat: true, + }, + inputs: { + mic: true, + camera: true, + }, + show_qr: false, +}; + +export const useAppConfig = (): AppConfig => { + if (APP_CONFIG) { + try { + const parsedConfig = jsYaml.load(APP_CONFIG); + console.log('parsedConfig:', parsedConfig); + return parsedConfig as AppConfig; + } catch (e) { + console.error('Error parsing app config:', e); + return defaultConfig; + } + } else { + return defaultConfig; + } +}; diff --git a/hooks/useTrackVolume.tsx b/hooks/useTrackVolume.tsx new file mode 100644 index 0000000..61416cf --- /dev/null +++ b/hooks/useTrackVolume.tsx @@ -0,0 +1,110 @@ +import { Track } from 'livekit-client'; +import { useEffect, useState } from 'react'; + +export const useTrackVolume = (track?: Track) => { + const [volume, setVolume] = useState(0); + useEffect(() => { + if (!track || !track.mediaStream) { + return; + } + + const ctx = new AudioContext(); + const source = ctx.createMediaStreamSource(track.mediaStream); + const analyser = ctx.createAnalyser(); + analyser.fftSize = 32; + analyser.smoothingTimeConstant = 0; + source.connect(analyser); + + const bufferLength = analyser.frequencyBinCount; + const dataArray = new Uint8Array(bufferLength); + + const updateVolume = () => { + analyser.getByteFrequencyData(dataArray); + let sum = 0; + for (let i = 0; i < dataArray.length; i++) { + const a = dataArray[i]; + sum += a * a; + } + setVolume(Math.sqrt(sum / dataArray.length) / 255); + }; + + const interval = setInterval(updateVolume, 1000 / 30); + + return () => { + source.disconnect(); + clearInterval(interval); + }; + }, [track, track?.mediaStream]); + + return volume; +}; + +const normalizeFrequencies = (frequencies: Float32Array) => { + const normalizeDb = (value: number) => { + const minDb = -100; + const maxDb = -10; + let db = 1 - (Math.max(minDb, Math.min(maxDb, value)) * -1) / 100; + db = Math.sqrt(db); + + return db; + }; + + // Normalize all frequency values + return frequencies.map((value) => { + if (value === -Infinity) { + return 0; + } + return normalizeDb(value); + }); +}; + +export const useMultibandTrackVolume = ( + track?: Track, + bands: number = 5, + loPass: number = 100, + hiPass: number = 600, +) => { + const [frequencyBands, setFrequencyBands] = useState([]); + + useEffect(() => { + if (!track || !track.mediaStream) { + return; + } + + const ctx = new AudioContext(); + const source = ctx.createMediaStreamSource(track.mediaStream); + const analyser = ctx.createAnalyser(); + analyser.fftSize = 2048; + source.connect(analyser); + + const bufferLength = analyser.frequencyBinCount; + const dataArray = new Float32Array(bufferLength); + + const updateVolume = () => { + analyser.getFloatFrequencyData(dataArray); + let frequencies: Float32Array = new Float32Array(dataArray.length); + for (let i = 0; i < dataArray.length; i++) { + frequencies[i] = dataArray[i]; + } + frequencies = frequencies.slice(loPass, hiPass); + + const normalizedFrequencies = normalizeFrequencies(frequencies); + const chunkSize = Math.ceil(normalizedFrequencies.length / bands); + const chunks: Float32Array[] = []; + for (let i = 0; i < bands; i++) { + chunks.push(normalizedFrequencies.slice(i * chunkSize, (i + 1) * chunkSize)); + } + + setFrequencyBands(chunks); + }; + + const interval = setInterval(updateVolume, 10); + + return () => { + source.disconnect(); + clearInterval(interval); + }; + }, [track, track?.mediaStream, loPass, hiPass, bands]); + + return frequencyBands; +}; diff --git a/hooks/useWindowResize.ts b/hooks/useWindowResize.ts new file mode 100644 index 0000000..d9e959a --- /dev/null +++ b/hooks/useWindowResize.ts @@ -0,0 +1,27 @@ +import { useEffect, useState } from 'react'; + +export const useWindowResize = () => { + const [size, setSize] = useState({ + width: 0, + height: 0, + }); + + useEffect(() => { + const handleResize = () => { + setSize({ + width: window.innerWidth, + height: window.innerHeight, + }); + }; + + handleResize(); + + window.addEventListener('resize', handleResize); + + return () => { + window.removeEventListener('resize', handleResize); + }; + }, []); + + return size; +}; diff --git a/kitt.py b/kitt.py new file mode 100644 index 0000000..ced1594 --- /dev/null +++ b/kitt.py @@ -0,0 +1,218 @@ +# Copyright 2023 LiveKit, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import asyncio +from datetime import datetime +from enum import Enum +import json +import logging +from typing import AsyncIterable + +from livekit import rtc, agents +from livekit.agents.tts import SynthesisEvent, SynthesisEventType +from chatgpt import ( + ChatGPTMessage, + ChatGPTMessageRole, + ChatGPTPlugin, +) +from livekit.plugins.deepgram import STT +from livekit.plugins.elevenlabs import TTS + +PROMPT = "You are KITT, a friendly voice assistant powered by LiveKit. \ + Conversation should be personable, and be sure to ask follow up questions. \ + If your response is a question, please append a question mark symbol to the end of it.\ + Don't respond with more than a few sentences." +INTRO = "Hello, I am KITT, a friendly voice assistant powered by LiveKit Agents. \ + You can find my source code in the top right of this screen if you're curious how I work. \ + Feel free to ask me anything — I'm here to help! Just start talking or type in the chat." +SIP_INTRO = "Hello, I am KITT, a friendly voice assistant powered by LiveKit Agents. \ + Feel free to ask me anything — I'm here to help! Just start talking." + + +# convert intro response to a stream +async def intro_text_stream(sip: bool): + if sip: + yield SIP_INTRO + return + + yield INTRO + + +AgentState = Enum("AgentState", "IDLE, LISTENING, THINKING, SPEAKING") + +ELEVEN_TTS_SAMPLE_RATE = 24000 +ELEVEN_TTS_CHANNELS = 1 + + +class KITT: + @classmethod + async def create(cls, ctx: agents.JobContext): + kitt = KITT(ctx) + await kitt.start() + + def __init__(self, ctx: agents.JobContext): + # plugins + self.chatgpt_plugin = ChatGPTPlugin( + prompt=PROMPT, message_capacity=20, model="gpt-4-1106-preview" + ) + self.stt_plugin = STT( + min_silence_duration=100, + ) + self.tts_plugin = TTS( + model_id="eleven_turbo_v2", sample_rate=ELEVEN_TTS_SAMPLE_RATE + ) + + self.ctx: agents.JobContext = ctx + self.chat = rtc.ChatManager(ctx.room) + self.audio_out = rtc.AudioSource(ELEVEN_TTS_SAMPLE_RATE, ELEVEN_TTS_CHANNELS) + + self._sending_audio = False + self._processing = False + self._agent_state: AgentState = AgentState.IDLE + + self.chat.on("message_received", self.on_chat_received) + self.ctx.room.on("track_subscribed", self.on_track_subscribed) + + async def start(self): + # if you have to perform teardown cleanup, you can listen to the disconnected event + # self.ctx.room.on("disconnected", your_cleanup_function) + + # publish audio track + track = rtc.LocalAudioTrack.create_audio_track("agent-mic", self.audio_out) + await self.ctx.room.local_participant.publish_track(track) + + # allow the participant to fully subscribe to the agent's audio track, so it doesn't miss + # anything in the beginning + await asyncio.sleep(1) + + sip = self.ctx.room.name.startswith("sip") + await self.process_chatgpt_result(intro_text_stream(sip)) + self.update_state() + + def on_chat_received(self, message: rtc.ChatMessage): + # TODO: handle deleted and updated messages in message context + if message.deleted: + return + + msg = ChatGPTMessage(role=ChatGPTMessageRole.user, content=message.message) + chatgpt_result = self.chatgpt_plugin.add_message(msg) + self.ctx.create_task(self.process_chatgpt_result(chatgpt_result)) + + def on_track_subscribed( + self, + track: rtc.Track, + publication: rtc.TrackPublication, + participant: rtc.RemoteParticipant, + ): + self.ctx.create_task(self.process_track(track)) + + async def process_track(self, track: rtc.Track): + audio_stream = rtc.AudioStream(track) + stream = self.stt_plugin.stream() + self.ctx.create_task(self.process_stt_stream(stream)) + async for audio_frame_event in audio_stream: + if self._agent_state != AgentState.LISTENING: + continue + stream.push_frame(audio_frame_event.frame) + await stream.flush() + + async def process_stt_stream(self, stream): + buffered_text = "" + async for event in stream: + if event.alternatives[0].text == "": + continue + if event.is_final: + buffered_text = " ".join([buffered_text, event.alternatives[0].text]) + + if not event.end_of_speech: + continue + await self.ctx.room.local_participant.publish_data( + json.dumps( + { + "text": buffered_text, + "timestamp": int(datetime.now().timestamp() * 1000), + } + ), + topic="transcription", + ) + + msg = ChatGPTMessage(role=ChatGPTMessageRole.user, content=buffered_text) + chatgpt_stream = self.chatgpt_plugin.add_message(msg) + self.ctx.create_task(self.process_chatgpt_result(chatgpt_stream)) + buffered_text = "" + + async def process_chatgpt_result(self, text_stream): + # ChatGPT is streamed, so we'll flip the state immediately + self.update_state(processing=True) + + stream = self.tts_plugin.stream() + # send audio to TTS in parallel + self.ctx.create_task(self.send_audio_stream(stream)) + all_text = "" + async for text in text_stream: + stream.push_text(text) + all_text += text + + self.update_state(processing=False) + # buffer up the entire response from ChatGPT before sending a chat message + await self.chat.send_message(all_text) + await stream.flush() + + async def send_audio_stream(self, tts_stream: AsyncIterable[SynthesisEvent]): + async for e in tts_stream: + if e.type == SynthesisEventType.STARTED: + self.update_state(sending_audio=True) + elif e.type == SynthesisEventType.FINISHED: + self.update_state(sending_audio=False) + elif e.type == SynthesisEventType.AUDIO: + await self.audio_out.capture_frame(e.audio.data) + await tts_stream.aclose() + + def update_state(self, sending_audio: bool = None, processing: bool = None): + if sending_audio is not None: + self._sending_audio = sending_audio + if processing is not None: + self._processing = processing + + state = AgentState.LISTENING + if self._sending_audio: + state = AgentState.SPEAKING + elif self._processing: + state = AgentState.THINKING + + self._agent_state = state + metadata = json.dumps( + { + "agent_state": state.name.lower(), + } + ) + self.ctx.create_task(self.ctx.room.local_participant.update_metadata(metadata)) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + + async def job_request_cb(job_request: agents.JobRequest): + logging.info("Accepting job for KITT") + + await job_request.accept( + KITT.create, + identity="kitt_agent", + name="KITT", + auto_subscribe=agents.AutoSubscribe.AUDIO_ONLY, + auto_disconnect=agents.AutoDisconnect.DEFAULT, + ) + + worker = agents.Worker(request_handler=job_request_cb) + agents.run_app(worker) \ No newline at end of file diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 0000000..a828b2e --- /dev/null +++ b/lib/types.ts @@ -0,0 +1,18 @@ +import { LocalAudioTrack, LocalVideoTrack } from 'livekit-client'; + +export interface SessionProps { + roomName: string; + identity: string; + audioTrack?: LocalAudioTrack; + videoTrack?: LocalVideoTrack; + region?: string; + turnServer?: RTCIceServer; + forceRelay?: boolean; +} + +export interface TokenResult { + identity: string; + accessToken: string; +} + +export type AgentState = 'idle' | 'listening' | 'speaking' | 'thinking' | 'offline' | 'starting'; diff --git a/lib/util.ts b/lib/util.ts new file mode 100644 index 0000000..357fabf --- /dev/null +++ b/lib/util.ts @@ -0,0 +1,11 @@ +export function generateRandomAlphanumeric(length: number): string { + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; + const charactersLength = characters.length; + + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + + return result; +} diff --git a/lkgpt/Cargo.toml b/lkgpt/Cargo.toml deleted file mode 100644 index a027692..0000000 --- a/lkgpt/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "lkgpt" -version = "0.0.1" -edition = "2021" -rust-version.workspace = true -default-run = "lkgpt" - -[dependencies] -actix-web = "4.4.0" -anyhow = "1.0.75" -async-openai = "0.18.0" -async-trait = "0.1.74" -base64 = "0.21.5" -bevy = { version = "0.12.0", default-features = false, features = [ - "bevy_asset", - "bevy_core_pipeline", - "bevy_render", -] } -bevy_gaussian_splatting = { version = "2.0.2", default-features = true } -bevy_panorbit_camera = "0.10.0" -bevy_web_asset = "0.7.0" -bytes = "1.5.0" -chrono = "0.4.31" -crossbeam-channel = "0.5.10" -deepgram = { git = "https://github.com/cs50victor/deepgram-rust-sdk.git", branch = "live-fork" } -dotenvy = "0.15.7" -ezsockets = { version = "0.6.1", features = ["rustls"] } -futures = "0.3.29" -futures-intrusive = "0.5.0" -image = { version = "0.24.7", default-features = false, features = ["png"] } -livekit = { git = "https://github.com/cs50victor/livekit-rust-sdks.git", branch = "update-proto", features = [ - "native-tls", -] } -livekit-api = { git = "https://github.com/cs50victor/livekit-rust-sdks.git", branch = "update-proto" } -livekit-protocol = { git = "https://github.com/cs50victor/livekit-rust-sdks.git", branch = "update-proto" } -log = "0.4.20" -parking_lot = "0.12.1" -pollster = "0.3.0" -pretty_env_logger = "0.5.0" -rodio = { version = "0.17.3", features = ["symphonia-mp3"] } -serde = { version = "1.0.192", features = ["derive"] } -serde_json = "1.0.108" -tokio = { version = "1.33.0", features = ["full"] } -url = "2.5.0" -wgpu = { version = "0.17.1" } diff --git a/lkgpt/src/controls.rs b/lkgpt/src/controls.rs deleted file mode 100644 index ece0108..0000000 --- a/lkgpt/src/controls.rs +++ /dev/null @@ -1,18 +0,0 @@ -use bevy::ecs::{ - system::Resource, - world::{FromWorld, World}, -}; - -/// Allows LLM / Model to Control the Bevy World remotely -#[derive(Resource)] -pub struct WorldControlChannel { - pub tx: crossbeam_channel::Sender, - rx: crossbeam_channel::Receiver, -} - -impl FromWorld for WorldControlChannel { - fn from_world(_: &mut World) -> Self { - let (tx, rx) = crossbeam_channel::unbounded::(); - Self { tx, rx } - } -} diff --git a/lkgpt/src/frame_capture.rs b/lkgpt/src/frame_capture.rs deleted file mode 100644 index f41081d..0000000 --- a/lkgpt/src/frame_capture.rs +++ /dev/null @@ -1,373 +0,0 @@ -/// Derived from: https://github.com/bevyengine/bevy/pull/5550 -pub mod image_copy { - use std::sync::Arc; - - use bevy::{ - prelude::*, - render::{ - render_asset::RenderAssets, - render_graph::{self, NodeRunError, RenderGraph, RenderGraphContext}, - renderer::{RenderContext, RenderDevice, RenderQueue}, - Extract, RenderApp, - }, - }; - - use bevy::render::render_resource::{ - Buffer, BufferDescriptor, BufferUsages, CommandEncoderDescriptor, Extent3d, - ImageCopyBuffer, ImageDataLayout, MapMode, - }; - use pollster::FutureExt; - use wgpu::Maintain; - - use std::sync::atomic::{AtomicBool, Ordering}; - - pub fn receive_images( - image_copiers: Query<&ImageCopier>, - mut images: ResMut>, - render_device: Res, - ) { - for image_copier in image_copiers.iter() { - if !image_copier.enabled() { - continue; - } - // Derived from: https://sotrh.github.io/learn-wgpu/showcase/windowless/#a-triangle-without-a-window - // We need to scope the mapping variables so that we can - // unmap the buffer - async { - let buffer_slice = image_copier.buffer.slice(..); - - // NOTE: We have to create the mapping THEN device.poll() before await - // the future. Otherwise the application will freeze. - let (tx, rx) = futures_intrusive::channel::shared::oneshot_channel(); - buffer_slice.map_async(MapMode::Read, move |result| { - tx.send(result).unwrap(); - }); - render_device.poll(Maintain::Wait); - rx.receive().await.unwrap().unwrap(); - if let Some(image) = images.get_mut(&image_copier.dst_image) { - image.data = buffer_slice.get_mapped_range().to_vec(); - } - - image_copier.buffer.unmap(); - } - .block_on(); - } - } - - pub const IMAGE_COPY: &str = "image_copy"; - - pub struct ImageCopyPlugin; - impl Plugin for ImageCopyPlugin { - fn build(&self, app: &mut App) { - let render_app = app.add_systems(Update, receive_images).sub_app_mut(RenderApp); - - render_app.add_systems(ExtractSchedule, image_copy_extract); - - let mut graph = render_app.world.get_resource_mut::().unwrap(); - - graph.add_node(IMAGE_COPY, ImageCopyDriver); - - graph.add_node_edge(IMAGE_COPY, bevy::render::main_graph::node::CAMERA_DRIVER); - } - } - - #[derive(Clone, Default, Resource, Deref, DerefMut)] - pub struct ImageCopiers(pub Vec); - - #[derive(Clone, Component)] - pub struct ImageCopier { - buffer: Buffer, - enabled: Arc, - src_image: Handle, - dst_image: Handle, - } - - impl ImageCopier { - pub fn new( - src_image: Handle, - dst_image: Handle, - size: Extent3d, - render_device: &RenderDevice, - ) -> ImageCopier { - let padded_bytes_per_row = - RenderDevice::align_copy_bytes_per_row((size.width) as usize) * 4; - - let cpu_buffer = render_device.create_buffer(&BufferDescriptor { - label: None, - size: padded_bytes_per_row as u64 * size.height as u64, - usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST, - mapped_at_creation: false, - }); - - ImageCopier { - buffer: cpu_buffer, - src_image, - dst_image, - enabled: Arc::new(AtomicBool::new(true)), - } - } - - pub fn enabled(&self) -> bool { - self.enabled.load(Ordering::Relaxed) - } - } - - pub fn image_copy_extract(mut commands: Commands, image_copiers: Extract>) { - commands.insert_resource(ImageCopiers( - image_copiers.iter().cloned().collect::>(), - )); - } - - #[derive(Default)] - pub struct ImageCopyDriver; - - impl render_graph::Node for ImageCopyDriver { - fn run( - &self, - _graph: &mut RenderGraphContext, - render_context: &mut RenderContext, - world: &World, - ) -> Result<(), NodeRunError> { - let image_copiers = world.get_resource::().unwrap(); - let gpu_images = world.get_resource::>().unwrap(); - - for image_copier in image_copiers.iter() { - if !image_copier.enabled() { - continue; - } - - let src_image = gpu_images.get(&image_copier.src_image).unwrap(); - - let mut encoder = render_context - .render_device() - .create_command_encoder(&CommandEncoderDescriptor::default()); - - let block_dimensions = src_image.texture_format.block_dimensions(); - let block_size = src_image.texture_format.block_size(None).unwrap(); - - let padded_bytes_per_row = RenderDevice::align_copy_bytes_per_row( - (src_image.size.x as usize / block_dimensions.0 as usize) * block_size as usize, - ); - - let texture_extent = Extent3d { - width: src_image.size.x as u32, - height: src_image.size.y as u32, - depth_or_array_layers: 1, - }; - - encoder.copy_texture_to_buffer( - src_image.texture.as_image_copy(), - ImageCopyBuffer { - buffer: &image_copier.buffer, - layout: ImageDataLayout { - offset: 0, - bytes_per_row: Some( - std::num::NonZeroU32::new(padded_bytes_per_row as u32) - .unwrap() - .into(), - ), - rows_per_image: None, - }, - }, - texture_extent, - ); - - let render_queue = world.get_resource::().unwrap(); - render_queue.submit(std::iter::once(encoder.finish())); - } - - Ok(()) - } - } -} -pub mod scene { - - use bevy::{ - prelude::*, - render::{camera::RenderTarget, renderer::RenderDevice}, - }; - - use pollster::FutureExt; - use wgpu::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsages}; - - use super::image_copy::ImageCopier; - - #[derive(Component, Default)] - pub struct CaptureCamera; - - #[derive(Component, Deref, DerefMut)] - struct ImageToSave(Handle); - - pub struct CaptureFramePlugin; - impl Plugin for CaptureFramePlugin { - fn build(&self, app: &mut App) { - app.add_systems( - PostUpdate, - update - .run_if(resource_exists::()) - .run_if(resource_exists::()), - ); - } - } - - #[derive(Debug, Default, Resource, Event)] - pub struct SceneController { - state: SceneState, - name: String, - width: u32, - height: u32, - } - - impl SceneController { - pub fn new(width: u32, height: u32) -> SceneController { - SceneController { state: SceneState::BuildScene, name: String::from(""), width, height } - } - - pub fn dimensions(&self) -> (u32, u32) { - (self.width, self.height) - } - } - - #[derive(Debug, Default)] - pub enum SceneState { - #[default] - BuildScene, - Render(u32), - } - - impl SceneState { - pub fn decrement(&mut self) { - if let SceneState::Render(n) = self { - *n -= 1; - } - } - } - - pub fn setup_render_target( - commands: &mut Commands, - images: &mut ResMut>, - render_device: &Res, - scene_controller: &mut ResMut, - pre_roll_frames: u32, - scene_name: String, - ) -> RenderTarget { - let size = Extent3d { - width: scene_controller.width, - height: scene_controller.height, - ..Default::default() - }; - - // This is the texture that will be rendered to. - let mut render_target_image = Image { - texture_descriptor: TextureDescriptor { - label: None, - size, - dimension: TextureDimension::D2, - format: TextureFormat::Rgba8UnormSrgb, - mip_level_count: 1, - sample_count: 1, - usage: TextureUsages::COPY_SRC - | TextureUsages::COPY_DST - | TextureUsages::TEXTURE_BINDING - | TextureUsages::RENDER_ATTACHMENT, - view_formats: &[], - }, - ..Default::default() - }; - render_target_image.resize(size); - let render_target_image_handle = images.add(render_target_image); - - // This is the texture that will be copied to. - let mut cpu_image = Image { - texture_descriptor: TextureDescriptor { - label: None, - size, - dimension: TextureDimension::D2, - format: TextureFormat::Rgba8UnormSrgb, - mip_level_count: 1, - sample_count: 1, - usage: TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING, - view_formats: &[], - }, - ..Default::default() - }; - cpu_image.resize(size); - let cpu_image_handle = images.add(cpu_image); - - commands.spawn(ImageCopier::new( - render_target_image_handle.clone(), - cpu_image_handle.clone(), - size, - render_device, - )); - - commands.spawn(ImageToSave(cpu_image_handle)); - - scene_controller.state = SceneState::Render(pre_roll_frames); - scene_controller.name = scene_name; - RenderTarget::Image(render_target_image_handle) - } - - fn update( - mut images: ResMut>, - images_to_save: Query<&ImageToSave>, - async_runtime: Res, - single_frame_data: ResMut, - mut scene_controller: ResMut, - ) { - if let SceneState::Render(n) = scene_controller.state { - if n < 1 { - let single_frame_data = single_frame_data.into_inner(); - let pixel_size = single_frame_data.pixel_size; - for image in images_to_save.iter() { - let img_bytes = images.get_mut(image.id()).unwrap(); - - let rgba_img = match img_bytes.clone().try_into_dynamic() { - Ok(img) => img.to_rgba8(), - Err(e) => panic!("Failed to create image buffer {e:?}"), - }; - - let (w, h) = rgba_img.dimensions(); - - if let Err(e) = async_runtime - .rt - .spawn_blocking({ - let frame_data = single_frame_data.frame_data.clone(); - let source = single_frame_data.video_src.clone(); - move || { - // VIDEO FRAME BUFFER (i420_buffer) - let mut video_frame = frame_data.video_frame.lock(); - let (stride_y, stride_u, stride_v) = video_frame.buffer.strides(); - let (data_y, data_u, data_v) = video_frame.buffer.data_mut(); - - // convert captured rgba image to i420 - livekit::webrtc::native::yuv_helper::abgr_to_i420( - rgba_img.as_raw(), - w * pixel_size, - data_y, - stride_y, - data_u, - stride_u, - data_v, - stride_v, - w as i32, - h as i32, - ); - - source.capture_frame(&*video_frame); - } - }) - .block_on() - { - error!("Error sending video frame to livekit {e}"); - }; - } - // if scene_controller.single_image { - // app_exit_writer.send(AppExit); - // } - } else { - scene_controller.state.decrement(); - } - } - } -} diff --git a/lkgpt/src/llm.rs b/lkgpt/src/llm.rs deleted file mode 100644 index 16d10fd..0000000 --- a/lkgpt/src/llm.rs +++ /dev/null @@ -1,152 +0,0 @@ -use async_openai::{ - config::OpenAIConfig, - types::{ - ChatCompletionRequestUserMessageArgs, ChatCompletionRequestUserMessageContent, - CreateChatCompletionRequestArgs, - }, - Client, -}; -use bevy::ecs::{ - system::{Res, ResMut, Resource}, - world::{FromWorld, World}, -}; -use futures::StreamExt; - -use crate::OPENAI_ORG_ID; - -#[derive(Resource)] -pub struct LLMChannel { - pub tx: crossbeam_channel::Sender, - pub rx: crossbeam_channel::Receiver, - pub client: Client, - pub splitters: [char; 12], - pub txt_buffer: String, - pub tts_buffer: String, - pub req_args: CreateChatCompletionRequestArgs, - pub text_chat_prefix: &'static str, -} - -impl Default for LLMChannel { - fn default() -> Self { - let open_ai_org_id = std::env::var(OPENAI_ORG_ID).unwrap(); - - let (tx, rx) = crossbeam_channel::unbounded::(); - - let openai_client = async_openai::Client::with_config( - async_openai::config::OpenAIConfig::new().with_org_id(open_ai_org_id), - ); - - let splitters = ['.', ',', '?', '!', ';', ':', '—', '-', ')', ']', '}', ' ']; - - let txt_buffer = String::new(); - let tts_buffer = String::new(); - - let req_args = CreateChatCompletionRequestArgs::default(); - - let text_chat_prefix = "[chat]"; - - Self { - tx, - rx, - client: openai_client, - splitters, - txt_buffer, - tts_buffer, - req_args, - text_chat_prefix, - } - } -} - -impl LLMChannel { - pub fn new() -> Self { - Self::default() - } -} - -/// Stream text chunks to gpt as it's being generated. -/// Note: if chunks don't end with space or punctuation (" ", ".", "?", "!"), -/// the stream will wait for more text. -/// Used during input streaming to chunk text blocks and set last char to space -pub fn run_llm( - mut llm_channel: ResMut, - async_runtime: Res, - mut tts_client: ResMut, -) { - while let Ok(chunk) = llm_channel.rx.try_recv() { - log::info!("\n\n\nchunk gotten from llm channel, {chunk}"); - llm_channel.txt_buffer.push_str(&chunk); - if llm_channel.txt_buffer.starts_with(llm_channel.text_chat_prefix) - || ends_with_splitter(&llm_channel.splitters, &llm_channel.txt_buffer) - { - let (txt_buffer, prefix) = - (llm_channel.txt_buffer.clone(), llm_channel.text_chat_prefix); - let request = llm_channel - .req_args - .model("gpt-4-1106-preview") - .max_tokens(512u16) - .messages([ChatCompletionRequestUserMessageArgs::default() - .content(ChatCompletionRequestUserMessageContent::Text(remove_prefix( - txt_buffer.as_str(), - prefix, - ))) - .build() - .unwrap() - .into()]) - .build() - .unwrap(); - - let rt = async_runtime.rt.clone(); - rt.block_on(async { - let mut gpt_resp_stream = - llm_channel.client.chat().create_stream(request).await.unwrap(); - while let Some(result) = gpt_resp_stream.next().await { - match result { - Ok(response) => { - for chat_choice in response.choices { - if let Some(content) = chat_choice.delta.content { - llm_channel.tts_buffer.push_str(&content); - if ends_with_splitter( - &llm_channel.splitters, - &llm_channel.tts_buffer, - ) { - let msg = { - let txt = llm_channel.tts_buffer.clone(); - txt.trim().to_owned() - }; - log::info!("GPT: {msg}"); - if let Err(e) = tts_client.send(msg) { - log::error!( - "Coudln't send gpt text chunk to tts channel - {e}" - ); - } else { - llm_channel.tts_buffer.clear(); - }; - } - }; - } - }, - Err(err) => { - log::warn!("chunk error: {err:#?}"); - }, - } - } - }); - llm_channel.txt_buffer.clear(); - } - } -} - -// ***** HELPER FUNCTIONS ***** - -fn ends_with_splitter(splitters: &[char], chunk: &str) -> bool { - !chunk.is_empty() && chunk != " " && splitters.iter().any(|&splitter| chunk.ends_with(splitter)) -} - -fn remove_prefix(s: &str, prefix: &str) -> String { - let s = match s.strip_prefix(prefix) { - Some(s) => s, - None => s, - }; - s.to_owned() -} diff --git a/lkgpt/src/main.rs b/lkgpt/src/main.rs deleted file mode 100644 index 2d00626..0000000 --- a/lkgpt/src/main.rs +++ /dev/null @@ -1,428 +0,0 @@ -#![feature(ascii_char, async_closure, slice_pattern)] -mod controls; -mod frame_capture; -mod llm; -mod room_events; -mod server; -mod stt; -mod tts; -mod video; - -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; - -use frame_capture::scene::SceneController; -use image::RgbaImage; -use livekit::{publication::LocalTrackPublication, webrtc::video_frame::VideoBuffer, Room}; -// use actix_web::{middleware, web::Data, App, HttpServer}; -use log::info; - -use livekit::{ - options::{TrackPublishOptions, VideoCodec}, - track::{LocalAudioTrack, LocalTrack, LocalVideoTrack, TrackSource}, - webrtc::{ - audio_source::native::NativeAudioSource, - prelude::{AudioSourceOptions, RtcAudioSource}, - video_source::{native::NativeVideoSource, RtcVideoSource}, - }, - RoomError, -}; - -use bevy::{ - app::ScheduleRunnerPlugin, core::Name, core_pipeline::tonemapping::Tonemapping, log::LogPlugin, - prelude::*, render::renderer::RenderDevice, tasks::AsyncComputeTaskPool, - time::common_conditions::on_timer, -}; -use bevy_panorbit_camera::{PanOrbitCamera, PanOrbitCameraPlugin}; - -use bevy_gaussian_splatting::{GaussianCloud, GaussianSplattingBundle, GaussianSplattingPlugin}; - -use pollster::FutureExt; - -use futures::StreamExt; -use livekit::{ - track::RemoteTrack, - webrtc::{audio_stream::native::NativeAudioStream, video_stream::native::NativeVideoStream}, - DataPacketKind, RoomEvent, -}; -use log::{error, warn}; -use rodio::cpal::Sample as _; -use serde::{Deserialize, Serialize}; -use stt::STT; - -use crate::{ - controls::WorldControlChannel, llm::LLMChannel, room_events::handle_room_events, - server::RoomData, tts::TTS, video::VideoChannel, -}; - -pub const LIVEKIT_API_SECRET: &str = "LIVEKIT_API_SECRET"; -pub const LIVEKIT_API_KEY: &str = "LIVEKIT_API_KEY"; -pub const LIVEKIT_WS_URL: &str = "LIVEKIT_WS_URL"; -pub const OPENAI_ORG_ID: &str = "OPENAI_ORG_ID"; -pub const DEEPGRAM_API_KEY: &str = "DEEPGRAM_API_KEY"; -pub const ELEVENLABS_API_KEY: &str = "ELEVENLABS_API_KEY"; - -#[derive(Resource)] -pub struct AsyncRuntime { - rt: std::sync::Arc, -} - -impl FromWorld for AsyncRuntime { - fn from_world(_world: &mut World) -> Self { - let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().unwrap(); - - Self { rt: std::sync::Arc::new(rt) } - } -} - -#[derive(Clone)] -struct FrameData { - video_frame: std::sync::Arc< - parking_lot::Mutex< - livekit::webrtc::video_frame::VideoFrame, - >, - >, -} - -#[derive(Resource)] -pub struct StreamingFrameData { - pixel_size: u32, - frame_data: FrameData, - video_src: NativeVideoSource, -} - -#[derive(Serialize, Deserialize)] -struct RoomText { - message: String, - timestamp: i64, -} - -#[derive(Debug, Clone, Copy, Default, Eq, PartialEq, Hash, States)] -pub enum AppState { - #[default] - Idle, - Active, -} - -#[derive(Default, Debug, PartialEq)] -pub enum AppStateServerResource { - #[default] - Init, - Idle, - Active, -} - -#[derive(Default, Debug, PartialEq)] -struct ParticipantRoomName(String); - -impl From for AppStateServerResource { - fn from(value: AppState) -> Self { - match value { - AppState::Idle => AppStateServerResource::Idle, - AppState::Active => AppStateServerResource::Active, - } - } -} - -#[derive(Resource)] -pub struct AudioSync { - should_stop: Arc, -} - -#[derive(Resource)] -pub struct AppStateSync { - state: std::sync::Arc>, - dirty: bool, -} - -#[derive(Resource)] -pub struct LivekitRoom { - #[allow(dead_code)] - room: std::sync::Arc, - room_events: tokio::sync::mpsc::UnboundedReceiver, -} - -pub struct TracksPublicationData { - pub video_src: NativeVideoSource, - pub video_pub: LocalTrackPublication, - pub audio_src: NativeAudioSource, - pub audio_pub: LocalTrackPublication, -} - -pub async fn publish_tracks( - room: std::sync::Arc, - bot_name: &str, - video_frame_dimension: (u32, u32), -) -> Result { - let audio_src = NativeAudioSource::new( - AudioSourceOptions::default(), - TTS::SAMPLE_RATE, - TTS::NUM_OF_CHANNELS, - ); - - let audio_track = - LocalAudioTrack::create_audio_track(bot_name, RtcAudioSource::Native(audio_src.clone())); - - let (width, height) = video_frame_dimension; - let video_src = - NativeVideoSource::new(livekit::webrtc::video_source::VideoResolution { width, height }); - let video_track = - LocalVideoTrack::create_video_track(bot_name, RtcVideoSource::Native(video_src.clone())); - - let video_publication = room - .local_participant() - .publish_track( - LocalTrack::Video(video_track), - TrackPublishOptions { - source: TrackSource::Camera, - video_codec: VideoCodec::VP8, - ..Default::default() - }, - ) - .await; - let audio_publication = room - .local_participant() - .publish_track( - LocalTrack::Audio(audio_track), - TrackPublishOptions { source: TrackSource::Microphone, ..Default::default() }, - ) - .await; - - let video_pub = video_publication?; - let audio_pub = audio_publication?; - Ok(TracksPublicationData { video_src, video_pub, audio_src, audio_pub }) -} - -fn setup_gaussian_cloud( - mut commands: Commands, - asset_server: Res, - _gaussian_assets: ResMut>, - mut scene_controller: ResMut, - mut images: ResMut>, - render_device: Res, -) { - // let remote_file = Some("https://huggingface.co/datasets/cs50victor/splats/resolve/main/train/point_cloud/iteration_7000/point_cloud.gcloud"); - // TODO: figure out how to load remote files later - let splat_file = "splats/bonsai/point_cloud/iteration_7000/point_cloud.gcloud"; - log::info!("loading {}", splat_file); - let cloud = asset_server.load(splat_file.to_string()); - - // let cloud = gaussian_assets.add(GaussianCloud::test_model()); - - let render_target = frame_capture::scene::setup_render_target( - &mut commands, - &mut images, - &render_device, - &mut scene_controller, - 15, - String::from("main_scene"), - ); - - let gs = GaussianSplattingBundle { cloud, ..default() }; - commands.spawn((gs, Name::new("gaussian_cloud"))); - - commands.spawn(( - Camera3dBundle { - transform: Transform { - translation: Vec3::new(-0.59989005, -0.88360703, -2.0863006), - rotation: Quat::from_xyzw(-0.97177905, -0.026801618, 0.13693734, -0.1901983), - scale: Vec3::new(1.0, 1.0, 1.0), - }, - tonemapping: Tonemapping::None, - camera: Camera { target: render_target, ..default() }, - ..default() - }, - PanOrbitCamera { - allow_upside_down: true, - orbit_smoothness: 0.0, - pan_smoothness: 0.0, - zoom_smoothness: 0.0, - ..default() - }, - )); -} - -pub fn sync_bevy_and_server_resources( - mut commands: Commands, - async_runtime: Res, - mut server_state_clone: ResMut, - mut set_app_state: ResMut>, - scene_controller: Res, - audio_syncer: Res, -) { - if !server_state_clone.dirty { - let participant_room_name = &(server_state_clone.state.lock().0).clone(); - if !participant_room_name.is_empty() { - let video_frame_dimensions = scene_controller.dimensions(); - let status = async_runtime.rt.block_on(server::setup_and_connect_to_livekit( - participant_room_name.clone(), - video_frame_dimensions, - )); - match status { - Ok(room_data) => { - info!("🎉connected to livekit room"); - - let RoomData { - livekit_room, - stream_frame_data, - audio_src, - bot_name: _, - video_pub: _, - audio_pub: _, - } = room_data; - - info!("initializing required bevy resources"); - - let llm_channel = LLMChannel::new(); - let llm_tx = llm_channel.tx.clone(); - let llm_channel_tx = llm_tx.clone(); - - let tts = async_runtime.rt.block_on(TTS::new(audio_src)).unwrap(); - let stt = async_runtime.rt.block_on(STT::new(llm_tx)).unwrap(); - - let video_channel = VideoChannel::new(); - commands.insert_resource(llm_channel); - commands.init_resource::(); - - commands.insert_resource(stt.clone()); - - commands.init_resource::(); - commands.insert_resource(tts); - commands.insert_resource(stream_frame_data); - // commands.insert_resource(livekit_room); - - set_app_state.set(AppState::Active); - - let audio_syncer = audio_syncer.should_stop.clone(); - let rt = async_runtime.rt.clone(); - async_runtime.rt.spawn(handle_room_events( - rt, - llm_channel_tx, - stt, - video_channel, - audio_syncer, - livekit_room, - 4, - )); - /* - async_runtime: Res, - llm_channel: Res, - stt_client: ResMut, - _video_channel: Res, - audio_syncer: ResMut, - mut room_events: ResMut, - single_frame_data: ResMut, - */ - server_state_clone.dirty = true; - }, - Err(e) => { - info!("couldn't connect to livekit room {e:#?}"); - }, - } - }; - } -} - -pub struct AppConfig { - pub width: u32, - pub height: u32, -} - -fn main() { - dotenvy::from_filename_override(".env.local").ok(); - - // ************** REQUIRED ENV VARS ************** - std::env::var(LIVEKIT_API_SECRET).expect("LIVEKIT_API_SECRET must be set"); - std::env::var(LIVEKIT_API_KEY).expect("LIVEKIT_API_KEY must be set"); - std::env::var(LIVEKIT_WS_URL).expect("LIVEKIT_WS_URL is not set"); - std::env::var(OPENAI_ORG_ID).expect("OPENAI_ORG_ID must be set"); - std::env::var(DEEPGRAM_API_KEY).expect("DEEPGRAM_API_KEY must be set"); - std::env::var(ELEVENLABS_API_KEY).expect("ELEVENLABS_API_KEY must be set"); - - let mut formatted_builder = pretty_env_logger::formatted_builder(); - - let pretty_env_builder = formatted_builder - .filter_module("lkgpt", log::LevelFilter::Info) - .filter_module("actix_server", log::LevelFilter::Info) - .filter_module("bevy", log::LevelFilter::Info) - .filter_module("actix_web", log::LevelFilter::Info); - - if cfg!(target_os = "unix") { - pretty_env_builder.filter_module("livekit", log::LevelFilter::Info); - } - - pretty_env_builder.init(); - - let mut app = App::new(); - - let config = AppConfig { width: 1920, height: 1080 }; - - app.insert_resource(frame_capture::scene::SceneController::new(config.width, config.height)); - app.insert_resource(ClearColor(Color::rgb_u8(0, 0, 0))); - - app.add_plugins(( - bevy_web_asset::WebAssetPlugin, - DefaultPlugins - .set(ImagePlugin::default_nearest()) - // "headless" window - .set(WindowPlugin { - primary_window: None, - exit_condition: bevy::window::ExitCondition::DontExit, - close_when_requested: false, - }).disable::(), - frame_capture::image_copy::ImageCopyPlugin, - frame_capture::scene::CaptureFramePlugin, - ScheduleRunnerPlugin::run_loop(std::time::Duration::from_secs_f64(1.0 / 60.0)), - PanOrbitCameraPlugin, - // plugin for gaussian splatting - GaussianSplattingPlugin, - )); - - app.add_state::(); - app.init_resource::(); - app.insert_resource(AudioSync { should_stop: Arc::new(AtomicBool::new(false)) }); - app.init_resource::(); - - app.init_resource::(); - app.add_event::(); - - app.add_systems(Update, move_camera); - - app.add_systems(Update, server::shutdown_bevy_remotely); - - // app.add_systems( - // Update, - // room_events::handle_room_events - // .run_if(resource_exists::()) - // .run_if(resource_exists::()) - // .run_if(resource_exists::()) - // .run_if(resource_exists::()), - // ); - - app.add_systems( - Update, - llm::run_llm - .run_if(resource_exists::()) - .run_if(resource_exists::()) - .run_if(in_state(AppState::Active)), - ); - - app.add_systems( - Update, - sync_bevy_and_server_resources.run_if(on_timer(std::time::Duration::from_secs(2))), - ); - - app.add_systems(OnEnter(AppState::Active), setup_gaussian_cloud); - - app.run(); -} - -fn move_camera(mut camera: Query<&mut Transform, With>) { - for mut transform in camera.iter_mut() { - transform.translation.x += 0.0005; - transform.translation.y += 0.0005; - transform.translation.z += 0.0005; - } -} diff --git a/lkgpt/src/room_events.rs b/lkgpt/src/room_events.rs deleted file mode 100644 index 26bce41..0000000 --- a/lkgpt/src/room_events.rs +++ /dev/null @@ -1,206 +0,0 @@ -use std::sync::{ - atomic::{AtomicBool, Ordering}, - Arc, -}; - -use bevy::ecs::system::{Res, ResMut}; -use futures::{future, FutureExt, StreamExt}; -use image::RgbaImage; -use livekit::{ - track::RemoteTrack, - webrtc::{ - audio_stream::native::NativeAudioStream, video_frame::VideoBuffer, - video_stream::native::NativeVideoStream, - }, - DataPacketKind, RoomEvent, -}; -use log::{error, info, warn}; -use rodio::cpal::Sample; -use tokio::runtime::Runtime; - -use crate::{llm, stt::STT, video, AsyncRuntime, AudioSync, LivekitRoom, RoomText}; - -async fn handle_video(mut video_stream: NativeVideoStream, pixel_size: u32) { - // every 10 video frames - let mut i = 0; - info!("📸 handling video"); - while let Some(frame) = video_stream.next().await { - log::error!("🤡received video frame | {:#?}", frame); - // VIDEO FRAME BUFFER (i420_buffer) - let video_frame_buffer = frame.buffer.to_i420(); - let width = video_frame_buffer.width(); - let height = video_frame_buffer.height(); - let rgba_stride = video_frame_buffer.width() * pixel_size; - - let (stride_y, stride_u, stride_v) = video_frame_buffer.strides(); - let (data_y, data_u, data_v) = video_frame_buffer.data(); - - let rgba_buffer = RgbaImage::new(width, height); - let rgba_raw = unsafe { - std::slice::from_raw_parts_mut( - rgba_buffer.as_raw().as_ptr() as *mut u8, - rgba_buffer.len(), - ) - }; - - livekit::webrtc::native::yuv_helper::i420_to_rgba( - data_y, - stride_y, - data_u, - stride_u, - data_v, - stride_v, - rgba_raw, - rgba_stride, - video_frame_buffer.width() as i32, - video_frame_buffer.height() as i32, - ); - - if let Err(e) = rgba_buffer.save(format!("camera/{i}.png")) { - log::error!("Couldn't save video frame {e}"); - }; - i += 1; - } - info!("🤡ended video thread"); -} - -pub async fn handle_room_events( - async_runtime: Arc, - llm_channel_tx: crossbeam_channel::Sender, - stt_client: STT, - _video_channel: video::VideoChannel, - should_stop: Arc, - mut room_events: LivekitRoom, - pixel_size: u32, -) { - while let Some(event) = room_events.room_events.recv().await { - println!("\n\n🤡received room event {:?}", event); - match event { - RoomEvent::TrackSubscribed { track, publication: _, participant: _user } => { - match track { - RemoteTrack::Audio(audio_track) => { - let audio_rtc_track = audio_track.rtc_track(); - let mut audio_stream = NativeAudioStream::new(audio_rtc_track); - let audio_should_stop = should_stop.clone(); - let stt_client = stt_client.clone(); - let rt = async_runtime.clone(); - - std::thread::spawn(move || { - while let Some(frame) = rt.block_on(audio_stream.next()) { - if audio_should_stop.load(Ordering::Relaxed) { - continue; - } - - let audio_buffer = frame - .data - .iter() - .map(|sample| sample.to_sample::()) - .collect::>(); - - if audio_buffer.is_empty() { - warn!("empty audio frame | {:#?}", audio_buffer); - continue; - } - - if let Err(e) = stt_client.send(audio_buffer) { - error!("Couldn't send audio frame to stt {e}"); - }; - } - error!("audio thread ended"); - }); - }, - RemoteTrack::Video(video_track) => { - let video_rtc_track = video_track.rtc_track(); - let mut video_stream = NativeVideoStream::new(video_rtc_track); - let rt = async_runtime.clone(); - - std::thread::spawn(move || { - // every 10 video frames - let mut i = 0; - info!("📸 handling video"); - loop { - while let Some(Some(frame)) = video_stream.next().now_or_never() { - log::error!("🤡received video frame | {:#?}", frame); - // VIDEO FRAME BUFFER (i420_buffer) - let video_frame_buffer = frame.buffer.to_i420(); - let width = video_frame_buffer.width(); - let height = video_frame_buffer.height(); - let rgba_stride = video_frame_buffer.width() * pixel_size; - - let (stride_y, stride_u, stride_v) = - video_frame_buffer.strides(); - let (data_y, data_u, data_v) = video_frame_buffer.data(); - - let rgba_buffer = RgbaImage::new(width, height); - let rgba_raw = unsafe { - std::slice::from_raw_parts_mut( - rgba_buffer.as_raw().as_ptr() as *mut u8, - rgba_buffer.len(), - ) - }; - - livekit::webrtc::native::yuv_helper::i420_to_rgba( - data_y, - stride_y, - data_u, - stride_u, - data_v, - stride_v, - rgba_raw, - rgba_stride, - video_frame_buffer.width() as i32, - video_frame_buffer.height() as i32, - ); - - if let Err(e) = rgba_buffer.save(format!("camera/{i}.png")) { - log::error!("Couldn't save video frame {e}"); - }; - i += 1; - } - } - info!("🤡ended video thread"); - }); - }, - }; - }, - RoomEvent::DataReceived { payload, kind, topic: _, participant: _ } => { - if kind == DataPacketKind::Reliable { - if let Some(payload) = payload.as_ascii() { - let room_text: serde_json::Result = - serde_json::from_str(payload.as_str()); - match room_text { - Ok(room_text) => { - if let Err(e) = - llm_channel_tx.send(format!("[chat]{} ", room_text.message)) - { - error!("Couldn't send the text to gpt {e}") - }; - }, - Err(e) => { - warn!("Couldn't deserialize room text. {e:#?}"); - }, - } - - info!("text from room {:#?}", payload.as_str()); - } - } - }, - // ignoring the participant for now, currently assuming there is only one participant - RoomEvent::TrackMuted { participant: _, publication: _ } => { - should_stop.store(true, Ordering::Relaxed); - }, - RoomEvent::TrackUnmuted { participant: _, publication: _ } => { - should_stop.store(false, Ordering::Relaxed); - }, - // RoomEvent::ActiveSpeakersChanged { speakers } => { - // if speakers.is_empty() { - // should_stop.store(true, Ordering::Relaxed); - // } - // let is_main_participant_muted = speakers.iter().any(|speaker| speaker.name() != "kitt"); - // should_stop.store(is_main_participant_muted, Ordering::Relaxed); - // } - RoomEvent::ConnectionQualityChanged { quality: _, participant: _ } => {}, - _ => info!("received room event {:?}", event), - } - } -} diff --git a/lkgpt/src/server.rs b/lkgpt/src/server.rs deleted file mode 100644 index 726dc4c..0000000 --- a/lkgpt/src/server.rs +++ /dev/null @@ -1,326 +0,0 @@ -use livekit::{ - publication::LocalTrackPublication, - webrtc::{ - audio_source::native::NativeAudioSource, - video_frame::{I420Buffer, VideoFrame, VideoRotation}, - }, -}; -use log::info; - -use actix_web::web; -use parking_lot::Mutex; - -use std::{fmt::Debug, sync::Arc}; - -use bevy::prelude::*; -use livekit_api::access_token::{AccessToken, VideoGrants}; -use serde::{Deserialize, Serialize}; - -use crate::{LivekitRoom, LIVEKIT_API_KEY, LIVEKIT_API_SECRET, LIVEKIT_WS_URL}; - -#[derive(Debug, Serialize, Deserialize)] -pub struct ServerMsg { - data: Option, - error: Option, -} - -impl ServerMsg { - pub fn data(data: T) -> Self { - Self { data: Some(data), error: None } - } - - pub fn error(error: T) -> Self { - let err_msg = error.to_string(); - log::warn!("Server error. {err_msg:?}"); - Self { data: None, error: Some(err_msg) } - } -} - -#[derive(Clone, Resource)] -pub struct ShutdownBevyRemotely { - tx: crossbeam_channel::Sender, - rx: crossbeam_channel::Receiver, -} - -impl FromWorld for ShutdownBevyRemotely { - fn from_world(_world: &mut World) -> Self { - let (tx, rx) = crossbeam_channel::unbounded::(); - Self { tx, rx } - } -} - -pub fn shutdown_bevy_remotely( - mut app_exit_writer: EventWriter, - shutdown: ResMut, -) { - if let Ok(true) = shutdown.rx.try_recv() { - log::info!("received bevy shutdown signal"); - app_exit_writer.send(bevy::app::AppExit); - } -} - -pub fn create_bot_token(room_name: String, ai_name: &str) -> anyhow::Result { - let api_key = std::env::var(LIVEKIT_API_KEY).unwrap(); - let api_secret = std::env::var(LIVEKIT_API_SECRET).unwrap(); - - let ttl = std::time::Duration::from_secs(60 * 5); // 10 minutes (in sync with frontend) - Ok(AccessToken::with_api_key(api_key.as_str(), api_secret.as_str()) - .with_ttl(ttl) - .with_identity(ai_name) - .with_name(ai_name) - .with_grants(VideoGrants { - room: room_name, - room_list: true, - room_join: true, - room_admin: true, - can_publish: true, - room_record: true, - can_subscribe: true, - can_publish_data: true, - can_update_own_metadata: true, - ..Default::default() - }) - .to_jwt()?) -} - -pub struct RoomData { - pub livekit_room: LivekitRoom, - pub video_pub: LocalTrackPublication, - pub stream_frame_data: crate::StreamingFrameData, - pub audio_src: NativeAudioSource, - pub audio_pub: LocalTrackPublication, - pub bot_name: String, -} - -pub async fn setup_and_connect_to_livekit( - participant_room_name: String, - video_frame_dimension: (u32, u32), -) -> anyhow::Result { - let lvkt_url = std::env::var(LIVEKIT_WS_URL).unwrap(); - - let bot_name = "kitt"; - - // connect to webrtc room - let lvkt_token = create_bot_token(participant_room_name, bot_name)?; - - let room_options = livekit::RoomOptions { ..Default::default() }; - - let (room, room_events) = livekit::Room::connect(&lvkt_url, &lvkt_token, room_options).await?; - let room = std::sync::Arc::new(room); - - info!("Established connection with livekit room. ID -> [{}]", room.name()); - - // ************** SETUP OPENAI, TTS, & STT ************** - let crate::TracksPublicationData { video_pub, video_src, audio_src, audio_pub } = - crate::publish_tracks(room.clone(), bot_name, video_frame_dimension).await?; - - let pixel_size = 4_u32; - - let (w, h) = (video_frame_dimension.0 as usize, video_frame_dimension.1 as usize); - - let frame_data = crate::FrameData { - video_frame: Arc::new(Mutex::new(VideoFrame { - rotation: VideoRotation::VideoRotation0, - buffer: I420Buffer::new(w as u32, h as u32), - timestamp_us: 0, - })), - }; - - let stream_frame_data = crate::StreamingFrameData { pixel_size, video_src, frame_data }; - - let livekit_room = LivekitRoom { room, room_events }; - - Ok(RoomData { - livekit_room, - stream_frame_data, - video_pub, - audio_src, - audio_pub, - bot_name: bot_name.to_string(), - }) -} - -mod health_check { - pub async fn handler() -> impl actix_web::Responder { - actix_web::HttpResponse::Ok().json(super::ServerMsg::data("OK")) - } -} - -pub type ServerStateMutex = parking_lot::Mutex; - -mod lsdk_webhook { - use actix_web::{http::Method, web, HttpRequest, HttpResponse as Resp, Responder}; - - use super::ServerMsg; - - use livekit_api::{ - access_token::{self}, - webhooks, - }; - use log::info; - - pub async fn handler( - req: HttpRequest, - server_data: web::Data, - body: web::Bytes, - ) -> impl Responder { - if req.method().ne(&Method::POST) { - return Resp::MethodNotAllowed() - .json(ServerMsg::error("Method not allowed".to_string())); - } - - log::info!("SERVER RECEIVED WEBHOOK"); - - let token_verifier = match access_token::TokenVerifier::new() { - Ok(i) => i, - Err(e) => return Resp::InternalServerError().json(ServerMsg::error(e.to_string())), - }; - let webhook_receiver = webhooks::WebhookReceiver::new(token_verifier); - - let jwt = req - .headers() - .get("Authorization") - .and_then(|hv| hv.to_str().ok()) - .unwrap_or_default() - .to_string(); - - let jwt = jwt.trim(); - - let body = match std::str::from_utf8(&body) { - Ok(i) => i, - Err(e) => return Resp::BadRequest().json(ServerMsg::error(e.to_string())), - }; - - let event = match webhook_receiver.receive(body, jwt) { - Ok(i) => i, - Err(e) => return Resp::InternalServerError().json(ServerMsg::error(e.to_string())), - }; - - // room_finished - if event.room.is_some() { - let livekit_protocol::Room { - name: participant_room_name, - max_participants, - num_participants, - .. - } = event.room.unwrap(); - let event = event.event; - if event == "room_started" { - if num_participants < max_participants { - info!("...connecting to room"); - - let server_data = server_data.lock(); - - log::info!("app state {:#?}", *server_data.app_state); - - *server_data.app_state.lock() = - crate::ParticipantRoomName(participant_room_name); - - log::info!("app state {:?}", *server_data.app_state); - - info!("\nSERVER FINISHED PROCESSING ROOM_STARTED WEBHOOK"); - }; - } else if event == "room_finished" { - let server_data = server_data.lock(); - - log::info!("app state {:#?}", *server_data.app_state); - - *server_data.app_state.lock() = - crate::ParticipantRoomName(format!("reset:{participant_room_name}")); - - log::info!("app state {:?}", *server_data.app_state); - - info!("\nSERVER FINISHED PROCESSING ROOM_FINISHED WEBHOOK"); - } - } else { - info!("received event {}", event.event); - } - - Resp::Ok().json(ServerMsg::data("Livekit Webhook Successfully Processed")) - } -} - -fn top_level_routes(cfg: &mut web::ServiceConfig) { - cfg.service(web::scope("/").service(web::resource("").to(health_check::handler))) - .service(web::resource("/webhooks/livekit").to(lsdk_webhook::handler)); -} - -pub struct ServerResources { - pub app_state: std::sync::Arc>, -} - -pub async fn http_server( - tx: crossbeam_channel::Sender, - app_state: std::sync::Arc>, -) -> std::io::Result<()> { - // let _ = setAppState; - let port = std::env::var("PORT") - .unwrap_or_else(|_| "6669".to_string()) - .parse::() - .expect("PORT couldn't be set"); - - info!("starting HTTP server on port {port}"); - - let server_resources = - actix_web::web::Data::new(parking_lot::Mutex::new(ServerResources { app_state })); - - let server = actix_web::HttpServer::new(move || { - actix_web::App::new() - .wrap(actix_web::middleware::Compress::default()) - .wrap(actix_web::middleware::Logger::new("IP - %a | Time - %D ms")) - .wrap( - actix_web::middleware::DefaultHeaders::new() - .add(("Content-Type", "application/json")), - ) - .app_data(server_resources.clone()) - .configure(top_level_routes) - }) - .bind(("0.0.0.0", port))? - .workers(1) - .run(); - - // server - let _ = tx.send(server.handle()); - - server.await -} - -#[derive(Resource)] -pub struct ActixServer { - server_handle: actix_web::dev::ServerHandle, -} - -impl bevy::ecs::world::FromWorld for ActixServer { - fn from_world(world: &mut World) -> Self { - world.init_resource::(); - - let app_state = - std::sync::Arc::new(parking_lot::Mutex::new(crate::ParticipantRoomName::default())); - - world.insert_resource(crate::AppStateSync { state: app_state.clone(), dirty: false }); - - let async_runtime = world.get_resource::().unwrap(); - - let (tx, rx) = crossbeam_channel::unbounded::(); - - let shutdown_bev = world.get_resource::().unwrap(); - let shutdown_bev_tx = shutdown_bev.tx.clone(); - - log::info!("spawning thread for server"); - - let rt = async_runtime.rt.clone(); - - std::thread::spawn(move || { - let svr = http_server(tx, app_state); - if let Err(e) = rt.block_on(svr) { - log::info!("Server errored out | Reason {e:#?}"); - }; - log::warn!("Server exited | Shutting down Bevy"); - shutdown_bev_tx.send(true).unwrap(); - }); - - let server_handle = rx.recv().unwrap(); - - Self { server_handle } - } -} diff --git a/lkgpt/src/stt.rs b/lkgpt/src/stt.rs deleted file mode 100644 index f5e0a2f..0000000 --- a/lkgpt/src/stt.rs +++ /dev/null @@ -1,118 +0,0 @@ -use async_trait::async_trait; -use bevy::ecs::system::Resource; -use bytes::{BufMut, Bytes, BytesMut}; -use deepgram::Deepgram; -use ezsockets::{ - client::ClientCloseMode, Client, ClientConfig, CloseFrame, MessageSignal, MessageStatus, - RawMessage, SocketConfig, WSError, -}; -use futures::StreamExt; -use livekit::webrtc::audio_stream::native::NativeAudioStream; -use log::{error, info}; -use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; -use serde_json::{json, Map, Value}; -use std::{ - sync::Arc, - time::{Duration, Instant}, -}; -use tokio::sync::mpsc::UnboundedSender; - -use crate::{AsyncRuntime, DEEPGRAM_API_KEY}; - -#[derive(Clone, Resource)] -pub struct STT { - ws_client: Arc>, -} - -struct WSClient { - llm_channel_tx: crossbeam_channel::Sender, -} - -#[async_trait] -impl ezsockets::ClientExt for WSClient { - type Call = (); - - async fn on_text(&mut self, text: String) -> Result<(), ezsockets::Error> { - let data: Value = serde_json::from_str(&text)?; - let transcript = data["channel"]["alternatives"][0]["transcript"].clone(); - - if transcript != Value::Null { - info!("🎉 from deepgram {transcript}"); - if let Err(e) = self.llm_channel_tx.send(transcript.to_string()) { - error!("Error sending to LLM: {}", e); - }; - } - - Ok(()) - } - - async fn on_binary(&mut self, bytes: Vec) -> Result<(), ezsockets::Error> { - info!("received bytes from deepgram: {bytes:?}"); - Ok(()) - } - - async fn on_call(&mut self, call: Self::Call) -> Result<(), ezsockets::Error> { - info!("Deepgram ON CALL: {call:?}"); - let () = call; - Ok(()) - } - - async fn on_connect(&mut self) -> Result<(), ezsockets::Error> { - info!("Deepgram CONNECTED 🎉"); - Ok(()) - } - - async fn on_connect_fail(&mut self, e: WSError) -> Result { - error!("Deepgram CONNECTION FAILED | {e}"); - Ok(ClientCloseMode::Reconnect) - } - - async fn on_close( - &mut self, - frame: Option, - ) -> Result { - error!("Deepgram CONNECTION CLOSED | {frame:?}"); - Ok(ClientCloseMode::Reconnect) - } - - async fn on_disconnect(&mut self) -> Result { - error!("Deepgram disconnected"); - Ok(ClientCloseMode::Reconnect) - } -} - -impl STT { - pub async fn new(llm_channel_tx: crossbeam_channel::Sender) -> anyhow::Result { - let deepgram_api_key = std::env::var(DEEPGRAM_API_KEY).unwrap(); - - let config = ClientConfig::new("wss://api.deepgram.com/v1/listen") - .socket_config(SocketConfig { - heartbeat: Duration::from_secs(11), - timeout: Duration::from_secs(30 * 60), // 30 minutes - heartbeat_ping_msg_fn: Arc::new(|_t: Duration| { - RawMessage::Text( - json!({ - "type": "KeepAlive", - }) - .to_string(), - ) - }), - }) - .header("Authorization", &format!("Token {}", deepgram_api_key)) - .query_parameter("model", "nova-2-conversationalai") - .query_parameter("smart_format", "true") - .query_parameter("version", "latest") - .query_parameter("filler_words", "true"); - - let (ws_client, _) = - ezsockets::connect(|_client| WSClient { llm_channel_tx }, config).await; - - Ok(Self { ws_client: Arc::new(ws_client) }) - } - - pub fn send(&self, bytes: impl Into>) -> anyhow::Result { - let signal = self.ws_client.binary(bytes)?; - Ok(signal.status()) - } -} diff --git a/lkgpt/src/tts.rs b/lkgpt/src/tts.rs deleted file mode 100644 index 2be67ec..0000000 --- a/lkgpt/src/tts.rs +++ /dev/null @@ -1,228 +0,0 @@ -use async_trait::async_trait; -use base64::{ - engine::general_purpose::{self}, - Engine, -}; -use bevy::ecs::system::Resource; - -use ezsockets::{ - client::ClientCloseMode, Client, ClientConfig, CloseFrame, MessageStatus, RawMessage, - SocketConfig, WSError, -}; -use futures::StreamExt; -use livekit::webrtc::{audio_frame::AudioFrame, audio_source::native::NativeAudioSource}; -use log::{error, info}; -use serde::Serialize; -use serde_json::Value; -use std::{ - sync::{ - atomic::{AtomicBool, Ordering}, - Arc, - }, - time::Duration, -}; - -use std::io::Cursor; - -use crate::ELEVENLABS_API_KEY; - -#[derive(Serialize)] -struct VoiceSettings { - stability: f32, - similarity_boost: bool, -} - -#[derive(Serialize)] -struct GenerationConfig { - chunk_length_schedule: [u8; 1], -} - -#[derive(Serialize)] -struct BOSMessage<'a> { - text: &'a str, - try_trigger_generation: bool, - voice_settings: VoiceSettings, - generation_config: GenerationConfig, -} - -#[derive(Serialize)] -struct EOSMessage<'a> { - text: &'a str, -} - -#[derive(Serialize)] -struct RegularMessage { - text: String, - try_trigger_generation: bool, -} - -#[allow(clippy::upper_case_acronyms)] -#[derive(Clone, Resource)] -pub struct TTS { - ws_client: Client, - pub started: Arc, -} - -impl TTS { - pub const NUM_OF_CHANNELS: u32 = 1; - pub const SAMPLE_RATE: u32 = 44100; -} - -struct WSClient { - audio_src: NativeAudioSource, - tts_ws_started: Arc, -} - -fn decode_base64_audio(base64_audio: &str) -> anyhow::Result> { - let data = general_purpose::STANDARD.decode(base64_audio)?; - let decoder = rodio::Decoder::new(Cursor::new(data))?; - - Ok(decoder.into_iter().collect::>()) -} - -#[async_trait] -impl ezsockets::ClientExt for WSClient { - type Call = (); - - async fn on_text(&mut self, text: String) -> Result<(), ezsockets::Error> { - // info!("raw message from eleven labs {text:?}"); - let data: Value = serde_json::from_str(&text)?; - let base64_audio = data["audio"].clone(); - - info!("incoming speech from eleven labs"); - if base64_audio != Value::Null { - let data = std::borrow::Cow::from(decode_base64_audio(base64_audio.as_str().unwrap())?); - - let num_channels = self.audio_src.num_channels(); - let sample_rate = self.audio_src.sample_rate(); - let samples_per_channel = 1_u32; - - let audio_frame = AudioFrame { data, num_channels, sample_rate, samples_per_channel }; - - self.audio_src.capture_frame(&audio_frame).await?; - } else { - error!("received null audio from eleven labs: {text:?}"); - } - - Ok(()) - } - - async fn on_binary(&mut self, bytes: Vec) -> Result<(), ezsockets::Error> { - info!("received bytes: {bytes:?}"); - Ok(()) - } - - async fn on_call(&mut self, call: Self::Call) -> Result<(), ezsockets::Error> { - info!("ELEVEN LABS WTF"); - let () = call; - Ok(()) - } - - async fn on_connect(&mut self) -> Result<(), ezsockets::Error> { - self.tts_ws_started.store(true, Ordering::Relaxed); - info!("ELEVEN LABS CONNECTED 🎉"); - Ok(()) - } - - async fn on_connect_fail( - &mut self, - _error: WSError, - ) -> Result { - error!("ELEVEN LABS connection FAIL"); - Ok(ClientCloseMode::Reconnect) - } - - async fn on_close( - &mut self, - _frame: Option, - ) -> Result { - error!("ELEVEN LABS connection CLOSE"); - self.tts_ws_started.store(false, Ordering::Relaxed); - Ok(ClientCloseMode::Reconnect) - } - - async fn on_disconnect(&mut self) -> Result { - error!("ELEVEN LABS disconnected"); - Ok(ClientCloseMode::Reconnect) - } -} - -impl TTS { - pub async fn new(audio_src: NativeAudioSource) -> anyhow::Result { - let eleven_labs_api_key = std::env::var(ELEVENLABS_API_KEY).unwrap(); - let started = Arc::new(AtomicBool::new(true)); - - let voice_id = "21m00Tcm4TlvDq8ikWAM"; - let model = "eleven_turbo_v2"; - - let url = url::Url::parse_with_params( - &format!( - "wss://api.elevenlabs.io/v1/text-to-speech/{voice_id}/stream-input?model_id={model}" - ), - &[("optimize_streaming_latency", "3")], - ) - .unwrap(); - - let config = ClientConfig::new(url) - .socket_config(SocketConfig { - heartbeat: Duration::from_secs(10), - timeout: Duration::from_secs(30 * 60), // 30 minutes - heartbeat_ping_msg_fn: Arc::new(|_t: Duration| { - RawMessage::Text( - serde_json::to_string(&RegularMessage { - text: " ".to_string(), - try_trigger_generation: false, - }) - .unwrap(), - ) - }), - }) - .header("xi-api-key", eleven_labs_api_key); - - let (ws_client, _) = ezsockets::connect( - |_client| WSClient { audio_src, tts_ws_started: started.clone() }, - config, - ) - .await; - - ws_client.text(serde_json::to_string(&BOSMessage { - text: " ", - try_trigger_generation: true, - voice_settings: VoiceSettings { stability: 0.8, similarity_boost: true }, - generation_config: GenerationConfig { chunk_length_schedule: [50] }, - })?)?; - - Ok(Self { ws_client, started }) - } - - pub fn restart(&mut self) -> anyhow::Result<()> { - self.started.store(true, Ordering::Relaxed); - self.send(" ".to_string())?; - Ok(()) - } - - pub fn send(&mut self, msg: String) -> anyhow::Result { - let msg = match msg.as_str() { - "" => serde_json::to_string(&EOSMessage { text: "" }), - " " => serde_json::to_string(&BOSMessage { - text: " ", - try_trigger_generation: true, - voice_settings: VoiceSettings { stability: 0.8, similarity_boost: true }, - generation_config: GenerationConfig { chunk_length_schedule: [50] }, - }), - msg => serde_json::to_string(&RegularMessage { - text: format!("{msg} "), - try_trigger_generation: true, - }), - }; - let msg = msg?; - - if !self.started.load(Ordering::Relaxed) { - self.restart()?; - } - - info!("sending to eleven labs {msg}"); - - Ok(self.ws_client.text(msg)?.status()) - } -} diff --git a/lkgpt/src/video.rs b/lkgpt/src/video.rs deleted file mode 100644 index 3b70c88..0000000 --- a/lkgpt/src/video.rs +++ /dev/null @@ -1,42 +0,0 @@ -use bevy::ecs::{ - system::Resource, - world::{FromWorld, World}, -}; -use futures::StreamExt; -use livekit::webrtc::video_stream::native::NativeVideoStream; - -pub struct ReceivedVideoFrame { - pub image_buffer: Vec, - pub timestamp: i64, // When the frame was captured in microseconds -} - -#[derive(Resource)] -pub struct VideoChannel { - pub tx: crossbeam_channel::Sender>, - rx: crossbeam_channel::Receiver>, -} - -impl Default for VideoChannel { - fn default() -> Self { - let (tx, rx) = crossbeam_channel::unbounded::>(); - Self { tx, rx } - } -} -impl VideoChannel { - pub fn new() -> Self { - Self::default() - } -} - -async fn video_stream_handler(mut video: NativeVideoStream) { - let mut counter = 0_u8; - let max_fps = 10; - - while let Some(frame) = video.next().await { - if counter % max_fps == 0 { - log::info!("video frame info - {frame:#?}"); - } - - counter = (counter + 1) % max_fps; - } -} diff --git a/llm.py b/llm.py new file mode 100644 index 0000000..4cddd9c --- /dev/null +++ b/llm.py @@ -0,0 +1,144 @@ +# Copyright 2023 LiveKit, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import logging +import asyncio +import openai +from dataclasses import dataclass +from typing import AsyncIterable, List, Optional +from enum import Enum + +ChatGPTMessageRole = Enum("MessageRole", ["system", "user", "assistant", "function"]) + + +@dataclass +class ChatGPTMessage: + role: ChatGPTMessageRole + content: str + + def to_api(self): + return {"role": self.role.name, "content": self.content} + + +class ChatGPTPlugin: + """OpenAI ChatGPT Plugin""" + + def __init__(self, prompt: str, message_capacity: int, model: str): + """ + Args: + prompt (str): First 'system' message sent to the chat that prompts the assistant + message_capacity (int): Maximum number of messages to send to the chat + model (str): Which model to use (i.e. 'gpt-3.5-turbo') + """ + self._model = model + self._client = openai.AsyncOpenAI(api_key=os.environ["OPENAI_API_KEY"]) + self._prompt = prompt + self._message_capacity = message_capacity + self._messages: List[ChatGPTMessage] = [] + self._producing_response = False + self._needs_interrupt = False + + def interrupt(self): + """Interrupt a currently streaming response (if there is one)""" + if self._producing_response: + self._needs_interrupt = True + + async def aclose(self): + pass + + async def send_system_prompt(self) -> AsyncIterable[str]: + """Send the system prompt to the chat and generate a streamed response + + Returns: + AsyncIterable[str]: Streamed ChatGPT response + """ + async for text in self.add_message(None): + yield text + + async def add_message( + self, message: Optional[ChatGPTMessage] + ) -> AsyncIterable[str]: + """Add a message to the chat and generate a streamed response + + Args: + message (ChatGPTMessage): The message to add + + Returns: + AsyncIterable[str]: Streamed ChatGPT response + """ + + if message is not None: + self._messages.append(message) + if len(self._messages) > self._message_capacity: + self._messages.pop(0) + + async for text in self._generate_text_streamed(self._model): + yield text + + async def _generate_text_streamed(self, model: str) -> AsyncIterable[str]: + prompt_message = ChatGPTMessage( + role=ChatGPTMessageRole.system, content=self._prompt + ) + try: + chat_messages = [m.to_api() for m in self._messages] + chat_stream = await asyncio.wait_for( + self._client.chat.completions.create( + model=model, + n=1, + stream=True, + messages=[prompt_message.to_api()] + chat_messages, + ), + 10, + ) + except TimeoutError: + yield "Sorry, I'm taking too long to respond. Please try again later." + return + + self._producing_response = True + complete_response = "" + + async def anext_util(aiter): + async for item in aiter: + return item + + return None + + while True: + try: + chunk = await asyncio.wait_for(anext_util(chat_stream), 5) + except TimeoutError: + break + except asyncio.CancelledError: + self._producing_response = False + self._needs_interrupt = False + break + + if chunk is None: + break + content = chunk.choices[0].delta.content + + if self._needs_interrupt: + self._needs_interrupt = False + logging.info("ChatGPT interrupted") + break + + if content is not None: + complete_response += content + yield content + + self._messages.append( + ChatGPTMessage(role=ChatGPTMessageRole.assistant, content=complete_response) + ) + self._producing_response = False \ No newline at end of file diff --git a/meet/app/global.css b/meet/app/global.css deleted file mode 100644 index b5c61c9..0000000 --- a/meet/app/global.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/meet/app/r/[name]/page.tsx b/meet/app/r/[name]/page.tsx deleted file mode 100644 index 7a45f9e..0000000 --- a/meet/app/r/[name]/page.tsx +++ /dev/null @@ -1,83 +0,0 @@ -'use client'; -import '@livekit/components-styles'; -import '@livekit/components-styles/prefabs'; - -import { decodePassphrase, encodePassphrase, randomString } from '~/utils/lksdk'; -import { LocalUserChoices } from '@livekit/components-react'; -import { ActiveRoom } from '~/components/ActiveRoom'; -import dynamic from 'next/dynamic'; -import { useState } from 'react'; - -// Required to access localStorage -const PreJoinNoSSR = dynamic( - async () => { - return (await import('@livekit/components-react')).PreJoin; - }, - { ssr: false }, -); - -export default function LivekitRoom({ params }: { params: { name: string } }) { - const roomName = params.name; - - const e2eePassphrase = - typeof window !== 'undefined' && decodePassphrase(location.hash.substring(1)); - - const [preJoinChoices, setPreJoinChoices] = useState(undefined); - - function handlePreJoinSubmit(values: LocalUserChoices) { - if (values.e2ee) { - location.hash = encodePassphrase(values.sharedPassphrase); - } - setPreJoinChoices(values); - } - - return ( -
- {roomName && !Array.isArray(roomName) && preJoinChoices ? ( -
- -
- ) : ( -
- {/*

Kitt2

*/} - console.log('error while setting up prejoin', err)} - defaults={{ - username: 'Pinkman', - videoEnabled: false, - audioEnabled: false, - e2ee: true, - sharedPassphrase: e2eePassphrase || randomString(64), - }} - onSubmit={handlePreJoinSubmit} - /> -
- )} -
- ); -} diff --git a/meet/app/r/page.tsx b/meet/app/r/page.tsx deleted file mode 100644 index d4a2989..0000000 --- a/meet/app/r/page.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { ButtonLink } from '~/components/ui/button'; - -export default function Room() { - return ( -
-
-

Lobby

- - Join a new room - -
-
- ); -} diff --git a/meet/middleware.ts b/meet/middleware.ts deleted file mode 100644 index bfbabb8..0000000 --- a/meet/middleware.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { NextResponse, type NextRequest } from 'next/server'; -import { generateRoomId } from '~/utils/lksdk'; - -export async function middleware(request: NextRequest) { - const url = request.nextUrl.clone(); - if (url.pathname === '/') { - const roomUrl = new URL(`/r/${generateRoomId()}`, request.url); - return NextResponse.redirect(roomUrl); - } -} diff --git a/meet/package.json b/meet/package.json deleted file mode 100644 index 84605fc..0000000 --- a/meet/package.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "name": "kitt2", - "version": "0.2.0", - "private": true, - "scripts": { - "dev": "ENVIRONMENT=../.env.local next dev --turbo", - "build": "next build", - "start": "next start", - "lint": "next lint" - }, - "dependencies": { - "@livekit/components-react": "1.5.1", - "@livekit/components-styles": "1.0.8", - "@radix-ui/react-slot": "^1.0.2", - "class-variance-authority": "^0.7.0", - "clsx": "^2.1.0", - "livekit-client": "1.15.8", - "livekit-server-sdk": "1.2.7", - "next": "14.0.4", - "react": "18.2.0", - "react-dom": "18.2.0", - "tailwind-merge": "^2.2.0", - "tinykeys": "^2.1.0" - }, - "devDependencies": { - "@headlessui/tailwindcss": "^0.2.0", - "@tailwindcss/aspect-ratio": "^0.4.2", - "@tailwindcss/forms": "^0.5.7", - "@tailwindcss/typography": "^0.5.10", - "@types/node": "20.10.8", - "@types/react": "18.2.47", - "@types/react-dom": "18.2.18", - "autoprefixer": "^10.4.16", - "dotenv": "^16.3.1", - "env-cmd": "^10.1.0", - "eslint": "8.56.0", - "eslint-config-next": "14.0.4", - "postcss": "^8.4.33", - "tailwindcss": "^3.4.1", - "tailwindcss-animate": "^1.0.7", - "typescript": "5.3.3" - }, - "engines": { - "node": ">=18" - } -} diff --git a/meet/public/favicon.ico b/meet/public/favicon.ico deleted file mode 100644 index 8fcb285..0000000 Binary files a/meet/public/favicon.ico and /dev/null differ diff --git a/meet/tailwind.config.ts b/meet/tailwind.config.ts deleted file mode 100644 index 210e415..0000000 --- a/meet/tailwind.config.ts +++ /dev/null @@ -1,19 +0,0 @@ -import aspectRatioPlugin from '@tailwindcss/aspect-ratio'; -import typographyPlugin from '@tailwindcss/typography'; -import { shadcnPlugin } from './utils/shadcnPlugin'; -import headlessui from '@headlessui/tailwindcss'; -import animatePlugin from 'tailwindcss-animate'; -import formsPlugin from '@tailwindcss/forms'; -import { type Config } from 'tailwindcss'; - -export default { - content: ['./{app,components}/**/*.{ts,tsx}'], - plugins: [ - headlessui, - animatePlugin, - aspectRatioPlugin, - typographyPlugin, - formsPlugin, - shadcnPlugin, - ], -} satisfies Config; diff --git a/meet/next-env.d.ts b/next-env.d.ts similarity index 100% rename from meet/next-env.d.ts rename to next-env.d.ts diff --git a/meet/next.config.mjs b/next.config.mjs similarity index 64% rename from meet/next.config.mjs rename to next.config.mjs index 718a0cf..a4144e8 100644 --- a/meet/next.config.mjs +++ b/next.config.mjs @@ -1,7 +1,3 @@ -import { config } from "dotenv" - -config({ path: `${process.env.ENVIRONMENT ?? "."}` }); - /** @type {import('next').NextConfig} */ const nextConfig = { reactStrictMode: true, diff --git a/package.json b/package.json index 8ff6d45..f82709b 100644 --- a/package.json +++ b/package.json @@ -1,34 +1,60 @@ { - "name": "kitt_2", - "version": "1.0.0", - "description": "", + "name": "kitt2", + "version": "0.2.0", + "private": true, + "keywords": [], + "author": "", + "license": "ISC", "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint", "prepare": "husky install", - "build": "pnpm --dir=meet build", - "dev": "concurrently --names 'WEB,SERVER' -c 'auto' \"pnpm --dir=meet dev\" \"cargo rr --bin lkgpt\"", - "format": "concurrently --names 'fmt:web,fmt:rs,fmt:toml' -c 'auto' \"pnpm format:prettier\" \"pnpm format:rs\" \"pnpm format:toml\"", + "dev:all": "concurrently --names 'WEB,SERVER' -c 'auto' \"pnpm dev\" \"python my_agent.py start\"", "format:prettier": "prettier --write \"**/*.{js,ts,tsx}\"", - "format:rs": "cargo fmt --all", - "format:toml": "taplo format", "pre-commit": "lint-staged" }, - "keywords": [], - "author": "", - "license": "ISC", + "dependencies": { + "@livekit/components-react": "1.5.1", + "@livekit/components-styles": "1.0.8", + "@radix-ui/react-slot": "^1.0.2", + "class-variance-authority": "^0.7.0", + "clsx": "^2.1.0", + "framer-motion": "^11.0.5", + "js-yaml": "^4.1.0", + "livekit-client": "1.15.8", + "livekit-server-sdk": "1.2.7", + "next": "14.0.4", + "react": "18.2.0", + "react-dom": "18.2.0", + "tailwind-merge": "^2.2.0", + "tinykeys": "^2.1.0" + }, "devDependencies": { + "@headlessui/tailwindcss": "^0.2.0", + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/forms": "^0.5.7", + "@tailwindcss/typography": "^0.5.10", "@taplo/cli": "^0.5.2", + "@types/js-yaml": "^4.0.9", + "@types/node": "20.10.8", + "@types/react": "18.2.47", + "@types/react-dom": "18.2.18", + "autoprefixer": "^10.4.16", "concurrently": "^8.2.2", + "env-cmd": "^10.1.0", + "eslint": "8.56.0", + "eslint-config-next": "14.0.4", "husky": "^8.0.3", "lint-staged": "^15.2.0", - "prettier": "^3.1.1" + "postcss": "^8.4.33", + "prettier": "^3.1.1", + "tailwindcss": "^3.4.1", + "tailwindcss-animate": "^1.0.7", + "typescript": "5.3.3" }, "lint-staged": { - "*.rs": [ - "cargo fmt --" - ], - "*.toml": [ - "taplo format" - ], "*.{js,ts,tsx}": [ "eslint --ext jsx,ts,tsx --quiet --fix --", "prettier --write" @@ -39,7 +65,7 @@ }, "packageManager": "pnpm@8.7.6", "engines": { - "node": "20.x", + "node": ">=18", "pnpm": "8" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 00ecce0..7294197 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,22 +7,113 @@ settings: importers: .: + dependencies: + '@livekit/components-react': + specifier: 1.5.1 + version: 1.5.1(livekit-client@1.15.8)(react-dom@18.2.0)(react@18.2.0)(tslib@2.6.2) + '@livekit/components-styles': + specifier: 1.0.8 + version: 1.0.8 + '@radix-ui/react-slot': + specifier: ^1.0.2 + version: 1.0.2(@types/react@18.2.47)(react@18.2.0) + class-variance-authority: + specifier: ^0.7.0 + version: 0.7.0 + clsx: + specifier: ^2.1.0 + version: 2.1.0 + framer-motion: + specifier: ^11.0.5 + version: 11.0.5(react-dom@18.2.0)(react@18.2.0) + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 + livekit-client: + specifier: 1.15.8 + version: 1.15.8 + livekit-server-sdk: + specifier: 1.2.7 + version: 1.2.7 + next: + specifier: 14.0.4 + version: 14.0.4(react-dom@18.2.0)(react@18.2.0) + react: + specifier: 18.2.0 + version: 18.2.0 + react-dom: + specifier: 18.2.0 + version: 18.2.0(react@18.2.0) + tailwind-merge: + specifier: ^2.2.0 + version: 2.2.0 + tinykeys: + specifier: ^2.1.0 + version: 2.1.0 devDependencies: + '@headlessui/tailwindcss': + specifier: ^0.2.0 + version: 0.2.0(tailwindcss@3.4.1) + '@tailwindcss/aspect-ratio': + specifier: ^0.4.2 + version: 0.4.2(tailwindcss@3.4.1) + '@tailwindcss/forms': + specifier: ^0.5.7 + version: 0.5.7(tailwindcss@3.4.1) + '@tailwindcss/typography': + specifier: ^0.5.10 + version: 0.5.10(tailwindcss@3.4.1) '@taplo/cli': specifier: ^0.5.2 version: 0.5.2 + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 + '@types/node': + specifier: 20.10.8 + version: 20.10.8 + '@types/react': + specifier: 18.2.47 + version: 18.2.47 + '@types/react-dom': + specifier: 18.2.18 + version: 18.2.18 + autoprefixer: + specifier: ^10.4.16 + version: 10.4.16(postcss@8.4.33) concurrently: specifier: ^8.2.2 version: 8.2.2 + env-cmd: + specifier: ^10.1.0 + version: 10.1.0 + eslint: + specifier: 8.56.0 + version: 8.56.0 + eslint-config-next: + specifier: 14.0.4 + version: 14.0.4(eslint@8.56.0)(typescript@5.3.3) husky: specifier: ^8.0.3 version: 8.0.3 lint-staged: specifier: ^15.2.0 version: 15.2.0 + postcss: + specifier: ^8.4.33 + version: 8.4.33 prettier: specifier: ^3.1.1 version: 3.1.1 + tailwindcss: + specifier: ^3.4.1 + version: 3.4.1 + tailwindcss-animate: + specifier: ^1.0.7 + version: 1.0.7(tailwindcss@3.4.1) + typescript: + specifier: 5.3.3 + version: 5.3.3 meet: dependencies: @@ -41,6 +132,12 @@ importers: clsx: specifier: ^2.1.0 version: 2.1.0 + framer-motion: + specifier: ^11.0.5 + version: 11.0.5(react-dom@18.2.0)(react@18.2.0) + js-yaml: + specifier: ^4.1.0 + version: 4.1.0 livekit-client: specifier: 1.15.8 version: 1.15.8 @@ -75,6 +172,12 @@ importers: '@tailwindcss/typography': specifier: ^0.5.10 version: 0.5.10(tailwindcss@3.4.1) + '@taplo/cli': + specifier: ^0.5.2 + version: 0.5.2 + '@types/js-yaml': + specifier: ^4.0.9 + version: 4.0.9 '@types/node': specifier: 20.10.8 version: 20.10.8 @@ -87,6 +190,9 @@ importers: autoprefixer: specifier: ^10.4.16 version: 10.4.16(postcss@8.4.33) + concurrently: + specifier: ^8.2.2 + version: 8.2.2 dotenv: specifier: ^16.3.1 version: 16.3.1 @@ -99,9 +205,18 @@ importers: eslint-config-next: specifier: 14.0.4 version: 14.0.4(eslint@8.56.0)(typescript@5.3.3) + husky: + specifier: ^8.0.3 + version: 8.0.3 + lint-staged: + specifier: ^15.2.0 + version: 15.2.0 postcss: specifier: ^8.4.33 version: 8.4.33 + prettier: + specifier: ^3.1.1 + version: 3.1.1 tailwindcss: specifier: ^3.4.1 version: 3.4.1 @@ -134,6 +249,20 @@ packages: resolution: {integrity: sha512-hp19vSFgNw3wBBcVBx5qo5pufCqjaJ0Cfk5H/pfjNOfNWU+4/w0QVOmfAOZNRrNWRrVuaJWxcN8P2vhOkkzbBQ==} dev: false + /@emotion/is-prop-valid@0.8.8: + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + requiresBuild: true + dependencies: + '@emotion/memoize': 0.7.4 + dev: false + optional: true + + /@emotion/memoize@0.7.4: + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + requiresBuild: true + dev: false + optional: true + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -541,6 +670,10 @@ packages: hasBin: true dev: true + /@types/js-yaml@4.0.9: + resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} + dev: true + /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true @@ -707,7 +840,6 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true /aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} @@ -1723,6 +1855,24 @@ packages: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} dev: true + /framer-motion@11.0.5(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Lb0EYbQcSK/pgyQUJm+KzsQrKrJRX9sFRyzl9hSr9gFG4Mk8yP7BjhuxvRXzblOM/+JxycrJdCDVmOQBsjpYlw==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + tslib: 2.6.2 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + dev: false + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -2193,7 +2343,6 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: true /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml deleted file mode 100644 index 4eb55fe..0000000 --- a/pnpm-workspace.yaml +++ /dev/null @@ -1,2 +0,0 @@ -packages: - - "meet" diff --git a/meet/postcss.config.js b/postcss.config.js similarity index 100% rename from meet/postcss.config.js rename to postcss.config.js diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/public/favicon.ico differ diff --git a/meet/public/images/livekit-apple-touch.png b/public/images/livekit-apple-touch.png similarity index 100% rename from meet/public/images/livekit-apple-touch.png rename to public/images/livekit-apple-touch.png diff --git a/meet/public/images/livekit-meet-home.svg b/public/images/livekit-meet-home.svg similarity index 100% rename from meet/public/images/livekit-meet-home.svg rename to public/images/livekit-meet-home.svg diff --git a/meet/public/images/livekit-meet-open-graph.png b/public/images/livekit-meet-open-graph.png similarity index 100% rename from meet/public/images/livekit-meet-open-graph.png rename to public/images/livekit-meet-open-graph.png diff --git a/meet/public/images/livekit-safari-pinned-tab.svg b/public/images/livekit-safari-pinned-tab.svg similarity index 100% rename from meet/public/images/livekit-safari-pinned-tab.svg rename to public/images/livekit-safari-pinned-tab.svg diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1320643 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +livekit>=0.9.0 +livekit-api +livekit-agents>=0.4.0 +livekit-plugins-deepgram>=0.2.0 +livekit-plugins-elevenlabs>=0.2.0 +openai \ No newline at end of file diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 5d56faf..0000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,2 +0,0 @@ -[toolchain] -channel = "nightly" diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index 737e956..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,8 +0,0 @@ -max_width = 100 -indent_style = "Block" -use_try_shorthand = true -reorder_impl_items = true -use_small_heuristics = "Max" -imports_granularity = "Crate" -use_field_init_shorthand = true -match_block_trailing_comma = true diff --git a/server.py b/server.py deleted file mode 100644 index 496d844..0000000 --- a/server.py +++ /dev/null @@ -1,445 +0,0 @@ -# Kitt 1.5 -from elevenlabs import generate, stream, TTS, Voice, VoiceSettings, Model -from websockets.sync.client import connect as client_ws_connect -from logging import basicConfig, INFO # info, warn, error, -from typing import Callable, Dict, Iterator, Union -from quart.typing import ResponseReturnValue -from logging.config import dictConfig -from signal import SIGINT, SIGTERM -from quart import Quart, websocket -from dotenv import load_dotenv -from os import environ as env -from deepgram import Deepgram -from livekit import api, rtc -from openai import OpenAI -from quart import request -from pathlib import Path -import numpy as np -import websockets -import asyncio -import json - -load_dotenv() -app = Quart(__name__) - -# ******** ENV VARIABLES ******** - -LIVEKIT_API_KEY = env.get("LIVEKIT_API_KEY") -LIVEKIT_API_SECRET = env.get("LIVEKIT_API_SECRET") -LIVEKIT_WS_URL = env.get("LIVEKIT_WS_URL") - -OPENAI_API_KEY = env.get("OPENAI_API_KEY") -OPENAI_ORG_ID = env.get("OPENAI_ORG_ID") - -ELEVENLABS_API_KEY = env.get("ELEVENLABS_API_KEY") -DEEPGRAM_API_KEY = env.get("DEEPGRAM_API_KEY") - -# ******** ENSURE ENV VARIABLES ARE SET ******** -assert isinstance(LIVEKIT_API_KEY, str), "LIVEKIT_API_KEY must be set!" -assert isinstance(LIVEKIT_API_SECRET, str), "LIVEKIT_API_SECRET must be set!" -assert isinstance(LIVEKIT_WS_URL, str), "LIVEKIT_WS_URL must be set!" -assert isinstance(OPENAI_API_KEY, str), "OPENAI_API_KEY must be set!" -assert isinstance(OPENAI_ORG_ID, str), "OPENAI_ORG_ID must be set!" -assert isinstance(ELEVENLABS_API_KEY, str), "ELEVENLABS_API_KEY must be set!" -assert isinstance(DEEPGRAM_API_KEY, str), "DEEPGRAM_API_KEY must be set!" - -# ******** GLOBAL VARIABLES ******** -SAMPLE_RATE = 48000 -SAMPLES_PER_CHANNEL = 480 # 10ms at 48kHz -NUM_CHANNELS = 1 -BOT_NAME = "talking_donut" -VOICE_ID = "21m00Tcm4TlvDq8ikWAM" -SPLITTERS = [".", ",", "?", "!", ";", ":", "—", "-", "(", ")", "[", "]", "}", " "] -WHISPER_SAMPLE_RATE = 16000 -# *********** CLIENTS *********** - -OPEN_AI_CLIENT = OpenAI( - api_key=OPENAI_API_KEY, - organization=OPENAI_ORG_ID, -) - -DEEPGRAM_CLIENT = Deepgram(DEEPGRAM_API_KEY) - -DEEPGRAM_PARAMS = { - "punctuate": True, - "numerals": True, - "model": "general", - "language": "en-US", - "tier": "enhanced" - } - -DEEPGRAM_TIME_LIMT = float('inf') -DEEPGRAM_TRANSCRIPT_ONLY = True - - -def text_chunker(chunks: Iterator[str]) -> Iterator[str]: - """Used during input streaming to chunk text blocks and set last char to space""" - splitters = (".", ",", "?", "!", ";", ":", "—", "-", "(", ")", "[", "]", "}", " ") - buffer = "" - for text in chunks: - if buffer.endswith(splitters): - yield buffer if buffer.endswith(" ") else buffer + " " - buffer = text - elif text.startswith(splitters): - output = buffer + text[0] - yield output if output.endswith(" ") else output + " " - buffer = text[1:] - else: - buffer += text - if buffer != "": - yield buffer + " " - -def generate_stream_input( - text: Iterator[str], voice: Voice - ) -> Iterator[bytes]: - BOS = json.dumps( - dict( - text=" ", - try_trigger_generation=True, - voice_settings=voice.settings.model_dump() if voice.settings else None, - generation_config=dict( - chunk_length_schedule=[50], - ), - ) - ) - EOS = json.dumps(dict(text="")) - - with client_ws_connect( - f"wss://api.elevenlabs.io/v1/text-to-speech/{voice.voice_id}/stream-input?model_id=eleven_monolingual_v2", - additional_headers={"xi-api-key": ELEVENLABS_API_KEY} - ) as websocket: - # Send beginning of stream - websocket.send(BOS) - app.logger.info("CONNECTED AND STARTED ELEVEN LABS WS CONNECTION") - - # Stream text chunks and receive audio - for text_chunk in text_chunker(text): - data = dict(text=text_chunk, try_trigger_generation=True) - websocket.send(json.dumps(data)) - print("\n\nSENT TO ELEVEN LABS") - try: - data = json.loads(websocket.recv(1e-4)) - if data["audio"]: - yield base64.b64decode(data["audio"]) # type: ignore - except TimeoutError: - pass - - # Send end of stream - websocket.send(EOS) - - # Receive remaining audio - while True: - try: - data = json.loads(websocket.recv()) - if data["audio"]: - yield base64.b64decode(data["audio"]) # type: ignore - except websockets.exceptions.ConnectionClosed: - break - -def ends_with_splitter(chunk): - splitters = [".", ",", "?", "!", ";", ":", "—", "-", "(", ")", "[", "]", "}", " "] - return ( - chunk - and chunk != " " - and any(chunk.endswith(splitter) for splitter in splitters) - ) - -async def audio_chunks_to_livekit(audio_stream: bytes | Iterator[bytes], audio_source: rtc.AudioSource,): - audio_frame = rtc.AudioFrame.create(SAMPLE_RATE, NUM_CHANNELS, SAMPLES_PER_CHANNEL) - audio_data = np.frombuffer(audio_frame.data, dtype=np.int16) - - if isinstance(audio_stream, bytes): - np.copyto(audio_data, audio_stream) - await audio_source.capture_frame(audio_frame) - else: - for chunk in audio_stream: - if chunk is not None: - np.copyto(audio_data, chunk) - await audio_source.capture_frame(audio_frame) - -async def chat_completion( - text_data: str, - room: rtc.Room, - participant, - audio_source: rtc.AudioSource, -): - try: - gpt_resp = OPEN_AI_CLIENT.chat.completions.create( - model="gpt-4-1106-preview", - messages=[ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": text_data}, - ], - stream=True, - ) - - def gpt_text_resp_iter() -> Iterator[str]: - chat_resp_chunk: str = "" - for chunk in gpt_resp: - msg_chunk = chunk.choices[0].delta.content - is_finished = chunk.choices[0].finish_reason - if is_finished: - break - else: - if msg_chunk: - chat_resp_chunk += msg_chunk - if ends_with_splitter(chat_resp_chunk): - app.logger.info(f"chat_resp_chunk - [{chat_resp_chunk}]") - yield chat_resp_chunk - chat_resp_chunk: str = "" - - gpt_text_resp_iter() - - # voice = Voice( - # voice_id=VOICE_ID, - # name="Bella", - # settings= VoiceSettings( - # stability=0.71, similarity_boost=0.5, style=0.0, use_speaker_boost=True - # ), - # ) - - # audio_stream = generate_stream_input(gpt_text_resp_iter(), voice) - # await audio_chunks_to_livekit(audio_stream, audio_source) - - except Exception as e: - app.logger.error(f"Exception while processing data received: {e}") - -async def handle_audio(audio_stream: rtc.AudioStream, deepgramLive): - async for frame in audio_stream: - frame = frame.remix_and_resample(WHISPER_SAMPLE_RATE, 1) - audio_bytes = frame.data.tobytes() - deepgramLive.send(audio_bytes) - - -async def ai_bot(room: rtc.Room, participant: str) -> None: - # publish a track - audio_source = rtc.AudioSource(SAMPLE_RATE, NUM_CHANNELS) - track = rtc.LocalAudioTrack.create_audio_track(f"{BOT_NAME}_voice", audio_source) - options = rtc.TrackPublishOptions() - options.source = rtc.TrackSource.SOURCE_MICROPHONE - audio_publication = await room.local_participant.publish_track(track, options) - app.logger.info("published audio track %s", audio_publication.sid) - - try: - deepgramLive = await DEEPGRAM_CLIENT.transcription.live(DEEPGRAM_PARAMS) # type: ignore - except Exception as e: - print(f'Could not open socket: {e}') - return - # Listen for the connection to close - deepgramLive.registerHandler(deepgramLive.event.CLOSE, # type: ignore - lambda _: print('✅ Transcription complete! Connection closed. ✅')) - - - - @room.on("data_received") - def on_data_received( - data: bytes, kind: rtc.DataPacketKind, participant: rtc.Participant - ): - msg_dict = json.loads(data) - raw_msg: str = msg_dict.get("message") - app.logger.info("received data from %s: %s", participant.identity, msg_dict) - if raw_msg: - asyncio.create_task( - chat_completion(raw_msg, room, participant, audio_source) - ) - else: - app.logger.warning("didn't send data") - - # ************* OTHERS ******************* - - @room.on("participant_connected") - def on_participant_connected(participant: rtc.RemoteParticipant) -> None: - app.logger.info( - "participant connected: %s %s", participant.sid, participant.identity - ) - - @room.on("participant_disconnected") - def on_participant_disconnected(participant: rtc.RemoteParticipant): - app.logger.info( - "participant disconnected: %s %s", participant.sid, participant.identity - ) - - @room.on("local_track_published") - def on_local_track_published( - publication: rtc.LocalTrackPublication, - track: Union[rtc.LocalAudioTrack, rtc.LocalVideoTrack], - ): - app.logger.info("local track published: %s", publication.sid) - - @room.on("active_speakers_changed") - def on_active_speakers_changed(speakers: list[rtc.Participant]): - app.logger.info("active speakers changed: %s", speakers) - - @room.on("local_track_unpublished") - def on_local_track_unpublished(publication: rtc.LocalTrackPublication): - app.logger.info("local track unpublished: %s", publication.sid) - - @room.on("track_published") - def on_track_published( - publication: rtc.RemoteTrackPublication, participant: rtc.RemoteParticipant - ): - app.logger.info( - "track published: %s from participant %s (%s)", - publication.sid, - participant.sid, - participant.identity, - ) - - @room.on("track_unpublished") - def on_track_unpublished( - publication: rtc.RemoteTrackPublication, participant: rtc.RemoteParticipant - ): - app.logger.info("track unpublished: %s", publication.sid) - - @room.on("track_subscribed") - def on_track_subscribed( - track: rtc.Track, - publication: rtc.RemoteTrackPublication, - participant: rtc.RemoteParticipant, - ): - app.logger.info("track subscribed: %s", publication.sid) - if track.kind == rtc.TrackKind.KIND_VIDEO: - _video_stream = rtc.VideoStream(track) - # video_stream is an async iterator that yields VideoFrame - elif track.kind == rtc.TrackKind.KIND_AUDIO: - print("Subscribed to an Audio Track") - # audio_stream is an async iterator that yields AudioFrame - audio_stream = rtc.AudioStream(track) - asyncio.create_task(handle_audio(audio_stream, deepgramLive)) - - @room.on("track_unsubscribed") - def on_track_unsubscribed( - track: rtc.Track, - publication: rtc.RemoteTrackPublication, - participant: rtc.RemoteParticipant, - ): - app.logger.info("track unsubscribed: %s", publication.sid) - - @room.on("track_muted") - def on_track_muted( - publication: rtc.RemoteTrackPublication, participant: rtc.RemoteParticipant - ): - app.logger.info("track muted: %s", publication.sid) - - @room.on("track_unmuted") - def on_track_unmuted( - publication: rtc.RemoteTrackPublication, participant: rtc.RemoteParticipant - ): - app.logger.info("track unmuted: %s", publication.sid) - - @room.on("connection_quality_changed") - def on_connection_quality_changed( - participant: rtc.Participant, quality: rtc.ConnectionQuality - ): - app.logger.info("connection quality changed for %s", participant.identity) - - @room.on("track_subscription_failed") - def on_track_subscription_failed( - participant: rtc.RemoteParticipant, track_sid: str, error: str - ): - app.logger.info("track subscription failed: %s %s", participant.identity, error) - - @room.on("connection_state_changed") - def on_connection_state_changed(state: rtc.ConnectionState): - app.logger.info("connection state changed: %s", state) - - @room.on("connected") - def on_connected() -> None: - app.logger.info("connected") - - @room.on("disconnected") - def on_disconnected() -> None: - app.logger.info("disconnected") - - @room.on("reconnecting") - def on_reconnecting() -> None: - app.logger.info("reconnecting") - - @room.on("reconnected") - def on_reconnected() -> None: - app.logger.info("reconnected") - - app.logger.info("connected to room %s", room.name) - app.logger.info("participants: %s", room.participants) - -@app.route("/lsdk-webhook", methods=["POST"]) -async def handle_livekit_webhook(): - token_verifier = api.TokenVerifier( - api_key=LIVEKIT_API_KEY, api_secret=LIVEKIT_API_SECRET - ) - webhook_receiver = api.WebhookReceiver(token_verifier) - - jwt = request.headers.get("Authorization") - if not jwt: - app.logger.error("no JWT in authorization header") - return "no JWT in authorization header", 401 - - body = await request.get_data(as_text=True) - - try: - event = webhook_receiver.receive(body, jwt) - if event.event == "room_started": - participant_room = event.room - participant = event.participant.name - room_name = participant_room.name - - app.logger.info("participant in the room {participant}") - - token = ( - api.AccessToken(api_key=LIVEKIT_API_KEY, api_secret=LIVEKIT_API_SECRET) - .with_identity(BOT_NAME) - .with_name(BOT_NAME) - .with_grants( - api.VideoGrants( - room=room_name, - room_join=True, - room_list=True, - room_record=True, - can_update_own_metadata=True, - ) - ) - .to_jwt() - ) - - room = rtc.Room() - await room.connect( - LIVEKIT_WS_URL, token, options=rtc.RoomOptions(auto_subscribe=True) - ) - app.logger.info("connected to room %s", room.name) - asyncio.create_task(ai_bot(room, participant)) - - # if num_participants < max_participants - else: - app.logger.info(f"Received event: {event.event}") - return "Webhook processed 🎉", 200 - except Exception as e: - app.logger.error(f"Error processing webhook: {e}") - return str(e), 500 - - -@app.route("/", methods=["GET"]) -def health_check() -> ResponseReturnValue: - return "Server is Up ", 200 - - -# @app.after_serving -# async def create_db_pool(): -# deepgramLive = app.deepgramLive -# if deepgramLive: -# await deepgramLive.finish() - -if __name__ == "__main__": - dictConfig( - { - "version": 1, - "loggers": { - "quart.app": { - "level": "ERROR", - }, - }, - } - ) - # basicConfig(level=INFO) - # handlers=[logging.FileHandler("server.log"), logging.StreamHandler()], - port = int(env.get("PORT", 6669)) - app.run(host="0.0.0.0", port=port, debug=True, use_reloader=False) diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..96ccb99 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,95 @@ +import aspectRatioPlugin from '@tailwindcss/aspect-ratio'; +import typographyPlugin from '@tailwindcss/typography'; +import { shadcnPlugin } from './utils/shadcnPlugin'; +import headlessui from '@headlessui/tailwindcss'; +import animatePlugin from 'tailwindcss-animate'; +import formsPlugin from '@tailwindcss/forms'; +import { type Config } from 'tailwindcss'; +import colors from 'tailwindcss/colors'; + +const shades = ['50', '100', '200', '300', '400', '500', '600', '700', '800', '900', '950']; +const colorList = [ + 'gray', + 'green', + 'cyan', + 'amber', + 'violet', + 'blue', + 'rose', + 'pink', + 'teal', + 'red', +]; +const uiElements = [ + 'bg', + 'selection:bg', + 'border', + 'text', + 'hover:bg', + 'hover:border', + 'hover:text', + 'ring', + 'focus:ring', +]; +const customColors = { + cyan: colors.cyan, + green: colors.green, + amber: colors.amber, + violet: colors.violet, + blue: colors.blue, + rose: colors.rose, + pink: colors.pink, + teal: colors.teal, + red: colors.red, +}; + +let shadowNames = []; +let customShadows: Record = {}; +let textShadows: Record = {}; +let textShadowNames: Array = []; + +for (const [name, color] of Object.entries(customColors)) { + customShadows[`${name}`] = `0px 0px 10px ${color['500']}`; + customShadows[`lg-${name}`] = `0px 0px 20px ${color['600']}`; + textShadows[`${name}`] = `0px 0px 4px ${color['700']}`; + textShadowNames.push(`drop-shadow-${name}`); + shadowNames.push(`shadow-${name}`); + shadowNames.push(`shadow-lg-${name}`); + shadowNames.push(`hover:shadow-${name}`); +} + +const safelist = [ + 'bg-black', + 'bg-white', + 'transparent', + 'object-cover', + 'object-contain', + ...shadowNames, + ...textShadowNames, + ...shades.flatMap((shade) => [ + ...colorList.flatMap((color) => [ + ...uiElements.flatMap((element) => [`${element}-${color}-${shade}`]), + ]), + ]), +]; + +export default { + content: ['./{app,components}/**/*.{ts,tsx}'], + extend: { + dropShadow: { + ...textShadows, + }, + boxShadow: { + ...customShadows, + }, + }, + safelist, + plugins: [ + headlessui, + animatePlugin, + aspectRatioPlugin, + typographyPlugin, + formsPlugin, + shadcnPlugin, + ], +} satisfies Config; diff --git a/meet/tsconfig.json b/tsconfig.json similarity index 100% rename from meet/tsconfig.json rename to tsconfig.json diff --git a/meet/utils/helpers.ts b/utils/helpers.ts similarity index 100% rename from meet/utils/helpers.ts rename to utils/helpers.ts diff --git a/meet/utils/lksdk.ts b/utils/lksdk.ts similarity index 98% rename from meet/utils/lksdk.ts rename to utils/lksdk.ts index 06f37ac..8d35a75 100644 --- a/meet/utils/lksdk.ts +++ b/utils/lksdk.ts @@ -29,6 +29,7 @@ export function decodePassphrase(base64String: string) { return decodeURIComponent(base64String); } +// DELETE LATER export function generateRoomId(): string { return `${randomString(4)}-${randomString(4)}-${randomString(4)}`; } diff --git a/meet/utils/server.ts b/utils/server.ts similarity index 100% rename from meet/utils/server.ts rename to utils/server.ts diff --git a/meet/utils/shadcnPlugin.ts b/utils/shadcnPlugin.ts similarity index 100% rename from meet/utils/shadcnPlugin.ts rename to utils/shadcnPlugin.ts diff --git a/meet/utils/tw.ts b/utils/tw.ts similarity index 100% rename from meet/utils/tw.ts rename to utils/tw.ts diff --git a/meet/utils/types.ts b/utils/types.ts similarity index 100% rename from meet/utils/types.ts rename to utils/types.ts