netget/tui/
command_exec.rs1use tokio::sync::mpsc;
8
9use crate::events::UserCommand;
10use crate::state::app_state::AppState;
11
12pub async fn execute(
14 command: UserCommand,
15 state: &AppState,
16 status_tx: &mpsc::UnboundedSender<String>,
17) -> Vec<String> {
18 match command {
19 UserCommand::Status => status_report(state).await,
20 UserCommand::Manage => {
21 let mut lines = vec![
22 "The list on the left is the management surface (Tab reaches it):".to_string(),
23 " a start a server A start a client e edit config".to_string(),
24 " r rules m cycle the driver x stop / remove".to_string(),
25 " c connect a client to a server n send through a client"
26 .to_string(),
27 ];
28 lines.extend(status_report(state).await);
29 lines
30 }
31 UserCommand::ShowStability => crate::protocol::stability_report(None),
32 UserCommand::ShowUsage => {
33 let (input, output, calls) = state.get_llm_stats().await;
34 vec![
35 format!("LLM calls: {calls}"),
36 format!("Input tokens: {input}"),
37 format!("Output tokens: {output}"),
38 ]
39 }
40 UserCommand::ShowEnvironment => environment_report(state).await,
41 UserCommand::ShowWebSearch => {
42 vec![format!(
43 "Web search: {:?}",
44 state.get_web_search_mode().await
45 )]
46 }
47 UserCommand::SetWebSearch { mode } => {
48 state.set_web_search_mode(mode).await;
49 vec![format!("Web search set to {mode:?}")]
50 }
51 UserCommand::ShowEventHandler => {
52 vec![format!(
53 "Handler mode: {:?}",
54 state.get_event_handler_mode().await
55 )]
56 }
57 UserCommand::SetEventHandler { mode } => {
58 state.set_event_handler_mode(mode).await;
59 vec![format!("Handler mode set to {mode:?}")]
60 }
61 UserCommand::ShowDocs { protocol } => match protocol {
62 Some(name) => match crate::protocol::server_registry::registry().resolve(&name) {
63 Ok(proto) => vec![
64 format!("{} — {}", proto.protocol_name(), proto.description()),
65 format!("maturity: {}", proto.metadata().summary()),
66 ],
67 Err(e) => vec![format!("{e}")],
68 },
69 None => vec!["Usage: /docs <protocol> — or press d on an instance".to_string()],
70 },
71 UserCommand::ShowBackend => {
72 vec![format!("Backend URL: {}", state.get_ollama_url().await)]
73 }
74 UserCommand::TestOutput { count } => {
75 for i in 1..=count {
76 let _ = status_tx.send(format!("[INFO] test output line {i}/{count}"));
77 }
78 Vec::new()
79 }
80 UserCommand::SetFooterStatus { message } => match message {
81 Some(m) => vec![format!("Status note: {m}")],
82 None => vec!["Status note cleared".to_string()],
83 },
84 other => vec![format!("'{other:?}' is not available in the dashboard yet")],
85 }
86}
87
88async fn status_report(state: &AppState) -> Vec<String> {
89 let servers = state.get_all_servers().await;
90 let clients = state.get_all_clients().await;
91 let mut lines = vec![format!(
92 "{} server(s), {} client(s)",
93 servers.len(),
94 clients.len()
95 )];
96 for s in servers {
97 lines.push(format!(
98 " server #{} {} :{} {} — {} conn",
99 s.id.as_u32(),
100 s.protocol_name,
101 s.port,
102 s.status,
103 s.connections.len()
104 ));
105 }
106 for c in clients {
107 lines.push(format!(
108 " client #{} {} → {} {}",
109 c.id.as_u32(),
110 c.protocol_name,
111 c.remote_addr,
112 c.status
113 ));
114 }
115 lines
116}
117
118async fn environment_report(state: &AppState) -> Vec<String> {
119 let env = state.get_scripting_env().await;
120 let caps = state.get_system_capabilities().await;
121 let mut lines = vec!["Scripting interpreters:".to_string()];
122 for language in [
123 crate::scripting::ScriptLanguage::Python,
124 crate::scripting::ScriptLanguage::JavaScript,
125 crate::scripting::ScriptLanguage::Go,
126 crate::scripting::ScriptLanguage::Perl,
127 ] {
128 lines.push(format!(
129 " {:<11} {}",
130 language.as_str(),
131 if env.is_available(language) {
132 "available"
133 } else {
134 "not installed"
135 }
136 ));
137 }
138 lines.push(String::new());
139 lines.push("Privileges:".to_string());
140 lines.push(format!(" root: {}", caps.is_root));
141 lines.push(format!(
142 " privileged port: {}",
143 caps.can_bind_privileged_ports
144 ));
145 lines.push(format!(" raw sockets: {}", caps.has_raw_socket_access));
146 lines.push(format!(
147 " packet capture: {}",
148 caps.has_packet_capture_access
149 ));
150 lines
151}