mirror of
https://github.com/block/buzz.git
synced 2026-11-08 02:11:36 +00:00
74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
//! Bridges mesh-llm's process-global output sink onto Tauri events so the
|
|
//! frontend can render model-download progress (bytes, percent) instead of a
|
|
//! frozen, greyed-out toggle. Same pattern as mesh-console's ConsoleSink.
|
|
|
|
use std::io;
|
|
use std::sync::Arc;
|
|
|
|
use serde::Serialize;
|
|
use tauri::{AppHandle, Emitter};
|
|
|
|
use mesh_llm_events::{ConsoleSessionMode, ModelProgressStatus, OutputEvent, OutputSink};
|
|
|
|
/// Tauri event name the frontend subscribes to.
|
|
pub const MESH_DOWNLOAD_PROGRESS_EVENT: &str = "mesh-download-progress";
|
|
|
|
#[derive(Debug, Clone, Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
pub struct MeshDownloadProgress {
|
|
/// Model (or runtime) label being downloaded.
|
|
pub label: String,
|
|
/// Specific file within the download, when known.
|
|
pub file: Option<String>,
|
|
pub downloaded_bytes: Option<u64>,
|
|
pub total_bytes: Option<u64>,
|
|
/// preparing | downloading | done — mirrors ModelProgressStatus.
|
|
pub status: &'static str,
|
|
pub done: bool,
|
|
}
|
|
|
|
struct TauriProgressSink {
|
|
app: AppHandle,
|
|
}
|
|
|
|
impl OutputSink for TauriProgressSink {
|
|
fn emit_event(&self, event: OutputEvent) -> io::Result<()> {
|
|
if let OutputEvent::ModelDownloadProgress {
|
|
label,
|
|
file,
|
|
downloaded_bytes,
|
|
total_bytes,
|
|
status,
|
|
} = event
|
|
{
|
|
let payload = MeshDownloadProgress {
|
|
label,
|
|
file,
|
|
downloaded_bytes,
|
|
total_bytes,
|
|
status: match status {
|
|
ModelProgressStatus::Ensuring => "preparing",
|
|
ModelProgressStatus::Downloading => "downloading",
|
|
ModelProgressStatus::Ready => "done",
|
|
},
|
|
done: matches!(status, ModelProgressStatus::Ready),
|
|
};
|
|
let _ = self.app.emit(MESH_DOWNLOAD_PROGRESS_EVENT, payload);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// Byte-level ModelDownloadProgress only flows through the sink when the
|
|
/// host-runtime believes an interactive dashboard is attached; otherwise
|
|
/// it draws ANSI progress bars on stderr. Our UI *is* the dashboard.
|
|
fn console_session_mode(&self) -> Option<ConsoleSessionMode> {
|
|
Some(ConsoleSessionMode::InteractiveDashboard)
|
|
}
|
|
}
|
|
|
|
/// Install (or replace) the process-global progress sink pointed at this app.
|
|
/// Idempotent in effect — replacing with an equivalent sink is harmless.
|
|
pub fn install_progress_sink(app: &AppHandle) {
|
|
mesh_llm_events::set_output_sink(Arc::new(TauriProgressSink { app: app.clone() }));
|
|
}
|