mobius_cli/frontend/
mod.rs1use mobius::Result;
4use mobius::protocol::FrontendBlock;
5use mobius_gateway::client::{GatewayEvents, GatewaySender};
6use mobius_gateway::wire::{ProviderInstance, ReadyPayload, SessionReadyPayload};
7
8mod bots;
9mod catalog;
10mod cloudflare_setup;
11mod dashboard;
12mod extensions;
13mod gateway;
14mod gateway_actions;
15mod headless;
16mod reinitialize;
17mod setup;
18mod terminal;
19mod theme;
20mod tui;
21
22pub use headless::run as run_headless;
23pub use terminal::terminal_text;
24
25pub use cloudflare_setup::{CloudflareInit, run as run_cloudflare_setup};
26pub use dashboard::{run as run_gateway_dashboard, run_provider as run_gateway_provider};
27pub use reinitialize::confirm as confirm_gateway_reinitialize;
28pub use setup::run_gateway_login;
29
30pub async fn run_extensions(
31 sender: GatewaySender,
32 events: GatewayEvents,
33 gateway: ReadyPayload,
34) -> Result<()> {
35 extensions::standalone(sender, events, gateway).await
36}
37
38fn block_text(block: &FrontendBlock) -> String {
39 let mut text = block.title.clone();
40 if !block.text.is_empty() {
41 if !text.is_empty() {
42 text.push('\n');
43 }
44 text.push_str(&block.text);
45 }
46 for part in &block.content.0 {
47 text.push('\n');
48 match part {
49 mobius::protocol::ContentPart::Text { text: part } => text.push_str(part),
50 mobius::protocol::ContentPart::Image { image } => text.push_str(&format!(
51 "[image] {} · {} × {} · file_id={}",
52 image.file.name, image.width, image.height, image.file.id
53 )),
54 mobius::protocol::ContentPart::File { file } => text.push_str(&format!(
55 "[file] {} · {} bytes · file_id={}",
56 file.name, file.size, file.id
57 )),
58 }
59 }
60 for file in &block.files {
61 if !text.is_empty() {
62 text.push('\n');
63 }
64 text.push_str(&format!(
65 "[file] {} · {} · {} bytes",
66 file.name, file.media_type, file.size
67 ));
68 }
69 text
70}
71
72fn provider_instance_label<'a>(
73 instances: &'a [ProviderInstance],
74 instance: &str,
75) -> Option<&'a str> {
76 instances
77 .iter()
78 .find(|entry| entry.selection.instance == instance)
79 .map(|entry| entry.label.as_str())
80}
81
82pub async fn run(
83 sender: GatewaySender,
84 events: GatewayEvents,
85 gateway: &mut ReadyPayload,
86 session: &mut SessionReadyPayload,
87 gateway_endpoint: String,
88) -> Result<(FrontendExit, GatewaySender, GatewayEvents)> {
89 let workspace = session.workspace.path.clone();
90 let catalog = catalog::UiCatalog::build(&session.contributions, &workspace)?;
91 tui::runtime::run(sender, events, gateway, session, catalog, gateway_endpoint).await
92}
93
94pub enum FrontendExit {
96 Exit,
97 Resume(String),
98 Reload,
99 Reconnect,
100}