agent: lumotia-rebrand — rust workspace crates magnotia-* -> lumotia-*
Some checks failed
check / cargo check (macos-latest) (push) Has been cancelled
check / cargo check (ubuntu-22.04) (push) Has been cancelled
check / cargo check (windows-latest) (push) Has been cancelled
check / svelte build + lint (push) Has been cancelled

Phase 2 of the rebrand cascade. Renames all 9 workspace crates from
magnotia-* to lumotia-* plus the src-tauri binary crate name:

- magnotia-ai-formatting   -> lumotia-ai-formatting
- magnotia-audio           -> lumotia-audio
- magnotia-cloud-providers -> lumotia-cloud-providers
- magnotia-core            -> lumotia-core
- magnotia-hotkey          -> lumotia-hotkey
- magnotia-llm             -> lumotia-llm
- magnotia-mcp             -> lumotia-mcp
- magnotia-storage         -> lumotia-storage
- magnotia-transcription   -> lumotia-transcription
- magnotia                 -> lumotia (src-tauri binary)
- magnotia_lib             -> lumotia_lib (src-tauri lib target)

Crate directories (crates/audio/ etc.) stay as-is; only the Cargo.toml
[package] name field changes plus all consumer module imports
(magnotia_core -> lumotia_core, etc.).

Remaining magnotia_* references at this point are intentional and
scoped to later phases: tracing targets (Phase 4), DB setting keys
magnotia_preferences/magnotia_history (Phase 5).

cargo build --workspace passes. cargo test --workspace: 330 pass, 0 fail.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-13 08:48:09 +01:00
parent bc2db91520
commit 089349d966
60 changed files with 372 additions and 372 deletions

View File

@@ -4,7 +4,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
use tauri::Manager;
use crate::commands::security::ensure_main_window;
use magnotia_audio::{DeviceInfo, MicrophoneCapture};
use lumotia_audio::{DeviceInfo, MicrophoneCapture};
/// Enumerate every input device available to cpal, with metadata for the
/// Settings device-picker UI. Includes a flag for likely PulseAudio /

View File

@@ -15,7 +15,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
use serde::{Deserialize, Serialize};
use magnotia_storage::{
use lumotia_storage::{
app_data_dir, crashes_dir, list_recent_errors, log_error, logs_dir, ErrorLogRow,
};
@@ -335,7 +335,7 @@ async fn generate_diagnostic_report_inner(
if opts.include_settings {
out.push_str("## Settings (sanitised)\n\n");
match magnotia_storage::get_setting(&state.db, "magnotia_preferences").await {
match lumotia_storage::get_setting(&state.db, "magnotia_preferences").await {
Ok(Some(json)) => {
out.push_str("```json\n");
out.push_str(&sanitise_preferences_json(&json));
@@ -520,7 +520,7 @@ pub async fn save_diagnostic_report(
let _ = app; // reserved for future dialog integration
let report = generate_diagnostic_report_inner(&state, options).await?;
let dir = magnotia_storage::app_data_dir().join("diagnostic-reports");
let dir = lumotia_storage::app_data_dir().join("diagnostic-reports");
fs::create_dir_all(&dir).map_err(|e| format!("create dir: {e}"))?;
let ts = SystemTime::now()

View File

@@ -5,7 +5,7 @@
use serde::Deserialize;
use magnotia_storage::{
use lumotia_storage::{
record_feedback as db_record_feedback, FeedbackTargetType, RecordFeedbackParams,
};

View File

@@ -1,7 +1,7 @@
use serde::Serialize;
use magnotia_core::hardware::{self, Os};
use magnotia_core::recommendation;
use lumotia_core::hardware::{self, Os};
use lumotia_core::recommendation;
#[derive(Serialize)]
pub struct SystemInfo {
@@ -53,7 +53,7 @@ pub fn rank_models() -> Result<Vec<ModelRecommendation>, String> {
Ok(ranked
.into_iter()
.map(|scored| {
let downloaded = magnotia_transcription::is_downloaded(&scored.entry.id);
let downloaded = lumotia_transcription::is_downloaded(&scored.entry.id);
ModelRecommendation {
id: scored.entry.id.as_str().to_string(),
display_name: scored.entry.display_name,

View File

@@ -3,7 +3,7 @@ use std::sync::Arc;
use tauri::Emitter;
use tokio::sync::{mpsc, Mutex};
use magnotia_hotkey::{EvdevHotkeyListener, HotkeyCombo, HotkeyEvent};
use lumotia_hotkey::{EvdevHotkeyListener, HotkeyCombo, HotkeyEvent};
/// Managed state for the evdev hotkey listener.
pub struct HotkeyState {
@@ -30,7 +30,7 @@ pub fn is_wayland_session() -> bool {
/// Check whether evdev hotkey capture is available (user in `input` group, etc.).
#[tauri::command]
pub fn check_hotkey_access() -> Result<(), String> {
magnotia_hotkey::check_evdev_access()
lumotia_hotkey::check_evdev_access()
}
/// Start the evdev global hotkey listener. Emits "magnotia:hotkey-pressed" and

View File

@@ -7,7 +7,7 @@
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use magnotia_storage::{
use lumotia_storage::{
delete_implementation_rule as db_delete_rule, get_task_by_id,
insert_implementation_rule as db_insert_rule, list_implementation_rules as db_list_rules,
mark_implementation_rule_fired as db_mark_rule_fired,

View File

@@ -19,13 +19,13 @@ use crate::commands::models::{default_model_id_for_engine, ensure_model_loaded};
use crate::commands::power::PowerAssertion;
use crate::commands::security::ensure_main_window;
use crate::AppState;
use magnotia_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions};
use magnotia_audio::{
use lumotia_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions};
use lumotia_audio::{
AudioChunk, CaptureRuntimeError, MicrophoneCapture, StreamingResampler, WavWriter,
};
use magnotia_core::constants::WHISPER_SAMPLE_RATE;
use magnotia_core::types::{AudioSamples, Segment, TranscriptionOptions};
use magnotia_transcription::LocalEngine;
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
use lumotia_core::types::{AudioSamples, Segment, TranscriptionOptions};
use lumotia_transcription::LocalEngine;
const CHUNK_SAMPLES: usize = 32_000; // 2s at 16kHz
const OVERLAP_SAMPLES: usize = 4_000; // 0.25s at 16kHz
@@ -450,7 +450,7 @@ struct InferenceTask {
chunk_start_sample: u64,
trim_before_secs: f64,
duration_secs: f64,
rx: std::sync::mpsc::Receiver<Result<magnotia_transcription::TimedTranscript, String>>,
rx: std::sync::mpsc::Receiver<Result<lumotia_transcription::TimedTranscript, String>>,
}
#[derive(Debug, Clone)]
@@ -503,15 +503,15 @@ pub async fn start_live_transcription_session(
let resolved_profile_id = config
.profile_id
.clone()
.unwrap_or_else(|| magnotia_storage::DEFAULT_PROFILE_ID.to_string());
.unwrap_or_else(|| lumotia_storage::DEFAULT_PROFILE_ID.to_string());
let profile = magnotia_storage::database::get_profile(&state.db, &resolved_profile_id)
let profile = lumotia_storage::database::get_profile(&state.db, &resolved_profile_id)
.await
.map_err(|e| e.to_string())?
.ok_or_else(|| format!("Profile {resolved_profile_id} not found"))?;
let profile_terms: Vec<String> =
magnotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
lumotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
.await
.map_err(|e| e.to_string())?
.into_iter()
@@ -1555,8 +1555,8 @@ mod tests {
let stop_flag = Arc::new(AtomicBool::new(false));
let (tx1, rx1) = std::sync::mpsc::channel();
tx1.send(Ok(magnotia_transcription::TimedTranscript {
transcript: magnotia_core::types::Transcript::new(
tx1.send(Ok(lumotia_transcription::TimedTranscript {
transcript: lumotia_core::types::Transcript::new(
vec![segment(0.0, 0.8, "first chunk")],
"en".into(),
0.8,
@@ -1597,8 +1597,8 @@ mod tests {
);
let (tx2, rx2) = std::sync::mpsc::channel();
tx2.send(Ok(magnotia_transcription::TimedTranscript {
transcript: magnotia_core::types::Transcript::new(
tx2.send(Ok(lumotia_transcription::TimedTranscript {
transcript: lumotia_core::types::Transcript::new(
vec![segment(0.0, 0.9, "second chunk")],
"en".into(),
0.9,

View File

@@ -3,10 +3,10 @@ use tauri::{Emitter, State};
use crate::commands::power::PowerAssertion;
use crate::commands::security::ensure_main_window;
use crate::AppState;
use magnotia_ai_formatting::{llm_cleanup_text, LlmPromptPreset};
use magnotia_core::hardware;
use magnotia_llm::model_manager::{self, model_info};
use magnotia_llm::{ContentTags, LlmModelId};
use lumotia_ai_formatting::{llm_cleanup_text, LlmPromptPreset};
use lumotia_core::hardware;
use lumotia_llm::model_manager::{self, model_info};
use lumotia_llm::{ContentTags, LlmModelId};
#[derive(Debug, serde::Serialize)]
#[serde(rename_all = "camelCase")]
@@ -369,9 +369,9 @@ pub async fn cleanup_transcript_text_cmd(
) -> Result<String, String> {
ensure_main_window(&window)?;
let resolved_profile_id =
profile_id.unwrap_or_else(|| magnotia_storage::DEFAULT_PROFILE_ID.to_string());
profile_id.unwrap_or_else(|| lumotia_storage::DEFAULT_PROFILE_ID.to_string());
let profile_terms: Vec<String> =
magnotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
lumotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
.await
.map_err(|e| e.to_string())?
.into_iter()

View File

@@ -7,7 +7,7 @@
use std::sync::Mutex;
use magnotia_core::process_watch::{self, ProcessLister};
use lumotia_core::process_watch::{self, ProcessLister};
/// Tauri-managed state for the meeting poller. Holds a long-lived
/// `ProcessLister` so each poll refreshes the existing `sysinfo::System`

View File

@@ -5,14 +5,14 @@ use tauri::Emitter;
use crate::commands::security::ensure_main_window;
use crate::AppState;
use magnotia_core::constants::WHISPER_SAMPLE_RATE;
use magnotia_core::hardware::{self, vulkan_loader_available, CpuFeatures};
use magnotia_core::model_registry::{self, Engine, LanguageSupport, ModelEntry};
use magnotia_core::types::{AudioSamples, ModelId, TranscriptionOptions};
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
use lumotia_core::hardware::{self, vulkan_loader_available, CpuFeatures};
use lumotia_core::model_registry::{self, Engine, LanguageSupport, ModelEntry};
use lumotia_core::types::{AudioSamples, ModelId, TranscriptionOptions};
#[cfg(feature = "whisper")]
use magnotia_transcription::load_whisper;
use magnotia_transcription::model_manager;
use magnotia_transcription::{load_parakeet, LocalEngine, Transcriber};
use lumotia_transcription::load_whisper;
use lumotia_transcription::model_manager;
use lumotia_transcription::{load_parakeet, LocalEngine, Transcriber};
/// Map legacy size strings to ModelId.
fn whisper_model_id(size: &str) -> ModelId {

View File

@@ -1,5 +1,5 @@
// Tauri commands wrapping magnotia_storage profile + profile_term CRUD.
// Pattern mirrors tasks.rs — flat imports from `magnotia_storage` with a `db_`
// Tauri commands wrapping lumotia_storage profile + profile_term CRUD.
// Pattern mirrors tasks.rs — flat imports from `lumotia_storage` with a `db_`
// alias prefix to avoid name collisions with the command functions, plain
// snake_case parameters (Tauri 2.x auto-converts camelCase JS keys),
// `.map_err(|e| e.to_string())` for error conversion, and camelCase DTOs
@@ -11,8 +11,8 @@
use serde::Serialize;
use magnotia_ai_formatting::extract_corrections;
use magnotia_storage::{
use lumotia_ai_formatting::extract_corrections;
use lumotia_storage::{
add_profile_term as db_add_profile_term, create_profile as db_create_profile,
delete_profile as db_delete_profile, delete_profile_term as db_delete_profile_term,
list_profile_terms as db_list_profile_terms, list_profiles as db_list_profiles,

View File

@@ -7,10 +7,10 @@
//! filtering rather than adding a second query path.
//!
//! Stored under the existing SQLite settings table via
//! `magnotia_storage::{get_setting, set_setting}` — same bag as
//! `lumotia_storage::{get_setting, set_setting}` — same bag as
//! `magnotia_preferences`.
use magnotia_storage::{get_setting, set_setting};
use lumotia_storage::{get_setting, set_setting};
use crate::AppState;

View File

@@ -1,4 +1,4 @@
// Tauri commands wrapping magnotia_storage task CRUD.
// Tauri commands wrapping lumotia_storage task CRUD.
// Pattern mirrors transcripts.rs — TaskDto is the camelCase frontend shape,
// storage functions are aliased with db_ prefix to avoid name collisions.
@@ -6,8 +6,8 @@ use serde::{Deserialize, Serialize};
use uuid::Uuid;
use magnotia_llm::prompts::FeedbackExample as LlmFeedbackExample;
use magnotia_storage::{
use lumotia_llm::prompts::FeedbackExample as LlmFeedbackExample;
use lumotia_storage::{
complete_subtask_and_check_parent as db_complete_subtask, complete_task as db_complete_task,
delete_task as db_delete_task, get_task_by_id as db_get_task,
insert_subtask as db_insert_subtask, insert_task as db_insert_task,
@@ -228,7 +228,7 @@ fn to_llm_examples(rows: Vec<FeedbackRow>) -> Vec<LlmFeedbackExample> {
Ok(v) => v,
Err(e) => {
tracing::warn!(
target: "magnotia_lib::feedback",
target: "lumotia_lib::feedback",
row_id = r.id,
error = %e,
"skipping feedback row with malformed context_json"

View File

@@ -9,9 +9,9 @@ use crate::commands::build_initial_prompt;
use crate::commands::models::{default_model_id_for_engine, ensure_model_loaded};
use crate::commands::security::ensure_main_window;
use crate::AppState;
use magnotia_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions};
use magnotia_core::constants::WHISPER_SAMPLE_RATE;
use magnotia_core::types::{AudioSamples, Segment, Transcript, TranscriptionOptions};
use lumotia_ai_formatting::{post_process_segments, FormatMode, PostProcessOptions};
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
use lumotia_core::types::{AudioSamples, Segment, Transcript, TranscriptionOptions};
const PARAKEET_CHUNK_THRESHOLD_SECS: usize = 18;
const PARAKEET_CHUNK_SECS: usize = 15;
@@ -29,7 +29,7 @@ struct ChunkingStrategy {
fn pick_engine(
state: &AppState,
engine: &str,
) -> Result<Arc<magnotia_transcription::LocalEngine>, String> {
) -> Result<Arc<lumotia_transcription::LocalEngine>, String> {
match engine {
"whisper" => Ok(state.whisper_engine.clone()),
"parakeet" => Ok(state.parakeet_engine.clone()),
@@ -70,11 +70,11 @@ fn trim_overlap_segments(segments: &mut Vec<Segment>, trim_before_secs: f64) {
}
fn transcribe_samples_sync(
engine: Arc<magnotia_transcription::LocalEngine>,
engine: Arc<lumotia_transcription::LocalEngine>,
engine_name: &str,
samples: Vec<f32>,
options: TranscriptionOptions,
) -> Result<magnotia_transcription::TimedTranscript, String> {
) -> Result<lumotia_transcription::TimedTranscript, String> {
let Some(strategy) = pick_chunking_strategy(engine_name, samples.len()) else {
let audio = AudioSamples::mono_16khz(samples);
return engine
@@ -128,7 +128,7 @@ fn transcribe_samples_sync(
chunk_start = chunk_end.saturating_sub(strategy.overlap_samples);
}
Ok(magnotia_transcription::TimedTranscript {
Ok(lumotia_transcription::TimedTranscript {
transcript: Transcript::new(
all_segments,
options.language.clone().unwrap_or_else(|| "en".to_string()),
@@ -165,15 +165,15 @@ pub async fn transcribe_file(
) -> Result<serde_json::Value, String> {
ensure_main_window(&window)?;
let resolved_profile_id =
profile_id.unwrap_or_else(|| magnotia_storage::DEFAULT_PROFILE_ID.to_string());
profile_id.unwrap_or_else(|| lumotia_storage::DEFAULT_PROFILE_ID.to_string());
let profile = magnotia_storage::database::get_profile(&state.db, &resolved_profile_id)
let profile = lumotia_storage::database::get_profile(&state.db, &resolved_profile_id)
.await
.map_err(|e| e.to_string())?
.ok_or_else(|| format!("Profile {resolved_profile_id} not found"))?;
let profile_terms: Vec<String> =
magnotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
lumotia_storage::database::list_profile_terms(&state.db, &resolved_profile_id)
.await
.map_err(|e| e.to_string())?
.into_iter()
@@ -199,7 +199,7 @@ pub async fn transcribe_file(
let engine_name_for_worker = engine_name.clone();
let path_for_probe = Path::new(&path);
if let Some(duration_secs) =
magnotia_audio::probe_audio_duration_secs(path_for_probe).map_err(|e| e.to_string())?
lumotia_audio::probe_audio_duration_secs(path_for_probe).map_err(|e| e.to_string())?
{
if duration_secs > MAX_FILE_TRANSCRIPTION_SECS {
return Err(format!(
@@ -210,12 +210,12 @@ pub async fn transcribe_file(
}
let timed = tokio::task::spawn_blocking(move || {
let audio = magnotia_audio::decode_audio_file_limited(
let audio = lumotia_audio::decode_audio_file_limited(
Path::new(&path),
Some(MAX_FILE_TRANSCRIPTION_SECS),
)
.map_err(|e| e.to_string())?;
let resampled = magnotia_audio::resample_to_16khz(&audio).map_err(|e| e.to_string())?;
let resampled = lumotia_audio::resample_to_16khz(&audio).map_err(|e| e.to_string())?;
transcribe_samples_sync(
engine,
&engine_name_for_worker,

View File

@@ -1,4 +1,4 @@
// Tauri commands wrapping the magnotia_storage transcript CRUD.
// Tauri commands wrapping the lumotia_storage transcript CRUD.
// These are the bridge that lets the Svelte frontend treat SQLite as the
// canonical store rather than localStorage.
//
@@ -13,7 +13,7 @@
use serde::{Deserialize, Serialize};
use magnotia_storage::{
use lumotia_storage::{
delete_transcript as db_delete_transcript, get_transcript as db_get_transcript,
insert_transcript as db_insert_transcript, list_transcripts_paged,
search_transcripts as db_search_transcripts, update_transcript as db_update_transcript,
@@ -110,7 +110,7 @@ pub async fn add_transcript(
profile_id: transcript
.profile_id
.as_deref()
.unwrap_or(magnotia_storage::DEFAULT_PROFILE_ID),
.unwrap_or(lumotia_storage::DEFAULT_PROFILE_ID),
title: transcript.title.as_deref(),
audio_path: transcript.audio_path.as_deref(),
duration: transcript.duration,

View File

@@ -12,15 +12,15 @@ use sqlx::SqlitePool;
use tauri::Manager;
use tracing_subscriber::EnvFilter;
use magnotia_core::types::EngineName;
use magnotia_llm::LlmEngine;
use magnotia_storage::{database_path, get_setting, init as init_db, prune_error_log, set_setting};
use lumotia_core::types::EngineName;
use lumotia_llm::LlmEngine;
use lumotia_storage::{database_path, get_setting, init as init_db, prune_error_log, set_setting};
/// How long to retain `error_log` rows. Pruned once on startup.
/// 90 days is long enough to triage "this happened a few weeks ago"
/// reports and short enough that the table stays kilobyte-scale.
const ERROR_LOG_RETENTION_DAYS: i64 = 90;
use magnotia_transcription::LocalEngine;
use lumotia_transcription::LocalEngine;
static TRACING_INIT: Once = Once::new();
@@ -162,7 +162,7 @@ fn init_tracing() {
TRACING_INIT.call_once(|| {
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| {
EnvFilter::new(
"warn,magnotia=info,magnotia_lib=info,magnotia_audio=info,magnotia_startup=info,magnotia_hotkey=info,magnotia_ai_formatting=info",
"warn,magnotia=info,lumotia_lib=info,lumotia_audio=info,magnotia_startup=info,lumotia_hotkey=info,lumotia_ai_formatting=info",
)
});

View File

@@ -1,5 +1,5 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
magnotia_lib::run()
lumotia_lib::run()
}