Initial ForgeLM import

This commit is contained in:
Evandro Fonseca Junior committed 2026-03-29 19:10:57 -03:00
commit a392b9dc60
4296 files changed
+1212675

No files matched your search

+256
View File
@@ -0,0 +1,256 @@
pub mod config;
pub mod health;
pub mod process;
pub mod state;
pub mod types;
use std::time::Duration;
use tauri::{AppHandle, State};
use self::config::{load_runtime_config, save_runtime_config};
use self::health::wait_for_health;
use self::process::spawn_localllm;
use self::state::{
begin_lifecycle_command, block_lifecycle_command, build_snapshot, finish_lifecycle_command,
guard_start_request, guard_stop_request, refresh_process_state, requires_runtime_restart,
runtime_error,
};
use self::types::{
ConnectionMode, RuntimeConfig, RuntimeLifecycleCommand, RuntimeLifecycleOutcome,
RuntimeSnapshot, RuntimeStatus, StartPolicy,
};
pub fn get_runtime_snapshot(state: State<'_, RuntimeState>) -> Result<RuntimeSnapshot, String> {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
refresh_process_state(&mut inner);
Ok(build_snapshot(&inner))
}
pub fn save_runtime_config_command(
app: AppHandle,
state: State<'_, RuntimeState>,
config: RuntimeConfig,
) -> Result<RuntimeSnapshot, String> {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
refresh_process_state(&mut inner);
if inner.child.is_some() && requires_runtime_restart(&inner.config, &config) {
let message =
"Stop the local API before changing connection mode, model, address, or runtime sizing.";
inner.last_error = Some(runtime_error("restart_required", message));
block_lifecycle_command(&mut inner, RuntimeLifecycleCommand::Save, message);
return Ok(build_snapshot(&inner));
}
begin_lifecycle_command(&mut inner, RuntimeLifecycleCommand::Save);
if let Err(error) = save_runtime_config(&app, &config) {
inner.last_error = Some(runtime_error("save_failed", &error));
finish_lifecycle_command(
&mut inner,
RuntimeLifecycleCommand::Save,
RuntimeLifecycleOutcome::Failed,
format!("Failed to save runtime settings: {error}"),
);
return Err(error);
}
inner.config = config;
inner.last_error = None;
finish_lifecycle_command(
&mut inner,
RuntimeLifecycleCommand::Save,
RuntimeLifecycleOutcome::Succeeded,
"Runtime settings saved.",
);
Ok(build_snapshot(&inner))
}
fn start_runtime_inner(
app: &AppHandle,
state: &State<'_, RuntimeState>,
override_config: Option<RuntimeConfig>,
) -> Result<RuntimeSnapshot, String> {
let command = if override_config.is_some() {
RuntimeLifecycleCommand::SaveAndStart
} else {
RuntimeLifecycleCommand::Start
};
let config = {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
refresh_process_state(&mut inner);
if guard_start_request(&mut inner).is_err() {
return Ok(build_snapshot(&inner));
}
begin_lifecycle_command(&mut inner, command);
if let Some(config) = override_config {
if let Err(error) = save_runtime_config(app, &config) {
inner.last_error = Some(runtime_error("save_failed", &error));
finish_lifecycle_command(
&mut inner,
command,
RuntimeLifecycleOutcome::Failed,
format!("Failed to save runtime settings: {error}"),
);
return Err(error);
}
inner.config = config;
}
if inner.config.connection_mode != ConnectionMode::Local {
let message = "Switch to Local mode before starting the built-in API";
inner.last_error = Some(runtime_error("remote_mode", message));
inner.status = RuntimeStatus::Error;
finish_lifecycle_command(
&mut inner,
command,
RuntimeLifecycleOutcome::Failed,
message,
);
return Ok(build_snapshot(&inner));
}
inner.status = RuntimeStatus::Starting;
inner.last_error = None;
inner.config.clone()
};
let child = match spawn_localllm(&config) {
Ok(child) => child,
Err(message) => {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
inner.status = RuntimeStatus::Error;
inner.last_error = Some(runtime_error("spawn_failed", &message));
finish_lifecycle_command(
&mut inner,
command,
RuntimeLifecycleOutcome::Failed,
message,
);
return Ok(build_snapshot(&inner));
}
};
{
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
inner.child = Some(child);
inner.status = RuntimeStatus::Starting;
}
if wait_for_health(&config.addr, Duration::from_secs(15)) {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
inner.status = RuntimeStatus::Ready;
inner.last_error = None;
let message = if command == RuntimeLifecycleCommand::SaveAndStart {
"Runtime settings saved and local API started."
} else {
"Local API started."
};
finish_lifecycle_command(
&mut inner,
command,
RuntimeLifecycleOutcome::Succeeded,
message,
);
Ok(build_snapshot(&inner))
} else {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
if let Some(child) = inner.child.as_mut() {
let _ = child.kill();
let _ = child.wait();
}
inner.child = None;
inner.status = RuntimeStatus::Error;
let message = format!(
"Local API did not pass /health readiness on {} in time",
config.addr
);
inner.last_error = Some(runtime_error("health_timeout", &message));
finish_lifecycle_command(
&mut inner,
command,
RuntimeLifecycleOutcome::Failed,
message,
);
Ok(build_snapshot(&inner))
}
}
pub fn bootstrap_runtime(
app: AppHandle,
state: State<'_, RuntimeState>,
) -> Result<RuntimeSnapshot, String> {
let config = load_runtime_config(&app).unwrap_or_default();
let should_autostart = config.connection_mode == ConnectionMode::Local
&& config.start_policy == StartPolicy::OnAppLaunch
&& config
.model_path
.as_deref()
.map(|value| !value.trim().is_empty())
.unwrap_or(false);
{
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
inner.config = config.clone();
refresh_process_state(&mut inner);
}
if should_autostart {
start_runtime_inner(&app, &state, Some(config))
} else {
get_runtime_snapshot(state)
}
}
pub fn start_runtime(
app: AppHandle,
state: State<'_, RuntimeState>,
) -> Result<RuntimeSnapshot, String> {
start_runtime_inner(&app, &state, None)
}
pub fn stop_runtime(state: State<'_, RuntimeState>) -> Result<RuntimeSnapshot, String> {
let mut inner = state.0.lock().map_err(|e| e.to_string())?;
refresh_process_state(&mut inner);
if guard_stop_request(&mut inner).is_err() {
return Ok(build_snapshot(&inner));
}
begin_lifecycle_command(&mut inner, RuntimeLifecycleCommand::Stop);
inner.status = RuntimeStatus::Stopping;
if let Some(child) = inner.child.as_mut() {
if let Err(error) = child.kill() {
inner.status = RuntimeStatus::Error;
inner.last_error = Some(runtime_error(
"stop_failed",
format!("Failed to kill server: {error}"),
));
finish_lifecycle_command(
&mut inner,
RuntimeLifecycleCommand::Stop,
RuntimeLifecycleOutcome::Failed,
format!("Failed to stop local API: {error}"),
);
return Ok(build_snapshot(&inner));
}
let _ = child.wait();
}
inner.child = None;
inner.status = RuntimeStatus::Stopped;
inner.last_error = None;
finish_lifecycle_command(
&mut inner,
RuntimeLifecycleCommand::Stop,
RuntimeLifecycleOutcome::Succeeded,
"Local API stopped.",
);
Ok(build_snapshot(&inner))
}
pub use state::RuntimeState;