From 58d53cab1e43d9f172357d48ef2e423e1101b6b7 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Tue, 10 Feb 2026 09:31:39 -0600 Subject: [PATCH] Remove TUI feature and all related code Drop ratatui, crossterm, hostname dependencies and the tui feature flag. Delete src/tui/ directory, remove event bus plumbing from websocket client, and simplify connect/init_logger to single implementations. -1,979 lines of conditional compilation removed. --- Cargo.lock | 941 ++-------------------------------------- Cargo.toml | 9 - src/main.rs | 122 +----- src/tui/app.rs | 150 ------- src/tui/events.rs | 72 --- src/tui/mod.rs | 8 - src/tui/state.rs | 172 -------- src/tui/ui.rs | 194 --------- src/websocket_client.rs | 360 +-------------- 9 files changed, 49 insertions(+), 1979 deletions(-) delete mode 100644 src/tui/app.rs delete mode 100644 src/tui/events.rs delete mode 100644 src/tui/mod.rs delete mode 100644 src/tui/state.rs delete mode 100644 src/tui/ui.rs diff --git a/Cargo.lock b/Cargo.lock index eaa75c5..6d70bf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,12 +52,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -143,16 +137,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", -] - -[[package]] -name = "atomic" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" -dependencies = [ - "bytemuck", + "syn", ] [[package]] @@ -196,12 +181,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd307490d624467aa6f74b0eabb77633d1f758a7b25f12bceb0b22e08d9726f6" -[[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - [[package]] name = "base64ct" version = "1.8.3" @@ -219,27 +198,6 @@ dependencies = [ "sha2 0.10.9", ] -[[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.10.0" @@ -298,12 +256,6 @@ version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" -[[package]] -name = "bytemuck" -version = "1.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" - [[package]] name = "byteorder" version = "1.5.0" @@ -316,15 +268,6 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" -[[package]] -name = "castaway" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a" -dependencies = [ - "rustversion", -] - [[package]] name = "cbc" version = "0.1.2" @@ -423,7 +366,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -453,20 +396,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "compact_str" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" -dependencies = [ - "castaway", - "cfg-if", - "itoa", - "rustversion", - "ryu", - "static_assertions", -] - [[package]] name = "const-oid" version = "0.9.6" @@ -479,15 +408,6 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -523,33 +443,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossterm" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" -dependencies = [ - "bitflags 2.10.0", - "crossterm_winapi", - "derive_more", - "document-features", - "mio", - "parking_lot", - "rustix", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" -dependencies = [ - "winapi", -] - [[package]] name = "crypto-bigint" version = "0.5.5" @@ -605,16 +498,6 @@ dependencies = [ "rand_core 0.10.0-rc-3", ] -[[package]] -name = "csscolorparser" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2a7d3066da2de787b7f032c736763eb7ae5d355f81a68bab2675a96008b0bf" -dependencies = [ - "lab", - "phf", -] - [[package]] name = "ctr" version = "0.9.2" @@ -657,41 +540,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", -] - -[[package]] -name = "darling" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" -dependencies = [ - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.114", -] - -[[package]] -name = "darling_macro" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -708,15 +557,9 @@ checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] -[[package]] -name = "deltae" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" - [[package]] name = "der" version = "0.7.10" @@ -739,37 +582,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "deranged" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derive_more" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" -dependencies = [ - "derive_more-impl", -] - -[[package]] -name = "derive_more-impl" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.114", -] - [[package]] name = "digest" version = "0.10.7" @@ -793,15 +605,6 @@ dependencies = [ "crypto-common 0.2.0", ] -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - [[package]] name = "dunce" version = "1.0.5" @@ -883,7 +686,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -902,25 +705,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "euclid" -version = "0.22.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" -dependencies = [ - "num-traits", -] - -[[package]] -name = "fancy-regex" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" -dependencies = [ - "bit-set", - "regex", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -943,35 +727,12 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" -[[package]] -name = "filedescriptor" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" -dependencies = [ - "libc", - "thiserror 1.0.69", - "winapi", -] - [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" -[[package]] -name = "finl_unicode" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" - -[[package]] -name = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - [[package]] name = "fixedbitset" version = "0.5.7" @@ -988,24 +749,12 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" -[[package]] -name = "foldhash" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" - [[package]] name = "fs_extra" version = "1.3.0" @@ -1068,7 +817,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1194,7 +943,7 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash 0.1.5", + "foldhash", ] [[package]] @@ -1202,11 +951,6 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash 0.2.0", -] [[package]] name = "hax-lib" @@ -1229,7 +973,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1290,17 +1034,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "hostname" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617aaa3557aef3810a6369d0a99fac8a080891b68bd9f9812a1eeda0c0730cbd" -dependencies = [ - "cfg-if", - "libc", - "windows-link", -] - [[package]] name = "http" version = "1.4.0" @@ -1356,12 +1089,6 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - [[package]] name = "indexmap" version = "2.13.0" @@ -1374,15 +1101,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "indoc" -version = "2.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" -dependencies = [ - "rustversion", -] - [[package]] name = "inout" version = "0.1.4" @@ -1393,19 +1111,6 @@ dependencies = [ "generic-array 0.14.7", ] -[[package]] -name = "instability" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357b7205c6cd18dd2c86ed312d1e70add149aea98e7ef72b9fdf0270e555c11d" -dependencies = [ - "darling", - "indoc", - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "internal-russh-forked-ssh-key" version = "0.6.16+upstream-0.6.7" @@ -1478,23 +1183,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kasuari" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fe90c1150662e858c7d5f945089b7517b0a80d8bf7ba4b1b5ffc984e7230a5b" -dependencies = [ - "hashbrown 0.16.1", - "portable-atomic", - "thiserror 2.0.18", -] - -[[package]] -name = "lab" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" - [[package]] name = "lazy_static" version = "1.5.0" @@ -1588,27 +1276,12 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" -[[package]] -name = "line-clipping" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4de44e98ddbf09375cbf4d17714d18f39195f4f4894e8524501726fd9a8a4a" -dependencies = [ - "bitflags 2.10.0", -] - [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - [[package]] name = "lock_api" version = "0.4.14" @@ -1624,25 +1297,6 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" -[[package]] -name = "lru" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" -dependencies = [ - "hashbrown 0.16.1", -] - -[[package]] -name = "mac_address" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" -dependencies = [ - "nix", - "winapi", -] - [[package]] name = "matchers" version = "0.2.0" @@ -1664,27 +1318,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "memmem" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[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.8.9" @@ -1702,7 +1335,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.61.2", ] @@ -1728,11 +1360,10 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.10.0", + "bitflags", "cfg-if", "cfg_aliases", "libc", - "memoffset", ] [[package]] @@ -1741,16 +1372,6 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" -[[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 = "nu-ansi-term" version = "0.50.3" @@ -1787,23 +1408,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "num-conv" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" - -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "num-integer" version = "0.1.46" @@ -1833,15 +1437,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -1860,15 +1455,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" -[[package]] -name = "ordered-float" -version = "4.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" -dependencies = [ - "num-traits", -] - [[package]] name = "p256" version = "0.13.2" @@ -1994,112 +1580,17 @@ dependencies = [ "base64ct", ] -[[package]] -name = "pest" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" -dependencies = [ - "memchr", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "pest_meta" -version = "2.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" -dependencies = [ - "pest", - "sha2 0.10.9", -] - [[package]] name = "petgraph" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" dependencies = [ - "fixedbitset 0.5.7", + "fixedbitset", "hashbrown 0.15.5", "indexmap", ] -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_macros", - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", - "syn 2.0.114", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher", -] - [[package]] name = "pin-project-lite" version = "0.2.16" @@ -2177,7 +1668,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.114", + "syn", ] [[package]] @@ -2224,18 +1715,6 @@ dependencies = [ "universal-hash", ] -[[package]] -name = "portable-atomic" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - [[package]] name = "ppv-lite86" version = "0.2.21" @@ -2252,7 +1731,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.114", + "syn", ] [[package]] @@ -2283,7 +1762,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -2320,7 +1799,7 @@ dependencies = [ "prost", "prost-types", "regex", - "syn 2.0.114", + "syn", "tempfile", ] @@ -2334,7 +1813,7 @@ dependencies = [ "itertools", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -2426,98 +1905,13 @@ version = "0.10.0-rc-3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f66ee92bc15280519ef199a274fe0cafff4245d31bc39aaa31c011ad56cb1f05" -[[package]] -name = "ratatui" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" -dependencies = [ - "instability", - "ratatui-core", - "ratatui-crossterm", - "ratatui-macros", - "ratatui-termwiz", - "ratatui-widgets", -] - -[[package]] -name = "ratatui-core" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" -dependencies = [ - "bitflags 2.10.0", - "compact_str", - "hashbrown 0.16.1", - "indoc", - "itertools", - "kasuari", - "lru", - "strum", - "thiserror 2.0.18", - "unicode-segmentation", - "unicode-truncate", - "unicode-width", -] - -[[package]] -name = "ratatui-crossterm" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" -dependencies = [ - "cfg-if", - "crossterm", - "instability", - "ratatui-core", -] - -[[package]] -name = "ratatui-macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" -dependencies = [ - "ratatui-core", - "ratatui-widgets", -] - -[[package]] -name = "ratatui-termwiz" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" -dependencies = [ - "ratatui-core", - "termwiz", -] - -[[package]] -name = "ratatui-widgets" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" -dependencies = [ - "bitflags 2.10.0", - "hashbrown 0.16.1", - "indoc", - "instability", - "itertools", - "line-clipping", - "ratatui-core", - "strum", - "time", - "unicode-segmentation", - "unicode-width", -] - [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags", ] [[package]] @@ -2600,7 +1994,7 @@ checksum = "01fe22d10a0e39c1134a971d5b8db8a40357b48ef22d81fa8d6eac22202dd782" dependencies = [ "aes", "aws-lc-rs", - "bitflags 2.10.0", + "bitflags", "block-padding", "byteorder", "bytes", @@ -2694,7 +2088,7 @@ version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2743,12 +2137,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - [[package]] name = "salsa20" version = "0.10.2" @@ -2822,7 +2210,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -2907,27 +2295,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook" -version = "0.3.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -2964,12 +2331,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" -[[package]] -name = "siphasher" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" - [[package]] name = "slab" version = "0.4.12" @@ -3047,39 +2408,12 @@ dependencies = [ "sha2 0.10.9", ] -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn 2.0.114", -] - [[package]] name = "subtle" version = "2.6.1" @@ -3102,17 +2436,6 @@ dependencies = [ "tracing", ] -[[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.114" @@ -3137,69 +2460,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "terminfo" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" -dependencies = [ - "fnv", - "nom", - "phf", - "phf_codegen", -] - -[[package]] -name = "termios" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" -dependencies = [ - "libc", -] - -[[package]] -name = "termwiz" -version = "0.23.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" -dependencies = [ - "anyhow", - "base64", - "bitflags 2.10.0", - "fancy-regex", - "filedescriptor", - "finl_unicode", - "fixedbitset 0.4.2", - "hex", - "lazy_static", - "libc", - "log", - "memmem", - "nix", - "num-derive", - "num-traits", - "ordered-float", - "pest", - "pest_derive", - "phf", - "sha2 0.10.9", - "signal-hook", - "siphasher", - "terminfo", - "termios", - "thiserror 1.0.69", - "ucd-trie", - "unicode-segmentation", - "vtparse", - "wezterm-bidi", - "wezterm-blob-leases", - "wezterm-color-types", - "wezterm-dynamic", - "wezterm-input-types", - "winapi", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -3226,7 +2486,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3237,7 +2497,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3249,27 +2509,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "time" -version = "0.3.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" -dependencies = [ - "deranged", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde_core", - "time-core", -] - -[[package]] -name = "time-core" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" - [[package]] name = "tls_codec" version = "0.4.2" @@ -3288,7 +2527,7 @@ checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3315,7 +2554,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3353,17 +2592,14 @@ dependencies = [ "cc", "chrono", "clap", - "crossterm", "futures", "home", - "hostname", "libc", "netsnmp-sys", "prost", "prost-build", "prost-types", "rand 0.8.5", - "ratatui", "regex", "russh", "serde", @@ -3397,7 +2633,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3464,41 +2700,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - [[package]] name = "unicode-ident" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-truncate" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" -dependencies = [ - "itertools", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - [[package]] name = "unicode-xid" version = "0.2.6" @@ -3545,7 +2752,6 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ - "atomic", "getrandom 0.3.4", "js-sys", "wasm-bindgen", @@ -3563,15 +2769,6 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vtparse" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" -dependencies = [ - "utf8parse", -] - [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -3642,7 +2839,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn", "wasm-bindgen-shared", ] @@ -3683,7 +2880,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.10.0", + "bitflags", "hashbrown 0.15.5", "indexmap", "semver", @@ -3717,78 +2914,6 @@ dependencies = [ "rustls-pki-types", ] -[[package]] -name = "wezterm-bidi" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" -dependencies = [ - "log", - "wezterm-dynamic", -] - -[[package]] -name = "wezterm-blob-leases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" -dependencies = [ - "getrandom 0.3.4", - "mac_address", - "sha2 0.10.9", - "thiserror 1.0.69", - "uuid", -] - -[[package]] -name = "wezterm-color-types" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" -dependencies = [ - "csscolorparser", - "deltae", - "lazy_static", - "wezterm-dynamic", -] - -[[package]] -name = "wezterm-dynamic" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" -dependencies = [ - "log", - "ordered-float", - "strsim", - "thiserror 1.0.69", - "wezterm-dynamic-derive", -] - -[[package]] -name = "wezterm-dynamic-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "wezterm-input-types" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" -dependencies = [ - "bitflags 1.3.2", - "euclid", - "lazy_static", - "serde", - "wezterm-dynamic", -] - [[package]] name = "winapi" version = "0.3.9" @@ -3864,7 +2989,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -3875,7 +3000,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -4107,7 +3232,7 @@ dependencies = [ "heck", "indexmap", "prettyplease", - "syn 2.0.114", + "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -4123,7 +3248,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.114", + "syn", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -4135,7 +3260,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags", "indexmap", "log", "serde", @@ -4182,7 +3307,7 @@ checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -4202,7 +3327,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 936e545..874f2a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,22 +22,13 @@ russh = "0.57" async-trait = "0.1" home = "=0.5.12" zeroize = { version = "1", features = ["derive"] } -hostname = "0.4" anyhow = "1.0" surge-ping = "0.8" rand = "0.8" -# TUI dependencies (optional feature) -ratatui = { version = "0.30", optional = true } -crossterm = { version = "0.29", optional = true } - [dev-dependencies] regex = "1" -[features] -default = ["tui"] -tui = ["ratatui", "crossterm"] - [build-dependencies] prost-build = "0.14" cc = "1.0" diff --git a/src/main.rs b/src/main.rs index cae8c54..0db5c4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,8 +4,6 @@ mod proto; pub mod secret; mod snmp; mod ssh; -#[cfg(feature = "tui")] -mod tui; mod version; mod websocket_client; @@ -19,45 +17,16 @@ use tokio::time::sleep; use tracing_subscriber::EnvFilter; use websocket_client::AgentClient; -fn init_logger(suppress_stdout: bool) { +fn init_logger() { // Use LOG_LEVEL env var (fall back to RUST_LOG for backwards compatibility) let filter = env::var("LOG_LEVEL") .or_else(|_| env::var("RUST_LOG")) .unwrap_or_else(|_| "info".to_string()); - let builder = tracing_subscriber::fmt() + tracing_subscriber::fmt() .with_env_filter(EnvFilter::new(&filter)) - .with_target(false); - - if suppress_stdout { - // Route to sink when TUI is active (using closure to create MakeWriter) - builder.with_writer(std::io::sink).init(); - } else { - builder.init(); - } -} - -/// Determine if TUI should be enabled based on CLI flags and TTY detection -#[cfg(feature = "tui")] -fn should_enable_tui(args: &Args) -> bool { - // If explicitly disabled, never enable - if args.no_tui { - return false; - } - - // If explicitly enabled, always enable - if let Some(explicit) = args.tui { - return explicit; - } - - // Auto-detect: check if stdout is a TTY - use std::io::IsTerminal; - std::io::stdout().is_terminal() -} - -#[cfg(not(feature = "tui"))] -fn should_enable_tui(_args: &Args) -> bool { - false + .with_target(false) + .init(); } /// Convert HTTP(S) URL to WebSocket URL @@ -145,14 +114,6 @@ struct Args { /// SNMPv3 priv password (for --snmpv3-test) #[arg(long, default_value = "")] snmpv3_priv_pass: String, - - /// Enable TUI mode (auto-detects TTY by default) - #[arg(long, env = "TOWEROPS_TUI")] - tui: Option, - - /// Force disable TUI even if TTY is available - #[arg(long, env = "TOWEROPS_NO_TUI", default_value_t = false)] - no_tui: bool, } fn main() { @@ -169,11 +130,8 @@ fn main() { async fn async_main() { let args = Args::parse(); - // Determine if TUI should be enabled (before initializing logger) - let tui_enabled = should_enable_tui(&args); - - // Initialize logging (suppress stdout if TUI is enabled) - init_logger(tui_enabled); + // Initialize logging + init_logger(); // Handle MikroTik test mode if args.mikrotik_test { @@ -224,58 +182,12 @@ async fn async_main() { let (shutdown_tx, shutdown_rx) = watch::channel(false); // Spawn signal handler for graceful shutdown - let shutdown_tx_clone = shutdown_tx.clone(); tokio::spawn(async move { wait_for_shutdown_signal().await; tracing::info!("Shutdown signal received, initiating graceful shutdown..."); - let _ = shutdown_tx_clone.send(true); + let _ = shutdown_tx.send(true); }); - // Setup TUI if enabled - #[cfg(feature = "tui")] - let (event_bus, _tui_handle) = if tui_enabled { - use std::sync::Mutex; - - // Get hostname for TUI state - let hostname = hostname::get() - .ok() - .and_then(|h| h.into_string().ok()) - .unwrap_or_else(|| "unknown".to_string()); - - // Create event bus and shared state - let event_bus = tui::EventBus::new(100); - let agent_state = Arc::new(Mutex::new(tui::AgentState::new( - hostname, - version::current_version().to_string(), - ))); - - // Spawn TUI task - match tui::TuiApp::new(agent_state.clone(), event_bus.subscribe()) { - Ok(mut tui_app) => { - let shutdown_rx_clone = shutdown_rx.clone(); - let tui_handle = tokio::spawn(async move { - if let Err(e) = tui_app.run(shutdown_rx_clone).await { - eprintln!("TUI task failed: {}", e); - } - // When TUI exits (user presses 'q'), trigger shutdown - let _ = shutdown_tx.send(true); - }); - - (Some(event_bus), Some(tui_handle)) - } - Err(e) => { - eprintln!("Failed to initialize TUI: {}", e); - eprintln!("Falling back to log mode"); - (None, None) - } - } - } else { - (None, None) - }; - - #[cfg(not(feature = "tui"))] - let event_bus: Option<()> = None; - // Retry loop with exponential backoff let mut retry_delay = Duration::from_secs(1); let max_retry_delay = Duration::from_secs(60); @@ -305,26 +217,6 @@ async fn async_main() { } // Connect to Towerops server via WebSocket - #[cfg(feature = "tui")] - let mut client = match AgentClient::connect(&ws_url, &token, event_bus.clone()).await { - Ok(client) => { - tracing::info!("Successfully connected to server"); - // Mark as connected for health check - connected.store(true, Ordering::Relaxed); - // Reset retry delay on successful connection - retry_delay = Duration::from_secs(1); - attempt = 0; - client - } - Err(e) => { - tracing::error!("Failed to connect to server: {}", e); - // Mark as disconnected for health check - connected.store(false, Ordering::Relaxed); - continue; - } - }; - - #[cfg(not(feature = "tui"))] let mut client = match AgentClient::connect(&ws_url, &token).await { Ok(client) => { tracing::info!("Successfully connected to server"); diff --git a/src/tui/app.rs b/src/tui/app.rs deleted file mode 100644 index b9eeeb6..0000000 --- a/src/tui/app.rs +++ /dev/null @@ -1,150 +0,0 @@ -use std::io::{self, Stdout}; -use std::sync::{Arc, Mutex}; -use std::time::Duration; - -use crossterm::{ - event::{self, Event, KeyCode, KeyEvent}, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use ratatui::{backend::CrosstermBackend, Terminal}; -use tokio::sync::{broadcast, watch}; -use tokio::time::interval; - -use super::events::AgentEvent; -use super::state::AgentState; -use super::ui; - -pub struct TuiApp { - state: Arc>, - event_rx: broadcast::Receiver, - terminal: Terminal>, - scroll_offset: usize, -} - -impl TuiApp { - pub fn new( - state: Arc>, - event_rx: broadcast::Receiver, - ) -> anyhow::Result { - // Setup terminal - enable_raw_mode()?; - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen)?; - let backend = CrosstermBackend::new(stdout); - let terminal = Terminal::new(backend)?; - - Ok(Self { - state, - event_rx, - terminal, - scroll_offset: 0, - }) - } - - pub async fn run(&mut self, mut shutdown_rx: watch::Receiver) -> anyhow::Result<()> { - let mut tick_interval = interval(Duration::from_millis(100)); // 10 FPS - - loop { - tokio::select! { - // Check for shutdown signal - _ = shutdown_rx.changed() => { - break; - } - - // Handle agent events - result = self.event_rx.recv() => { - match result { - Ok(event) => { - let mut state = self.state.lock().unwrap(); - state.apply_event(&event); - } - Err(broadcast::error::RecvError::Lagged(skipped)) => { - tracing::warn!("TUI lagged behind, skipped {} events", skipped); - } - Err(broadcast::error::RecvError::Closed) => { - break; - } - } - } - - // Render tick - _ = tick_interval.tick() => { - self.render()?; - } - - // Handle keyboard input (non-blocking) - _ = tokio::time::sleep(Duration::from_millis(50)) => { - if event::poll(Duration::from_millis(0))? { - if let Event::Key(key) = event::read()? { - if self.handle_key(key) { - break; // User pressed 'q' to quit - } - } - } - } - } - } - - self.cleanup()?; - Ok(()) - } - - fn render(&mut self) -> anyhow::Result<()> { - let state = self.state.lock().unwrap().clone(); - let scroll_offset = self.scroll_offset; - - self.terminal.draw(|f| { - ui::render(f, &state, scroll_offset); - })?; - - Ok(()) - } - - fn handle_key(&mut self, key: KeyEvent) -> bool { - match key.code { - KeyCode::Char('q') => { - return true; // Signal to quit - } - KeyCode::Up => { - self.scroll_offset = self.scroll_offset.saturating_add(1); - } - KeyCode::Down => { - self.scroll_offset = self.scroll_offset.saturating_sub(1); - } - KeyCode::PageUp => { - self.scroll_offset = self.scroll_offset.saturating_add(10); - } - KeyCode::PageDown => { - self.scroll_offset = self.scroll_offset.saturating_sub(10); - } - KeyCode::Home => { - // Go to end (most recent events) - self.scroll_offset = 0; - } - KeyCode::End => { - // Go to beginning (oldest events) - let state = self.state.lock().unwrap(); - self.scroll_offset = state.recent_events.len().saturating_sub(1); - } - _ => {} - } - false - } - - fn cleanup(&mut self) -> anyhow::Result<()> { - disable_raw_mode()?; - execute!(self.terminal.backend_mut(), LeaveAlternateScreen,)?; - self.terminal.show_cursor()?; - Ok(()) - } -} - -impl Drop for TuiApp { - fn drop(&mut self) { - // Ensure terminal is restored even on panic - let _ = disable_raw_mode(); - let _ = execute!(self.terminal.backend_mut(), LeaveAlternateScreen,); - let _ = self.terminal.show_cursor(); - } -} diff --git a/src/tui/events.rs b/src/tui/events.rs deleted file mode 100644 index a0d6012..0000000 --- a/src/tui/events.rs +++ /dev/null @@ -1,72 +0,0 @@ -use tokio::sync::broadcast; - -#[derive(Debug, Clone)] -pub enum AgentEvent { - Connected { - agent_id: String, - }, - Disconnected, - JobReceived { - job_id: String, - device_id: String, - job_type: String, - }, - JobCompleted { - job_id: String, - device_id: String, - duration_ms: u64, - }, - JobFailed { - job_id: String, - device_id: String, - error: String, - }, - SnmpResultSent { - device_id: String, - oid_count: usize, - }, - MikrotikResultSent { - device_id: String, - sentence_count: usize, - }, - MonitoringCheckSent { - device_id: String, - status: String, - }, - PollerCreated { - device_ip: String, - total_count: usize, - }, - PollerRemoved { - device_ip: String, - total_count: usize, - }, - HeartbeatSent, - PhxHeartbeatSent, - Error { - message: String, - }, -} - -#[derive(Clone)] -pub struct EventBus { - tx: broadcast::Sender, -} - -impl EventBus { - pub fn new(capacity: usize) -> Self { - let (tx, _) = broadcast::channel(capacity); - Self { tx } - } - - pub fn subscribe(&self) -> broadcast::Receiver { - self.tx.subscribe() - } - - pub fn send( - &self, - event: AgentEvent, - ) -> Result> { - self.tx.send(event) - } -} diff --git a/src/tui/mod.rs b/src/tui/mod.rs deleted file mode 100644 index 62510c7..0000000 --- a/src/tui/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod app; -mod events; -mod state; -mod ui; - -pub use app::TuiApp; -pub use events::{AgentEvent, EventBus}; -pub use state::AgentState; diff --git a/src/tui/state.rs b/src/tui/state.rs deleted file mode 100644 index d7e3341..0000000 --- a/src/tui/state.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::collections::VecDeque; -use std::time::Instant; - -use super::events::AgentEvent; - -#[derive(Clone)] -pub struct AgentState { - // Connection - pub connected: bool, - pub agent_id: String, - - // System info - pub hostname: String, - pub version: String, - pub started_at: Instant, - - // Active jobs - pub active_pollers: usize, - pub active_devices: Vec, - - // Event log (ring buffer, last 100 events) - pub recent_events: VecDeque<(Instant, String)>, - - // Statistics - pub stats: Stats, -} - -#[derive(Clone, Default)] -pub struct Stats { - pub jobs_received: u64, - pub snmp_results_sent: u64, - pub mikrotik_results_sent: u64, - pub heartbeats_sent: u64, - pub errors: u64, - pub last_heartbeat_at: Option, -} - -impl AgentState { - pub fn new(hostname: String, version: String) -> Self { - Self { - connected: false, - agent_id: String::new(), - hostname, - version, - started_at: Instant::now(), - active_pollers: 0, - active_devices: Vec::new(), - recent_events: VecDeque::with_capacity(100), - stats: Stats::default(), - } - } - - pub fn apply_event(&mut self, event: &AgentEvent) { - let now = Instant::now(); - let event_msg = match event { - AgentEvent::Connected { agent_id } => { - self.connected = true; - self.agent_id = agent_id.clone(); - format!("Connected to server (agent_id: {})", agent_id) - } - AgentEvent::Disconnected => { - self.connected = false; - "Disconnected from server".to_string() - } - AgentEvent::JobReceived { - job_id, - device_id, - job_type, - } => { - self.stats.jobs_received += 1; - format!("Job received: {} ({} - {})", job_id, device_id, job_type) - } - AgentEvent::JobCompleted { - job_id, - device_id, - duration_ms, - } => { - format!( - "Job completed: {} ({}) in {}ms", - job_id, device_id, duration_ms - ) - } - AgentEvent::JobFailed { - job_id, - device_id, - error, - } => { - self.stats.errors += 1; - format!("Job failed: {} ({}) - {}", job_id, device_id, error) - } - AgentEvent::SnmpResultSent { - device_id, - oid_count, - } => { - self.stats.snmp_results_sent += 1; - format!("SNMP result sent for {} ({} OIDs)", device_id, oid_count) - } - AgentEvent::MikrotikResultSent { - device_id, - sentence_count, - } => { - self.stats.mikrotik_results_sent += 1; - format!( - "MikroTik result sent for {} ({} sentences)", - device_id, sentence_count - ) - } - AgentEvent::MonitoringCheckSent { device_id, status } => { - format!( - "Monitoring check sent for {} (status: {})", - device_id, status - ) - } - AgentEvent::PollerCreated { - device_ip, - total_count, - } => { - self.active_pollers = *total_count; - if !self.active_devices.contains(device_ip) { - self.active_devices.push(device_ip.clone()); - } - format!( - "Poller created for {} ({} total pollers)", - device_ip, total_count - ) - } - AgentEvent::PollerRemoved { - device_ip, - total_count, - } => { - self.active_pollers = *total_count; - self.active_devices.retain(|d| d != device_ip); - format!( - "Poller removed for {} ({} total pollers)", - device_ip, total_count - ) - } - AgentEvent::HeartbeatSent => { - self.stats.heartbeats_sent += 1; - self.stats.last_heartbeat_at = Some(now); - "Heartbeat sent".to_string() - } - AgentEvent::PhxHeartbeatSent => "Phoenix heartbeat sent".to_string(), - AgentEvent::Error { message } => { - self.stats.errors += 1; - format!("Error: {}", message) - } - }; - - // Add event to ring buffer (keep last 100) - if self.recent_events.len() >= 100 { - self.recent_events.pop_front(); - } - self.recent_events.push_back((now, event_msg)); - } - - pub fn uptime_seconds(&self) -> u64 { - self.started_at.elapsed().as_secs() - } - - pub fn format_uptime(&self) -> String { - let seconds = self.uptime_seconds(); - let hours = seconds / 3600; - let minutes = (seconds % 3600) / 60; - let secs = seconds % 60; - format!("{}h {}m {}s", hours, minutes, secs) - } - - pub fn last_heartbeat_ago(&self) -> Option { - self.stats.last_heartbeat_at.map(|t| t.elapsed().as_secs()) - } -} diff --git a/src/tui/ui.rs b/src/tui/ui.rs deleted file mode 100644 index 091b475..0000000 --- a/src/tui/ui.rs +++ /dev/null @@ -1,194 +0,0 @@ -use ratatui::{ - layout::{Constraint, Direction, Layout, Rect}, - style::{Color, Modifier, Style}, - text::{Line, Span}, - widgets::{Block, Borders, List, ListItem, Paragraph}, - Frame, -}; - -use super::state::AgentState; - -pub fn render(f: &mut Frame, state: &AgentState, scroll_offset: usize) { - let chunks = Layout::default() - .direction(Direction::Vertical) - .constraints([ - Constraint::Length(3), // Header - Constraint::Length(3), // Stats - Constraint::Length(8), // Devices - Constraint::Min(0), // Events log - ]) - .split(f.area()); - - render_header(f, chunks[0], state); - render_stats(f, chunks[1], state); - render_devices(f, chunks[2], state); - render_events(f, chunks[3], state, scroll_offset); -} - -fn render_header(f: &mut Frame, area: Rect, state: &AgentState) { - let status_color = if state.connected { - Color::Green - } else { - Color::Red - }; - - let status_text = if state.connected { - "Connected" - } else { - "Disconnected" - }; - - let version_str = format!(" | v{}", state.version); - let uptime_str = format!(" | Uptime: {}", state.format_uptime()); - - let header_lines = vec![ - Line::from(vec![ - Span::raw("Status: "), - Span::styled( - status_text, - Style::default() - .fg(status_color) - .add_modifier(Modifier::BOLD), - ), - Span::raw(" | Agent ID: "), - Span::styled(&state.agent_id, Style::default().fg(Color::Cyan)), - Span::raw(version_str), - ]), - Line::from(vec![ - Span::raw("Hostname: "), - Span::styled(&state.hostname, Style::default().fg(Color::Yellow)), - Span::raw(uptime_str), - ]), - ]; - - let header = Paragraph::new(header_lines).block( - Block::default() - .title("Towerops Agent") - .borders(Borders::ALL), - ); - - f.render_widget(header, area); -} - -fn render_stats(f: &mut Frame, area: Rect, state: &AgentState) { - let heartbeat_ago = state - .last_heartbeat_ago() - .map(|s| format!("{}s ago", s)) - .unwrap_or_else(|| "never".to_string()); - - let heartbeat_str = format!(" | Last Heartbeat: {}", heartbeat_ago); - - let stats_lines = vec![ - Line::from(vec![ - Span::raw("Jobs: "), - Span::styled( - format!("{}", state.stats.jobs_received), - Style::default().fg(Color::Cyan), - ), - Span::raw(" | SNMP: "), - Span::styled( - format!("{}", state.stats.snmp_results_sent), - Style::default().fg(Color::Green), - ), - Span::raw(" | MikroTik: "), - Span::styled( - format!("{}", state.stats.mikrotik_results_sent), - Style::default().fg(Color::Green), - ), - Span::raw(" | Errors: "), - Span::styled( - format!("{}", state.stats.errors), - Style::default().fg(if state.stats.errors > 0 { - Color::Red - } else { - Color::White - }), - ), - ]), - Line::from(vec![ - Span::raw("Active Pollers: "), - Span::styled( - format!("{}", state.active_pollers), - Style::default().fg(Color::Yellow), - ), - Span::raw(heartbeat_str), - ]), - ]; - - let stats = Paragraph::new(stats_lines) - .block(Block::default().title("Statistics").borders(Borders::ALL)); - - f.render_widget(stats, area); -} - -fn render_devices(f: &mut Frame, area: Rect, state: &AgentState) { - let device_items: Vec = state - .active_devices - .iter() - .take(10) - .map(|device| { - ListItem::new(Line::from(vec![ - Span::raw("• "), - Span::styled(device, Style::default().fg(Color::Cyan)), - ])) - }) - .collect(); - - let more_count = state.active_devices.len().saturating_sub(10); - let title = if more_count > 0 { - format!("Active Devices ({} more)", more_count) - } else { - "Active Devices".to_string() - }; - - let devices = - List::new(device_items).block(Block::default().title(title).borders(Borders::ALL)); - - f.render_widget(devices, area); -} - -fn render_events(f: &mut Frame, area: Rect, state: &AgentState, scroll_offset: usize) { - let event_items: Vec = state - .recent_events - .iter() - .rev() - .skip(scroll_offset) - .take(area.height.saturating_sub(2) as usize) - .map(|(timestamp, message)| { - let elapsed = timestamp.elapsed().as_secs(); - let time_str = if elapsed < 60 { - format!("{}s ago", elapsed) - } else if elapsed < 3600 { - format!("{}m ago", elapsed / 60) - } else { - format!("{}h ago", elapsed / 3600) - }; - - let color = if message.contains("Error") || message.contains("failed") { - Color::Red - } else if message.contains("sent") || message.contains("completed") { - Color::Green - } else if message.contains("received") { - Color::Yellow - } else { - Color::White - }; - - ListItem::new(Line::from(vec![ - Span::styled( - format!("[{}] ", time_str), - Style::default().fg(Color::DarkGray), - ), - Span::styled(message, Style::default().fg(color)), - ])) - }) - .collect(); - - let events = List::new(event_items).block( - Block::default() - .title("Recent Events (Press 'q' to quit, ↑/↓ to scroll)") - .borders(Borders::ALL), - ); - - f.render_widget(events, area); -} diff --git a/src/websocket_client.rs b/src/websocket_client.rs index 7bb43e9..82bb523 100644 --- a/src/websocket_client.rs +++ b/src/websocket_client.rs @@ -69,9 +69,6 @@ pub struct AgentClient { phx_heartbeat_ref: u64, /// Cached hostname (computed once at startup, avoids blocking /proc reads) cached_hostname: String, - /// Optional event bus for TUI updates - #[cfg(feature = "tui")] - event_bus: Option, } impl AgentClient { @@ -80,124 +77,7 @@ impl AgentClient { /// # Arguments /// * `url` - Server URL (e.g., "wss://towerops.net") /// * `token` - Agent authentication token - /// * `event_bus` - Optional event bus for TUI updates - /// - /// # Example - /// ```no_run - /// let client = AgentClient::connect("wss://towerops.net", "token123", None).await?; - /// ``` - #[cfg(feature = "tui")] - pub async fn connect( - url: &str, - token: &SecretString, - event_bus: Option, - ) -> Result { - Self::connect_internal(url, token, event_bus).await - } - - #[cfg(not(feature = "tui"))] pub async fn connect(url: &str, token: &SecretString) -> Result { - Self::connect_internal(url, token).await - } - - #[cfg(feature = "tui")] - async fn connect_internal( - url: &str, - token: &SecretString, - event_bus: Option, - ) -> Result { - // Strip trailing slash from base URL to avoid double slashes - let base_url = url.trim_end_matches('/'); - let ws_url = format!("{}/socket/agent/websocket", base_url); - tracing::info!( - "Connecting to WebSocket: {} (timeout: {}s)", - ws_url, - CONNECTION_TIMEOUT.as_secs() - ); - - // Wrap connection in timeout to avoid hanging indefinitely on bad network - let (ws_stream, _) = match timeout(CONNECTION_TIMEOUT, connect_async(&ws_url)).await { - Ok(Ok(result)) => result, - Ok(Err(e)) => { - tracing::error!("WebSocket connection failed: {}", e); - return Err(format!("Failed to connect to WebSocket: {}", e).into()); - } - Err(_) => { - tracing::error!( - "WebSocket connection timed out after {}s", - CONNECTION_TIMEOUT.as_secs() - ); - return Err(format!( - "Connection timed out after {}s", - CONNECTION_TIMEOUT.as_secs() - ) - .into()); - } - }; - - tracing::info!("Connected to Towerops server at {}", url); - - let agent_id = generate_agent_id(); - let (result_tx, result_rx) = mpsc::channel(RESULT_CHANNEL_CAPACITY); - let (mikrotik_result_tx, mikrotik_result_rx) = mpsc::channel(RESULT_CHANNEL_CAPACITY); - let (credential_test_tx, credential_test_rx) = mpsc::channel(RESULT_CHANNEL_CAPACITY); - let (monitoring_check_tx, monitoring_check_rx) = mpsc::channel(RESULT_CHANNEL_CAPACITY); - - // Split the WebSocket stream so reads and writes can proceed concurrently. - // The write half is owned by a dedicated writer task. - let (ws_write, ws_read) = ws_stream.split(); - let (ws_write_tx, ws_write_rx) = mpsc::channel::(WS_WRITE_CHANNEL_CAPACITY); - - tokio::spawn(ws_writer_task(ws_write, ws_write_rx)); - - // Join Phoenix channel with token in payload - let join_msg = PhoenixMessage { - topic: format!("agent:{}", agent_id), - event: "phx_join".to_string(), - payload: serde_json::json!({"token": token.expose()}), - reference: Some("1".to_string()), - }; - - let join_text = serde_json::to_string(&join_msg)?; - ws_write_tx - .send(WsMessage::Text(join_text.into())) - .await - .map_err(|e| format!("Failed to send join message: {}", e))?; - tracing::info!( - "Sent channel join request with token for agent:{}", - agent_id - ); - - let client = Self { - ws_read, - ws_write_tx, - agent_id: agent_id.clone(), - result_tx, - result_rx, - mikrotik_result_tx, - mikrotik_result_rx, - credential_test_tx, - credential_test_rx, - monitoring_check_tx, - monitoring_check_rx, - poller_registry: PollerRegistry::new(), - phx_heartbeat_ref: 0, - cached_hostname: get_hostname(), - #[cfg(feature = "tui")] - event_bus: event_bus.clone(), - }; - - // Publish connected event - #[cfg(feature = "tui")] - client.publish_event(crate::tui::AgentEvent::Connected { - agent_id: agent_id.clone(), - }); - - Ok(client) - } - - #[cfg(not(feature = "tui"))] - async fn connect_internal(url: &str, token: &SecretString) -> Result { // Strip trailing slash from base URL to avoid double slashes let base_url = url.trim_end_matches('/'); let ws_url = format!("{}/socket/agent/websocket", base_url); @@ -278,19 +158,6 @@ impl AgentClient { }) } - /// Publish an event to the TUI event bus (if enabled). - #[cfg(feature = "tui")] - fn publish_event(&self, event: crate::tui::AgentEvent) { - if let Some(bus) = &self.event_bus { - let _ = bus.send(event); // Fire-and-forget - } - } - - #[cfg(not(feature = "tui"))] - fn publish_event(&self, _event: ()) { - // No-op when TUI is disabled - } - /// Main event loop for agent operation. /// /// Handles: @@ -330,22 +197,16 @@ impl AgentClient { } Some(Ok(WsMessage::Close(_))) => { tracing::info!("Server closed connection"); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Disconnected); self.poller_registry.shutdown_all(); break Ok(()); } Some(Err(e)) => { tracing::error!("WebSocket error: {}", e); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Disconnected); self.poller_registry.shutdown_all(); break Err(e.into()); } None => { tracing::info!("Connection closed"); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Disconnected); self.poller_registry.shutdown_all(); break Ok(()); } @@ -355,29 +216,15 @@ impl AgentClient { // Receive SNMP results from job tasks Some(snmp_result) = self.result_rx.recv() => { - #[cfg(feature = "tui")] - let device_id = snmp_result.device_id.clone(); - if let Err(e) = self.send_snmp_result(snmp_result).await { tracing::error!("Error sending SNMP result: {}", e); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Error { - message: format!("SNMP result send failed for {}: {}", device_id, e), - }); } } // Receive MikroTik results from job tasks Some(mikrotik_result) = self.mikrotik_result_rx.recv() => { - #[cfg(feature = "tui")] - let device_id = mikrotik_result.device_id.clone(); - if let Err(e) = self.send_mikrotik_result(mikrotik_result).await { tracing::error!("Error sending MikroTik result: {}", e); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Error { - message: format!("MikroTik result send failed for {}: {}", device_id, e), - }); } } @@ -390,15 +237,8 @@ impl AgentClient { // Receive monitoring check results from job tasks Some(monitoring_check) = self.monitoring_check_rx.recv() => { - #[cfg(feature = "tui")] - let device_id = monitoring_check.device_id.clone(); - if let Err(e) = self.send_monitoring_check(monitoring_check).await { tracing::error!("Error sending monitoring check: {}", e); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Error { - message: format!("Monitoring check send failed for {}: {}", device_id, e), - }); } } @@ -406,13 +246,6 @@ impl AgentClient { _ = heartbeat_interval.tick() => { if let Err(e) = self.send_heartbeat().await { tracing::error!("Error sending heartbeat: {}", e); - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::Error { - message: format!("Heartbeat failed: {}", e), - }); - } else { - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::HeartbeatSent); } // Log active poller count let count = self.poller_registry.count(); @@ -425,9 +258,6 @@ impl AgentClient { _ = phx_heartbeat_interval.tick() => { if let Err(e) = self.send_phx_heartbeat().await { tracing::error!("Error sending Phoenix heartbeat: {}", e); - } else { - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::PhxHeartbeatSent); } } } @@ -493,17 +323,7 @@ impl AgentClient { "Removing poller for device no longer in job list: {}", device_id ); - let device_ip = self.poller_registry.remove(&device_id); - - #[cfg(feature = "tui")] - if let Some(ref bus) = self.event_bus { - if let Some(ip) = device_ip { - let _ = bus.send(crate::tui::AgentEvent::PollerRemoved { - device_ip: ip, - total_count: self.poller_registry.count(), - }); - } - } + self.poller_registry.remove(&device_id); } } @@ -511,123 +331,34 @@ impl AgentClient { let job_type = JobType::try_from(job.job_type).unwrap_or(JobType::Poll); tracing::info!("Executing job: {} (type: {:?})", job.job_id, job_type); - #[cfg(feature = "tui")] - { - if let Some(ref bus) = self.event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobReceived { - job_id: job.job_id.clone(), - device_id: job.device_id.clone(), - job_type: format!("{:?}", job_type), - }); - } - } - match job_type { JobType::Mikrotik => { // Execute MikroTik API job let mikrotik_result_tx = self.mikrotik_result_tx.clone(); - #[cfg(feature = "tui")] - let event_bus = self.event_bus.clone(); - let job_id = job.job_id.clone(); - let device_id = job.device_id.clone(); tokio::spawn(async move { - let start_time = std::time::Instant::now(); - match execute_mikrotik_job(job, mikrotik_result_tx).await { - Ok(_) => - { - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobCompleted { - job_id, - device_id, - duration_ms: start_time.elapsed().as_millis() as u64, - }); - } - } - Err(e) => { - tracing::error!("MikroTik job execution failed: {}", e); - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobFailed { - job_id, - device_id, - error: e.to_string(), - }); - } - } + if let Err(e) = execute_mikrotik_job(job, mikrotik_result_tx).await { + tracing::error!("MikroTik job execution failed: {}", e); } }); } JobType::TestCredentials => { // Execute credential test let credential_test_tx = self.credential_test_tx.clone(); - #[cfg(feature = "tui")] - let event_bus = self.event_bus.clone(); - let job_id = job.job_id.clone(); - let device_id = job.device_id.clone(); tokio::spawn(async move { - let start_time = std::time::Instant::now(); - match execute_credential_test(job, credential_test_tx).await { - Ok(_) => - { - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobCompleted { - job_id, - device_id, - duration_ms: start_time.elapsed().as_millis() as u64, - }); - } - } - Err(e) => { - tracing::error!("Credential test execution failed: {}", e); - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobFailed { - job_id, - device_id, - error: e.to_string(), - }); - } - } + if let Err(e) = execute_credential_test(job, credential_test_tx).await { + tracing::error!("Credential test execution failed: {}", e); } }); } JobType::Ping => { // Execute ICMP ping health check let monitoring_check_tx = self.monitoring_check_tx.clone(); - #[cfg(feature = "tui")] - let event_bus = self.event_bus.clone(); - let job_id = job.job_id.clone(); - let device_id = job.device_id.clone(); tokio::spawn(async move { - let start_time = std::time::Instant::now(); - match execute_ping_job(job, monitoring_check_tx).await { - Ok(_) => - { - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobCompleted { - job_id, - device_id, - duration_ms: start_time.elapsed().as_millis() as u64, - }); - } - } - Err(e) => { - tracing::error!("Ping job execution failed: {}", e); - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobFailed { - job_id, - device_id, - error: e.to_string(), - }); - } - } + if let Err(e) = execute_ping_job(job, monitoring_check_tx).await { + tracing::error!("Ping job execution failed: {}", e); } }); } @@ -635,45 +366,10 @@ impl AgentClient { // Execute SNMP job (discovery or polling) let result_tx = self.result_tx.clone(); let poller_registry = self.poller_registry.clone(); - #[cfg(feature = "tui")] - let event_bus = self.event_bus.clone(); - #[cfg(feature = "tui")] - let event_bus_for_task = event_bus.clone(); - let job_id = job.job_id.clone(); - let device_id = job.device_id.clone(); tokio::spawn(async move { - let start_time = std::time::Instant::now(); - #[cfg(feature = "tui")] - let result = - execute_snmp_job(job, result_tx, poller_registry, event_bus_for_task) - .await; - #[cfg(not(feature = "tui"))] - let result = execute_snmp_job(job, result_tx, poller_registry).await; - - match result { - Ok(_) => - { - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobCompleted { - job_id, - device_id, - duration_ms: start_time.elapsed().as_millis() as u64, - }); - } - } - Err(e) => { - tracing::error!("SNMP job execution failed: {}", e); - #[cfg(feature = "tui")] - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::JobFailed { - job_id, - device_id, - error: e.to_string(), - }); - } - } + if let Err(e) = execute_snmp_job(job, result_tx, poller_registry).await { + tracing::error!("SNMP job execution failed: {}", e); } }); } @@ -757,13 +453,6 @@ impl AgentClient { .map_err(|e| format!("Writer task closed: {}", e))?; tracing::debug!("Sent SNMP result for device {}", result.device_id); - - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::SnmpResultSent { - device_id: result.device_id.clone(), - oid_count: result.oid_values.len(), - }); - Ok(()) } @@ -789,13 +478,6 @@ impl AgentClient { result.device_id, result.job_id ); - - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::MikrotikResultSent { - device_id: result.device_id.clone(), - sentence_count: result.sentences.len(), - }); - Ok(()) } @@ -846,13 +528,6 @@ impl AgentClient { result.device_id, result.status ); - - #[cfg(feature = "tui")] - self.publish_event(crate::tui::AgentEvent::MonitoringCheckSent { - device_id: result.device_id.clone(), - status: result.status.clone(), - }); - Ok(()) } } @@ -892,7 +567,6 @@ async fn execute_snmp_job( job: AgentJob, result_tx: mpsc::Sender, poller_registry: PollerRegistry, - #[cfg(feature = "tui")] event_bus: Option, ) -> Result<()> { let mut snmp_device = job.snmp_device.ok_or("Job missing SNMP device info")?; @@ -963,24 +637,8 @@ async fn execute_snmp_job( snmp_device.v3_auth_password.zeroize(); snmp_device.v3_priv_password.zeroize(); - #[cfg(feature = "tui")] - let count_before = poller_registry.count(); - let poller = poller_registry.get_or_create(job.device_id.clone(), device_config); - #[cfg(feature = "tui")] - { - let count_after = poller_registry.count(); - if count_after > count_before { - if let Some(ref bus) = event_bus { - let _ = bus.send(crate::tui::AgentEvent::PollerCreated { - device_ip: snmp_device.ip.clone(), - total_count: count_after, - }); - } - } - } - let mut oid_values: HashMap = HashMap::new(); for query in job.queries {