From af2737dea9fe0240bb3604747b4b4471b0936d9f Mon Sep 17 00:00:00 2001 From: Jasper Hugo Date: Tue, 13 Oct 2026 11:15:03 +0200 Subject: [PATCH] refactor(local-inference): use eredu naming without legacy aliases --- crates/goose-cli/Cargo.toml | 2 +- crates/goose-local-inference/Cargo.toml | 2 +- crates/goose-local-inference/src/backend.rs | 2 +- crates/goose-local-inference/src/eredu.rs | 8 +-- crates/goose-local-inference/src/hf_models.rs | 52 +++++++++---------- crates/goose-local-inference/src/lib.rs | 25 ++++----- .../goose-local-inference/src/management.rs | 19 +++---- .../src/tool_emulation.rs | 22 ++++---- crates/goose-providers/Cargo.toml | 2 +- crates/goose/Cargo.toml | 2 +- goose-self-test.yaml | 38 +------------- .../localInference/ModelSettingsPanel.tsx | 5 +- 12 files changed, 68 insertions(+), 111 deletions(-) diff --git a/crates/goose-cli/Cargo.toml b/crates/goose-cli/Cargo.toml index 5b66a7b4aa..122d63fe25 100644 --- a/crates/goose-cli/Cargo.toml +++ b/crates/goose-cli/Cargo.toml @@ -118,7 +118,7 @@ local-inference = ["goose/local-inference"] aws-providers = ["goose/aws-providers"] cuda = ["goose/cuda", "local-inference"] vulkan = ["goose/vulkan", "local-inference"] -mlx = ["goose/mlx", "local-inference"] +eredu = ["goose/eredu", "local-inference"] telemetry = ["goose/telemetry"] otel = ["goose/otel"] system-keyring = ["goose/system-keyring"] diff --git a/crates/goose-local-inference/Cargo.toml b/crates/goose-local-inference/Cargo.toml index 12f4cd5821..07932b19b5 100644 --- a/crates/goose-local-inference/Cargo.toml +++ b/crates/goose-local-inference/Cargo.toml @@ -15,7 +15,7 @@ workspace = true default = [] cuda = ["llama-cpp-2/cuda"] vulkan = ["llama-cpp-2/vulkan"] -mlx = [ +eredu = [ "dep:eredu", "dep:eredu-core", "dep:eredu-backend-mlx", diff --git a/crates/goose-local-inference/src/backend.rs b/crates/goose-local-inference/src/backend.rs index fa8dd14377..309fa3f13a 100644 --- a/crates/goose-local-inference/src/backend.rs +++ b/crates/goose-local-inference/src/backend.rs @@ -12,7 +12,7 @@ pub(super) trait BackendLoadedModel: Send { fn as_any_mut(&mut self) -> &mut dyn Any; } -#[cfg_attr(not(feature = "mlx"), allow(dead_code))] +#[cfg_attr(not(feature = "eredu"), allow(dead_code))] pub(super) struct LocalGenerationRequest<'a> { pub model_name: String, pub system: &'a str, diff --git a/crates/goose-local-inference/src/eredu.rs b/crates/goose-local-inference/src/eredu.rs index ed9364d78b..6419c95a04 100644 --- a/crates/goose-local-inference/src/eredu.rs +++ b/crates/goose-local-inference/src/eredu.rs @@ -89,14 +89,14 @@ pub(crate) const EREDU_BACKEND_ID: &str = "eredu"; pub(crate) fn unavailable_reason() -> Option<&'static str> { if !cfg!(all(target_os = "macos", target_arch = "aarch64")) { Some("The eredu backend in Goose requires Apple silicon macOS.") - } else if !cfg!(feature = "mlx") { - Some("Eredu support was not compiled in. Rebuild with the `mlx` feature.") + } else if !cfg!(feature = "eredu") { + Some("Eredu support was not compiled in. Rebuild with the `eredu` feature.") } else { None } } -#[cfg(all(feature = "mlx", target_os = "macos", target_arch = "aarch64"))] +#[cfg(all(feature = "eredu", target_os = "macos", target_arch = "aarch64"))] mod imp { use std::any::Any; use std::collections::HashMap; @@ -1041,7 +1041,7 @@ mod imp { } } -#[cfg(not(all(feature = "mlx", target_os = "macos", target_arch = "aarch64")))] +#[cfg(not(all(feature = "eredu", target_os = "macos", target_arch = "aarch64")))] mod imp { use super::*; use crate::backend::{BackendLoadedModel, LocalGenerationRequest, LocalInferenceBackend}; diff --git a/crates/goose-local-inference/src/hf_models.rs b/crates/goose-local-inference/src/hf_models.rs index a56f4e5468..6a0567e29a 100644 --- a/crates/goose-local-inference/src/hf_models.rs +++ b/crates/goose-local-inference/src/hf_models.rs @@ -8,15 +8,15 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; use std::sync::{Arc, Mutex}; -use crate::eredu::snapshot_files_are_complete as mlx_snapshot_files_are_complete; +use crate::eredu::snapshot_files_are_complete; use crate::huggingface_auth; const HF_DOWNLOAD_BASE: &str = "https://huggingface.co"; const LLAMACPP_BACKEND_ID: &str = "llamacpp"; -const MLX_BACKEND_ID: &str = "eredu"; +const EREDU_BACKEND_ID: &str = "eredu"; const GGUF_FORMAT: &str = "gguf"; -const MLX_FORMAT: &str = "safetensors"; -const MLX_VARIANT_ID: &str = "default"; +const SAFETENSORS_FORMAT: &str = "safetensors"; +const SAFETENSORS_VARIANT_ID: &str = "default"; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct HfModelInfo { @@ -1143,10 +1143,10 @@ mod tests { unsupported_reason: None, }; let mlx_variant = HfModelVariant { - variant_id: MLX_VARIANT_ID.to_string(), + variant_id: SAFETENSORS_VARIANT_ID.to_string(), label: "Default".to_string(), - backend_id: MLX_BACKEND_ID.to_string(), - format: MLX_FORMAT.to_string(), + backend_id: EREDU_BACKEND_ID.to_string(), + format: SAFETENSORS_FORMAT.to_string(), model_id: repo_id.clone(), download_id: repo_id.clone(), size_bytes: 8, @@ -1195,7 +1195,7 @@ mod tests { assert!(models[0] .variants .iter() - .any(|variant| variant.backend_id == MLX_BACKEND_ID)); + .any(|variant| variant.backend_id == EREDU_BACKEND_ID)); } fn sibling(filename: &str) -> RepoSibling { @@ -1258,18 +1258,18 @@ mod tests { } }); - assert!(!mlx_snapshot_files_are_complete(&cached, Some(&index))); + assert!(!snapshot_files_are_complete(&cached, Some(&index))); cached.insert("model-00002-of-00002.safetensors"); - assert!(mlx_snapshot_files_are_complete(&cached, Some(&index))); + assert!(snapshot_files_are_complete(&cached, Some(&index))); } #[test] fn mlx_snapshot_requires_every_numbered_safetensors_shard_without_an_index() { let mut cached = std::collections::HashSet::from(["model-00001-of-00002.safetensors"]); - assert!(!mlx_snapshot_files_are_complete(&cached, None)); + assert!(!snapshot_files_are_complete(&cached, None)); cached.insert("model-00002-of-00002.safetensors"); - assert!(mlx_snapshot_files_are_complete(&cached, None)); + assert!(snapshot_files_are_complete(&cached, None)); } #[test] @@ -1277,7 +1277,7 @@ mod tests { let cached = std::collections::HashSet::from(["model.safetensors", "vision_model.safetensors"]); - assert!(mlx_snapshot_files_are_complete(&cached, None)); + assert!(snapshot_files_are_complete(&cached, None)); } #[test] @@ -2137,8 +2137,8 @@ fn mlx_variants_from_model_info( vec![HfModelVariant { variant_id: variant_id.clone(), label: mlx_variant_label(&variant_id), - backend_id: MLX_BACKEND_ID.to_string(), - format: MLX_FORMAT.to_string(), + backend_id: EREDU_BACKEND_ID.to_string(), + format: SAFETENSORS_FORMAT.to_string(), model_id: repo_id.to_string(), download_id: repo_id.to_string(), size_bytes, @@ -2243,14 +2243,14 @@ fn mlx_config_support(config: &Option) -> Option { mlx_config_support_for_value(config) } -#[cfg(all(feature = "mlx", target_os = "macos", target_arch = "aarch64"))] +#[cfg(all(feature = "eredu", target_os = "macos", target_arch = "aarch64"))] fn mlx_config_support_for_value(config: &serde_json::Value) -> Option { eredu_architectures::configuration::resolve_model_config(config) .err() .map(|error| error.to_string()) } -#[cfg(not(all(feature = "mlx", target_os = "macos", target_arch = "aarch64")))] +#[cfg(not(all(feature = "eredu", target_os = "macos", target_arch = "aarch64")))] fn mlx_config_support_for_value(_config: &serde_json::Value) -> Option { None } @@ -2367,11 +2367,11 @@ fn mlx_variant_id(repo_id: &str, config: &Option) -> String { .and_then(|config| config.get("torch_dtype")) .and_then(|value| value.as_str()) .map(|dtype| dtype.replace("float", "f")) - .unwrap_or_else(|| MLX_VARIANT_ID.to_string()) + .unwrap_or_else(|| SAFETENSORS_VARIANT_ID.to_string()) } fn mlx_variant_label(variant_id: &str) -> String { - if variant_id == MLX_VARIANT_ID { + if variant_id == SAFETENSORS_VARIANT_ID { "SafeTensors".to_string() } else { format!("SafeTensors {}", variant_id.to_uppercase()) @@ -2384,8 +2384,8 @@ pub async fn resolve_local_model_selection( variant_id: Option<&str>, ) -> Result { match backend_id { - MLX_BACKEND_ID | "mlx" => { - resolve_mlx_model(repo_id, variant_id.unwrap_or(MLX_VARIANT_ID)).await + EREDU_BACKEND_ID => { + resolve_mlx_model(repo_id, variant_id.unwrap_or(SAFETENSORS_VARIANT_ID)).await } LLAMACPP_BACKEND_ID => { let quantization = variant_id.ok_or_else(|| { @@ -2496,7 +2496,7 @@ pub async fn resolve_local_model_spec(spec: &str) -> Result let variants = get_repo_local_variants(spec).await?; let mlx_variants: Vec<_> = variants .iter() - .filter(|variant| variant.backend_id == MLX_BACKEND_ID) + .filter(|variant| variant.backend_id == EREDU_BACKEND_ID) .collect(); if mlx_variants.len() == 1 && !variants @@ -2907,7 +2907,7 @@ pub async fn cached_local_models() -> Result> { if is_mlx_compatible_repo(&config, &repo_siblings) && is_mlx_runtime_supported(&config) && valid_index - && mlx_snapshot_files_are_complete(&cached_filenames, index.as_ref()) + && snapshot_files_are_complete(&cached_filenames, index.as_ref()) { let cached_files: Vec<_> = revision .files @@ -2918,9 +2918,9 @@ pub async fn cached_local_models() -> Result> { let model = CachedLocalModel { id: repo.repo_id.clone(), repo_id: repo.repo_id.clone(), - filename: MLX_VARIANT_ID.to_string(), + filename: SAFETENSORS_VARIANT_ID.to_string(), quantization: mlx_variant_id(&repo.repo_id, &config), - backend_id: MLX_BACKEND_ID.to_string(), + backend_id: EREDU_BACKEND_ID.to_string(), model_path: revision.snapshot_path.clone(), size_bytes: cached_files.iter().map(|file| file.size_on_disk).sum(), mmproj_path: None, @@ -3029,7 +3029,7 @@ pub async fn delete_cached_local_model(model_id: &str) -> Result<()> { .flat_map(|repo| &repo.revisions) .flat_map(|revision| &revision.files) .filter(|file| { - if model.backend_id == MLX_BACKEND_ID { + if model.backend_id == EREDU_BACKEND_ID { should_download_for_mlx(&file.file_name) } else { let is_model_weight = file.file_name.ends_with(".gguf") diff --git a/crates/goose-local-inference/src/lib.rs b/crates/goose-local-inference/src/lib.rs index aa7480b28a..861fd161ee 100644 --- a/crates/goose-local-inference/src/lib.rs +++ b/crates/goose-local-inference/src/lib.rs @@ -184,7 +184,12 @@ impl InferenceRuntime { let state = slot.state.lock().await; if let ModelSlotState::Loaded { resolved, .. } = &*state { if selected_backend(&resolved.model_path, backend_id).ok() - == Some(key_backend(&resolved.backend_id)) + == Some( + resolved + .backend_id + .as_deref() + .unwrap_or(LLAMACPP_BACKEND_ID), + ) { return Some(resolved.as_ref().clone()); } @@ -264,14 +269,6 @@ struct ExplicitModelPath { model_path: PathBuf, } -fn key_backend(id: &Option) -> &str { - match id.as_deref() { - Some("mlx") => EREDU_BACKEND_ID, - Some(id) => id, - None => LLAMACPP_BACKEND_ID, - } -} - fn selected_backend(path: &Path, requested: Option<&str>) -> Result<&'static str> { let gguf = has_extension(path, "gguf"); match requested { @@ -280,7 +277,7 @@ fn selected_backend(path: &Path, requested: Option<&str>) -> Result<&'static str } else { EREDU_BACKEND_ID }), - Some("eredu" | "mlx") => Ok(EREDU_BACKEND_ID), + Some("eredu") => Ok(EREDU_BACKEND_ID), Some("llamacpp") if gguf => Ok(LLAMACPP_BACKEND_ID), Some("llamacpp") => { bail!("llama.cpp requires a GGUF checkpoint; use eredu for SafeTensors") @@ -326,14 +323,14 @@ fn explicit_model_path(model_id: &str) -> Result> { return Ok(Some(ExplicitModelPath { model_path: path })); } - let mlx_directory = if path.is_dir() { + let safetensors_directory = if path.is_dir() { Some(path.as_path()) } else if path.is_file() && has_extension(&path, "safetensors") { path.parent() } else { None }; - if let Some(directory) = mlx_directory { + if let Some(directory) = safetensors_directory { if is_safetensors_model_directory(directory)? { eredu::validate_model_directory(directory) .map_err(|error| anyhow::anyhow!(error.to_string()))?; @@ -761,7 +758,7 @@ impl ProviderDescriptor for LocalInferenceProvider { ProviderMetadata::new( PROVIDER_NAME, "Local Inference", - "Local inference using GGUF (llama.cpp) and MLX models", + "Local inference using llama.cpp and Eredu", "", vec![], "https://github.com/utilityai/llama-cpp-rs", @@ -1080,7 +1077,7 @@ mod tests { assert_eq!(selected_backend(gguf, None).unwrap(), "llamacpp"); assert_eq!(selected_backend(safetensors, None).unwrap(), "eredu"); assert_eq!(selected_backend(gguf, Some("eredu")).unwrap(), "eredu"); - assert_eq!(selected_backend(safetensors, Some("mlx")).unwrap(), "eredu"); + assert!(selected_backend(safetensors, Some("mlx")).is_err()); assert!(selected_backend(safetensors, Some("llamacpp")).is_err()); assert!(selected_backend(gguf, Some("unknown")).is_err()); } diff --git a/crates/goose-local-inference/src/management.rs b/crates/goose-local-inference/src/management.rs index 4becb816b6..11c3548c1b 100644 --- a/crates/goose-local-inference/src/management.rs +++ b/crates/goose-local-inference/src/management.rs @@ -132,7 +132,7 @@ pub async fn download_model( ) -> Result { let selection = explicit_model_selection(&req)?; let model_id = local_model_id_from_request(&req, selection.as_ref()).await?; - if matches!(req.backend_id.as_deref(), Some("eredu" | "mlx")) + if req.backend_id.as_deref() == Some("eredu") && selection .as_ref() .is_some_and(|selection| selection.backend_id == "llamacpp") @@ -251,10 +251,7 @@ fn settings_model_path(model_id: &str) -> Result { } pub fn get_model_settings(model_id: &str) -> Result { - let mut settings = crate::config_resolver::model_settings(model_id)?; - if settings.backend_id.as_deref() == Some("mlx") { - settings.backend_id = Some("eredu".into()); - } + let settings = crate::config_resolver::model_settings(model_id)?; let path = settings_model_path(model_id)?; let default_backend = crate::selected_backend(&path, None)?.to_string(); let mut available_backends = Vec::new(); @@ -588,7 +585,7 @@ fn explicit_model_selection( ) -> Result> { let format_backend = match req.format.as_deref() { Some("gguf") => Some("llamacpp"), - Some("safetensors" | "mlx-safetensors") => Some("eredu"), + Some("safetensors") => Some("eredu"), Some(format) => anyhow::bail!("Unknown local checkpoint format '{format}'"), None => None, }; @@ -607,12 +604,12 @@ fn explicit_model_selection( let is_gguf = format_backend == Some("llamacpp") || parsed_variant_id.is_some(); let variant_id = req.variant_id.clone().or(parsed_variant_id); match backend_id { - "eredu" | "mlx" if is_gguf => Ok(Some(LocalModelSelection { + "eredu" if is_gguf => Ok(Some(LocalModelSelection { repo_id, backend_id: "llamacpp".into(), variant_id: variant_id.map(|id| hf_models::canonicalize_quantization(&id)), })), - "mlx" | "eredu" => Ok(Some(LocalModelSelection { + "eredu" => Ok(Some(LocalModelSelection { repo_id, backend_id: backend_id.to_string(), variant_id, @@ -636,7 +633,7 @@ async fn local_model_id_from_request( ) -> Result { if let Some(selection) = selection { return match selection.backend_id.as_str() { - "mlx" | "eredu" => Ok(selection.repo_id.clone()), + "eredu" => Ok(selection.repo_id.clone()), "llamacpp" => { let quantization = selection.variant_id.as_deref().ok_or_else(|| { anyhow!( @@ -664,11 +661,11 @@ async fn local_model_id_from_request( let has_llamacpp = variants .iter() .any(|variant| variant.backend_id == "llamacpp"); - let mlx_variants: Vec<_> = variants + let eredu_variants: Vec<_> = variants .iter() .filter(|variant| variant.backend_id == "eredu") .collect(); - if mlx_variants.len() == 1 && !has_llamacpp { + if eredu_variants.len() == 1 && !has_llamacpp { Ok(req.spec.clone()) } else { anyhow::bail!( diff --git a/crates/goose-local-inference/src/tool_emulation.rs b/crates/goose-local-inference/src/tool_emulation.rs index 4e9046f7fc..10104fd540 100644 --- a/crates/goose-local-inference/src/tool_emulation.rs +++ b/crates/goose-local-inference/src/tool_emulation.rs @@ -6,23 +6,23 @@ use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] use goose_provider_types::conversation::message::{Message, MessageContent}; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] use rmcp::model::{CallToolRequestParams, Tool}; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] use serde_json::json; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] use std::borrow::Cow; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] use uuid::Uuid; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] pub(crate) const SHELL_TOOL: &str = "developer__shell"; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] pub(crate) const CODE_EXECUTION_TOOL: &str = "code_execution__execute_typescript"; -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] pub(crate) fn load_tiny_model_prompt() -> String { use std::env; @@ -55,7 +55,7 @@ pub(crate) fn load_tiny_model_prompt() -> String { }) } -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] pub(crate) fn build_emulator_tool_description(tools: &[Tool], code_mode_enabled: bool) -> String { let mut tool_desc = String::new(); @@ -466,7 +466,7 @@ impl StreamingEmulatorParser { } } -#[cfg(feature = "mlx")] +#[cfg(feature = "eredu")] pub(crate) fn message_for_emulator_action( action: &EmulatorAction, message_id: &str, @@ -721,7 +721,7 @@ mod tests { } } - #[cfg(feature = "mlx")] + #[cfg(feature = "eredu")] #[test] fn tool_description_uses_execute_typescript_fence() { let description = build_emulator_tool_description(&[], true); diff --git a/crates/goose-providers/Cargo.toml b/crates/goose-providers/Cargo.toml index 353ba907da..4cb1c8b879 100644 --- a/crates/goose-providers/Cargo.toml +++ b/crates/goose-providers/Cargo.toml @@ -17,7 +17,7 @@ local-inference = ["dep:goose-local-inference"] local-inference-hf-hub = ["local-inference", "goose-local-inference/hf-hub"] cuda = ["local-inference", "goose-local-inference/cuda"] vulkan = ["local-inference", "goose-local-inference/vulkan"] -mlx = ["local-inference", "goose-local-inference/mlx"] +eredu = ["local-inference", "goose-local-inference/eredu"] rustls-tls = [ "reqwest/rustls", "rmcp/reqwest", diff --git a/crates/goose/Cargo.toml b/crates/goose/Cargo.toml index 59d699ad2a..2bfde2d915 100644 --- a/crates/goose/Cargo.toml +++ b/crates/goose/Cargo.toml @@ -54,7 +54,7 @@ aws-providers = [ ] cuda = ["local-inference", "candle-core/cuda", "candle-nn/cuda", "goose-providers/cuda"] vulkan = ["local-inference", "goose-providers/vulkan"] -mlx = ["local-inference", "goose-providers/mlx"] +eredu = ["local-inference", "goose-providers/eredu"] rustls-tls = [ "dep:rustls", "dep:rcgen", diff --git a/goose-self-test.yaml b/goose-self-test.yaml index f70c206b90..121de50d9e 100644 --- a/goose-self-test.yaml +++ b/goose-self-test.yaml @@ -20,7 +20,6 @@ activities: - Validate ACP thinking-effort discovery, forwarding, and provider switching - Validate GDK observability hook lifecycle events and payload opt-in - Validate capped and uncapped auto-compaction thresholds and Desktop editing - - Validate local eredu inference, tool round trips, and interruption recovery - Test error boundaries including nested delegation prevention - Generate comprehensive test report @@ -29,7 +28,7 @@ parameters: input_type: string requirement: optional default: "all" - description: "Which test phases to run: all, basic, extensions, delegation, declared-vision, reasoning, zai-coding-plan, acp-effort, compaction, local-inference, advanced" + description: "Which test phases to run: all, basic, extensions, delegation, declared-vision, reasoning, zai-coding-plan, acp-effort, compaction, advanced" - key: test_depth input_type: string @@ -59,41 +58,6 @@ instructions: | You are testing yourself - a running goose instance validating its own capabilities through meta-testing. This is true first-person integration testing where you use your own tools to test your own functionality. - ## Local inference migration checks - When test_phases includes local-inference, or includes all and this session uses - the local provider, validate the currently selected cached model without downloading - new weights. Record the model ID, format, selected backend, and agent-loop mode. - Use a tool to write a small file, read it back in a later turn, and confirm that - tool arguments and results survive the round trip. Request a response long enough - to observe streaming, interrupt it, and verify a subsequent request still works. - Check that reasoning is separated from the visible answer and that completed - native or emulated tool calls execute only once. Record unavailable hardware, - models, or interruption controls as skipped checks, not successful checks. - Repeat this phase with a supported SafeTensors model using the automatic eredu - default and a cached GGUF explicitly set to eredu, then restore the GGUF to its - automatic llama.cpp default. Confirm switching engines does not download weights. - With a cached eredu vision model, send image attachments of different sizes and - check prompt usage against eredu's prepared-input model-position count. Confirm - that text plus media consumes the configured context budget, including rejection - of an oversized input, and that image_token_estimate does not change that count. - Skip these image checks explicitly if no compatible cached vision model exists. - Inspect the eredu inference response log for memory_forecast on ordinary and, - when an already-cached compatible drafter is available, speculative requests. - Confirm the forecast uses the actual input/output budget and preserves unknown - bounds. A forecast error must be diagnostic only, allowing valid generation to - continue. Record unavailable log access or draft models as skipped checks. - Repeat a request with a cached mixed-precision GGUF and inspect the loaded - forecasts before and after warm-up. Check each reported conversion-retention - group's effective policy and that retained payload plus reservations stays within - its bound (256 MiB by default); unavailable observations are not zero usage. - Target and external drafter budgets are separate. Reset may preserve admitted - conversions. Do not add their payload to residency a second time or treat either - the conversion-retention budget or allocator-cache ceiling as a total-memory - limit: unsupported projection layouts, arithmetic or row counts may still need - temporary full-weight casts. Supported multi-row Metal prefill can now avoid them. - Skip this comparison if no suitable checkpoint or forecast log is available. - Run the same tool round trip with both legacy and GOOSE_STATE_MACHINE=1 sessions. - ## Understanding First-Person Integration Testing This is a crucial distinction - as a running goose instance, you are testing yourself using your own capabilities. This is meta-testing in the truest sense: not unit tests or external test harnesses, but you using your tools diff --git a/ui/desktop/src/components/settings/localInference/ModelSettingsPanel.tsx b/ui/desktop/src/components/settings/localInference/ModelSettingsPanel.tsx index 959ed38bf9..a80810e2a0 100644 --- a/ui/desktop/src/components/settings/localInference/ModelSettingsPanel.tsx +++ b/ui/desktop/src/components/settings/localInference/ModelSettingsPanel.tsx @@ -472,8 +472,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => { save({ ...settings, [key]: value }); }; - const effectiveBackend = - settings.backendId === 'mlx' ? 'eredu' : settings.backendId || defaultBackend; + const effectiveBackend = settings.backendId || defaultBackend; const usesEredu = effectiveBackend === 'eredu'; const samplingType: SamplingType = settings.sampling?.type ?? 'Temperature'; @@ -571,7 +570,7 @@ export const ModelSettingsPanel = ({ modelId }: { modelId: string }) => { label={intl.formatMessage(i18n.inferenceBackend)} description={intl.formatMessage(i18n.inferenceBackendDescription)} - value={settings.backendId === 'mlx' ? 'eredu' : settings.backendId || 'auto'} + value={settings.backendId || 'auto'} options={[ { value: 'auto', label: intl.formatMessage(i18n.automaticBackend) }, ...Array.from(