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

@@ -1,11 +1,11 @@
[package]
name = "magnotia-ai-formatting"
name = "lumotia-ai-formatting"
version = "0.1.0"
edition = "2021"
description = "Text post-processing pipeline: filler removal, British English conversion, formatting for Magnotia"
[dependencies]
magnotia-core = { path = "../core" }
magnotia-llm = { path = "../llm" }
lumotia-core = { path = "../core" }
lumotia-llm = { path = "../llm" }
regex-lite = "0.1"
tracing = "0.1"

View File

@@ -3,7 +3,7 @@
//! The llm_client is not yet wired to a running model. This module defines
//! the prompt contract so that wiring it produces correct, hardened output.
use magnotia_llm::{EngineError, LlmEngine};
use lumotia_llm::{EngineError, LlmEngine};
/// System prompt sent before every cleanup call.
///
@@ -161,7 +161,7 @@ pub fn cleanup_text(
#[cfg(test)]
mod tests {
use super::*;
use magnotia_llm::EngineError;
use lumotia_llm::EngineError;
#[test]
fn empty_terms_returns_empty_string() {

View File

@@ -1,6 +1,6 @@
use magnotia_core::constants::SMART_PARAGRAPH_GAP_SECS;
use magnotia_core::types::Segment;
use magnotia_llm::LlmEngine;
use lumotia_core::constants::SMART_PARAGRAPH_GAP_SECS;
use lumotia_core::types::Segment;
use lumotia_llm::LlmEngine;
use crate::{llm_client, rule_based, to_plain_text::to_plain_text};

View File

@@ -13,7 +13,7 @@
//! is the whitespace pass and empty-segment filter, plus a single
//! public function the pipeline can depend on.
use magnotia_core::types::Segment;
use lumotia_core::types::Segment;
/// Join transcription segments into a single plain-text string
/// suitable for feeding to an LLM cleanup prompt.

View File

@@ -1,11 +1,11 @@
[package]
name = "magnotia-audio"
name = "lumotia-audio"
version = "0.1.0"
edition = "2021"
description = "Audio capture (cpal), VAD, resampling (rubato), file decoding (symphonia), WAV I/O (hound) for Magnotia"
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
# Microphone capture
cpal = "0.17"

View File

@@ -8,7 +8,7 @@ use regex::Regex;
use serde::{Deserialize, Serialize};
use std::sync::OnceLock;
use magnotia_core::error::{MagnotiaError, Result};
use lumotia_core::error::{MagnotiaError, Result};
const AUDIO_CHANNEL_CAPACITY: usize = 32;
@@ -149,7 +149,7 @@ impl MicrophoneCapture {
for device in devices {
let name = device_display_name(&device).unwrap_or_default();
if name == device_name {
tracing::info!(target: "magnotia_audio", "start_with_device: opening explicit device '{name}'");
tracing::info!(target: "lumotia_audio", "start_with_device: opening explicit device '{name}'");
return open_and_validate(device, &name, /* require_audio = */ true);
}
}
@@ -196,7 +196,7 @@ impl MicrophoneCapture {
});
tracing::info!(
target: "magnotia_audio",
target: "lumotia_audio",
device_count = all_devices.len(),
default = %default_name,
"enumerated input devices"
@@ -211,7 +211,7 @@ impl MicrophoneCapture {
match open_and_validate(device.clone(), &name, true) {
Ok(result) => return Ok(result),
Err(e) => {
tracing::warn!(target: "magnotia_audio", device = %name, error = %e, "candidate device rejected");
tracing::warn!(target: "lumotia_audio", device = %name, error = %e, "candidate device rejected");
}
}
}
@@ -219,7 +219,7 @@ impl MicrophoneCapture {
// Second pass: accept anything that delivers bytes (monitor sources
// included). Better to capture from a monitor than fail entirely.
tracing::warn!(
target: "magnotia_audio",
target: "lumotia_audio",
"no non-monitor mic produced audio; falling back to monitor/loopback sources"
);
for device in &all_devices {
@@ -227,7 +227,7 @@ impl MicrophoneCapture {
match open_and_validate(device.clone(), &name, false) {
Ok(result) => {
tracing::warn!(
target: "magnotia_audio",
target: "lumotia_audio",
device = %name,
"capturing from likely monitor source; recordings may be silent or contain system audio"
);
@@ -367,7 +367,7 @@ fn open_and_validate(
let format = config.sample_format();
tracing::info!(
target: "magnotia_audio",
target: "lumotia_audio",
device = %name,
sample_rate,
channels,
@@ -467,7 +467,7 @@ fn open_and_validate(
let rms = (sum_sq / total_samples as f64).sqrt() as f32;
tracing::info!(
target: "magnotia_audio",
target: "lumotia_audio",
device = %name,
samples = total_samples,
rms,
@@ -499,7 +499,7 @@ fn open_and_validate(
}
}
tracing::info!(target: "magnotia_audio", device = %name, "selected microphone");
tracing::info!(target: "lumotia_audio", device = %name, "selected microphone");
Ok((
MicrophoneCapture {
stream: Some(stream),
@@ -547,7 +547,7 @@ where
move |err| {
// Surface stream errors to the live session via err_tx so the
// frontend can show a toast.
tracing::error!(target: "magnotia_audio", error = %err, "capture stream error");
tracing::error!(target: "lumotia_audio", error = %err, "capture stream error");
if err_tx
.try_send(CaptureRuntimeError {
device_name: err_device_name.clone(),
@@ -560,7 +560,7 @@ where
// even if the frontend never received the typed event.
let prior = dropped_errors.fetch_add(1, Ordering::Relaxed);
tracing::warn!(
target: "magnotia_audio",
target: "lumotia_audio",
device = %err_device_name,
dropped_error = prior + 1,
"capture error channel full; dropping runtime error"

View File

@@ -1,7 +1,7 @@
use std::path::Path;
use magnotia_core::error::Result;
use magnotia_core::types::AudioSamples;
use lumotia_core::error::Result;
use lumotia_core::types::AudioSamples;
use crate::decode::decode_audio_file;
use crate::resample::resample_to_16khz;
@@ -16,6 +16,6 @@ pub async fn decode_and_resample(path: &Path) -> Result<AudioSamples> {
})
.await
.map_err(|e| {
magnotia_core::error::MagnotiaError::AudioDecodeFailed(format!("Task join error: {e}"))
lumotia_core::error::MagnotiaError::AudioDecodeFailed(format!("Task join error: {e}"))
})?
}

View File

@@ -9,8 +9,8 @@ use symphonia::core::io::MediaSourceStream;
use symphonia::core::meta::MetadataOptions;
use symphonia::core::probe::Hint;
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::AudioSamples;
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::AudioSamples;
/// Decode an audio file to mono f32 PCM samples.
/// Supports all formats symphonia handles: mp3, aac, flac, wav, ogg, etc.

View File

@@ -2,9 +2,9 @@ use rubato::{
Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction,
};
use magnotia_core::constants::WHISPER_SAMPLE_RATE;
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::AudioSamples;
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::AudioSamples;
/// Resample audio to 16kHz mono using sinc interpolation (rubato).
/// Returns a new AudioSamples at the target sample rate.

View File

@@ -27,8 +27,8 @@ use rubato::{
Resampler, SincFixedIn, SincInterpolationParameters, SincInterpolationType, WindowFunction,
};
use magnotia_core::constants::WHISPER_SAMPLE_RATE;
use magnotia_core::error::{MagnotiaError, Result};
use lumotia_core::constants::WHISPER_SAMPLE_RATE;
use lumotia_core::error::{MagnotiaError, Result};
/// Number of input samples the rubato resampler consumes per `process()`
/// call. Matches the chunk size used in `resample::resample_to_16khz`.

View File

@@ -7,7 +7,7 @@
// For now, all audio is treated as speech. This matches v0.2 behaviour
// (no VAD) and doesn't affect core functionality.
use magnotia_core::constants::VAD_SPEECH_THRESHOLD;
use lumotia_core::constants::VAD_SPEECH_THRESHOLD;
/// Stub speech detector. Treats all audio as speech.
#[derive(Default)]

View File

@@ -1,8 +1,8 @@
use std::io::BufWriter;
use std::path::Path;
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::AudioSamples;
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::AudioSamples;
/// Append-friendly WAV writer for long-running captures.
///

View File

@@ -1,11 +1,11 @@
[package]
name = "magnotia-cloud-providers"
name = "lumotia-cloud-providers"
version = "0.1.0"
edition = "2021"
description = "Provider trait and BYOK cloud STT scaffolding for Magnotia (Wyrdnote pending rebrand)"
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
# Async-native trait. async_trait converts async fn into Pin<Box<dyn
# Future>> at the trait surface so TranscriptionProvider stays

View File

@@ -16,8 +16,8 @@
use std::fmt;
use async_trait::async_trait;
use magnotia_core::error::Result;
use magnotia_core::types::{AudioSamples, ModelId, Transcript, TranscriptionOptions};
use lumotia_core::error::Result;
use lumotia_core::types::{AudioSamples, ModelId, Transcript, TranscriptionOptions};
use serde::{Deserialize, Serialize};
/// Stable, lower-kebab-case identifier for a provider. Used in user
@@ -70,7 +70,7 @@ pub enum CostClass {
}
/// Capabilities a provider advertises to the orchestrator and the UI.
/// Superset of `magnotia_transcription::TranscriberCapabilities` for
/// Superset of `lumotia_transcription::TranscriberCapabilities` for
/// local providers, with extra fields cloud providers populate.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProviderCapabilities {

View File

@@ -1,5 +1,5 @@
[package]
name = "magnotia-core"
name = "lumotia-core"
version = "0.1.0"
edition = "2021"
description = "Core types, constants, traits, hardware detection, and model registry for Magnotia"

View File

@@ -9,11 +9,11 @@
//! exactly one INFO line; subsequent calls with the same tuple are
//! silenced by the per-process log-once cache.
use magnotia_core::tuning::{inference_thread_count, Workload};
use lumotia_core::tuning::{inference_thread_count, Workload};
fn main() {
tracing_subscriber::fmt()
.with_env_filter("magnotia_core=info")
.with_env_filter("lumotia_core=info")
.with_target(true)
.with_writer(std::io::stderr)
.init();

View File

@@ -34,7 +34,7 @@ pub enum MagnotiaError {
#[error("file not found: '{}'", .0.display())]
FileNotFound(PathBuf),
/// Structured storage failure flowed up from `magnotia_storage::Error` via
/// Structured storage failure flowed up from `lumotia_storage::Error` via
/// its `From` impl. Display reads through to `detail` so the operation +
/// source context produced by the storage crate isn't double-prefixed.
#[error("{detail}")]
@@ -58,7 +58,7 @@ pub enum MagnotiaError {
/// Coarse discriminator for `MagnotiaError::Storage`. The storage crate maps
/// its full typed error onto one of these kinds at the boundary. Backend code
/// that wants finer-grained branching pattern-matches on
/// `magnotia_storage::Error` directly.
/// `lumotia_storage::Error` directly.
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum StorageKind {

View File

@@ -89,7 +89,7 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
if let Ok(mut seen) = log_seen().lock() {
if seen.insert(key) {
tracing::info!(
target: "magnotia_core::tuning",
target: "lumotia_core::tuning",
threads = final_value,
workload = ?workload,
gpu_offloaded,

View File

@@ -1,11 +1,11 @@
[package]
name = "magnotia-hotkey"
name = "lumotia-hotkey"
version = "0.1.0"
edition = "2021"
description = "Wayland-compatible global hotkey listener for Magnotia — evdev backend with device hotplug"
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
tokio = { version = "1", features = ["rt", "sync", "macros", "time"] }
serde = { version = "1", features = ["derive"] }
tracing = "0.1"

View File

@@ -1,5 +1,5 @@
[package]
name = "magnotia-llm"
name = "lumotia-llm"
version = "0.1.0"
edition = "2021"
description = "Local LLM engine for Magnotia (Qwen3.5 / Qwen3.6 via llama-cpp-2): transcript cleanup, task extraction, micro-step decomposition"
@@ -7,7 +7,7 @@ description = "Local LLM engine for Magnotia (Qwen3.5 / Qwen3.6 via llama-cpp-2)
[features]
# Default desktop build keeps the existing openmp + vulkan acceleration.
# Mobile / CPU-only targets can drop one or both via:
# cargo build -p magnotia-llm --no-default-features
# cargo build -p lumotia-llm --no-default-features
# These are independent so an Android Vulkan build can opt into vulkan
# without openmp (the NDK ships OpenMP libs but the toolchain configuration
# is fragile across NDK versions).
@@ -16,7 +16,7 @@ gpu-vulkan = ["llama-cpp-2/vulkan"]
openmp = ["llama-cpp-2/openmp"]
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
encoding_rs = "0.8"
futures-util = "0.3"
llama-cpp-2 = { version = "0.1.146", default-features = false }

View File

@@ -9,7 +9,7 @@ use llama_cpp_2::llama_batch::LlamaBatch;
use llama_cpp_2::model::params::LlamaModelParams;
use llama_cpp_2::model::{AddBos, LlamaChatMessage, LlamaChatTemplate, LlamaModel};
use llama_cpp_2::sampling::LlamaSampler;
use magnotia_core::tuning::{inference_thread_count, Workload};
use lumotia_core::tuning::{inference_thread_count, Workload};
use serde::{Deserialize, Serialize};
pub mod grammars;

View File

@@ -240,7 +240,7 @@ pub fn recommend_tier(total_ram_bytes: u64, total_vram_bytes: Option<u64>) -> Ll
}
pub fn model_dir() -> PathBuf {
magnotia_core::paths::app_paths().llm_models_dir()
lumotia_core::paths::app_paths().llm_models_dir()
}
pub fn model_path(id: LlmModelId) -> PathBuf {

View File

@@ -10,7 +10,7 @@
use std::env;
use std::path::PathBuf;
use magnotia_llm::{is_valid_intent, LlmEngine, LlmModelId};
use lumotia_llm::{is_valid_intent, LlmEngine, LlmModelId};
#[test]
fn extract_content_tags_returns_valid_pair() {

View File

@@ -11,8 +11,8 @@
use std::env;
use std::path::PathBuf;
use magnotia_llm::LlmEngine;
use magnotia_llm::LlmModelId;
use lumotia_llm::LlmEngine;
use lumotia_llm::LlmModelId;
#[test]
fn llama_cpp_2_smoke_generates_and_wraps() {
@@ -32,7 +32,7 @@ fn llama_cpp_2_smoke_generates_and_wraps() {
let completion = engine
.generate(
"Write exactly one short greeting.",
&magnotia_llm::GenerationConfig {
&lumotia_llm::GenerationConfig {
max_tokens: 32,
temperature: 0.0,
stop_sequences: vec!["\n".to_string()],

View File

@@ -1,18 +1,18 @@
[package]
name = "magnotia-mcp"
name = "lumotia-mcp"
version = "0.1.0"
edition = "2021"
description = "Read-only MCP stdio server exposing Magnotia transcripts and tasks to external agents"
[[bin]]
name = "magnotia-mcp"
name = "lumotia-mcp"
path = "src/main.rs"
[lib]
path = "src/lib.rs"
[dependencies]
magnotia-storage = { path = "../storage" }
lumotia-storage = { path = "../storage" }
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio", "sqlite"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View File

@@ -206,7 +206,7 @@ async fn list_transcripts_tool(pool: &SqlitePool, args: Value) -> Result<Value,
};
let limit = args.limit.unwrap_or(20).clamp(1, 200);
let rows = magnotia_storage::list_transcripts(pool, limit)
let rows = lumotia_storage::list_transcripts(pool, limit)
.await
.map_err(|e| error(-32603, format!("DB error: {e}")))?;
@@ -239,7 +239,7 @@ async fn get_transcript_tool(pool: &SqlitePool, args: Value) -> Result<Value, Js
let args: Args = serde_json::from_value(args)
.map_err(|e| error(-32602, format!("Invalid arguments: {e}")))?;
let row = magnotia_storage::get_transcript(pool, &args.id)
let row = lumotia_storage::get_transcript(pool, &args.id)
.await
.map_err(|e| error(-32603, format!("DB error: {e}")))?
.ok_or_else(|| error(-32000, format!("Transcript {} not found", args.id)))?;
@@ -273,7 +273,7 @@ async fn search_transcripts_tool(pool: &SqlitePool, args: Value) -> Result<Value
.map_err(|e| error(-32602, format!("Invalid arguments: {e}")))?;
let limit = args.limit.unwrap_or(20).clamp(1, 100);
let rows = magnotia_storage::search_transcripts(pool, &args.query, limit)
let rows = lumotia_storage::search_transcripts(pool, &args.query, limit)
.await
.map_err(|e| error(-32603, format!("DB error: {e}")))?;
@@ -296,7 +296,7 @@ async fn search_transcripts_tool(pool: &SqlitePool, args: Value) -> Result<Value
}
async fn list_tasks_tool(pool: &SqlitePool) -> Result<Value, JsonRpcError> {
let rows = magnotia_storage::list_tasks(pool)
let rows = lumotia_storage::list_tasks(pool)
.await
.map_err(|e| error(-32603, format!("DB error: {e}")))?;
@@ -460,7 +460,7 @@ mod tests {
});
let pool = sqlx::SqlitePool::connect("sqlite::memory:").await.unwrap();
magnotia_storage::migrations::run_migrations(&pool)
lumotia_storage::migrations::run_migrations(&pool)
.await
.unwrap();
let response = handle_message(&pool, request).await.expect("has response");

View File

@@ -1,12 +1,12 @@
//! Stdio entry point for magnotia-mcp. Reads newline-delimited JSON-RPC messages
//! from stdin, dispatches via `magnotia_mcp::handle_message`, writes responses to
//! from stdin, dispatches via `lumotia_mcp::handle_message`, writes responses to
//! stdout. Logs land on stderr so they don't collide with the JSON-RPC stream.
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
let db_path = magnotia_storage::database_path();
let db_path = lumotia_storage::database_path();
eprintln!(
"[magnotia-mcp] opening Magnotia database at {} (read-only)",
db_path.display()
@@ -15,7 +15,7 @@ async fn main() -> anyhow::Result<()> {
// to the user's database, regardless of which tools the dispatcher
// exposes. Migrations are deliberately skipped — this binary never owns
// the schema; the main app is the single migration writer.
let pool = magnotia_storage::init_readonly(&db_path).await?;
let pool = lumotia_storage::init_readonly(&db_path).await?;
eprintln!("[magnotia-mcp] ready, waiting for JSON-RPC on stdin");
let mut lines = BufReader::new(tokio::io::stdin()).lines();
@@ -28,7 +28,7 @@ async fn main() -> anyhow::Result<()> {
}
let response = match serde_json::from_str::<serde_json::Value>(trimmed) {
Ok(raw) => match magnotia_mcp::handle_message(&pool, raw).await {
Ok(raw) => match lumotia_mcp::handle_message(&pool, raw).await {
Some(response) => response,
None => continue, // notification — no reply
},
@@ -39,7 +39,7 @@ async fn main() -> anyhow::Result<()> {
// clients saw silence instead of a structured error
// (2026-04-22 review MAJOR).
eprintln!("[magnotia-mcp] parse error: {err}");
magnotia_mcp::parse_error_response(&err.to_string())
lumotia_mcp::parse_error_response(&err.to_string())
}
};

View File

@@ -1,11 +1,11 @@
[package]
name = "magnotia-storage"
name = "lumotia-storage"
version = "0.1.0"
edition = "2021"
description = "SQLite persistence, BM25 search, and file storage for Magnotia"
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
# SQLite with compile-time checked queries
# default-features = false strips sqlx's `any`, `macros`, `migrate`, `json` —
@@ -24,7 +24,7 @@ serde = { version = "1", features = ["derive"] }
# Logging
log = "0.4"
# Structured error derivation for magnotia_storage::Error.
# Structured error derivation for lumotia_storage::Error.
thiserror = "1"
# UUIDs for profile + profile_terms ids (v7 random).

View File

@@ -1,7 +1,7 @@
//! Storage-local typed error.
//!
//! Backend code that wants to branch on storage failure modes pattern-matches
//! on [`Error`] directly. The crate boundary into [`magnotia_core::error::MagnotiaError`]
//! on [`Error`] directly. The crate boundary into [`lumotia_core::error::MagnotiaError`]
//! flattens this into a [`MagnotiaError::Storage`] variant carrying a serde-friendly
//! `kind`, an `operation` label, and the Display output as `detail` — so the
//! frontend (which still receives stringified errors from Tauri commands today)
@@ -14,7 +14,7 @@
use std::borrow::Cow;
use std::path::PathBuf;
use magnotia_core::error::{MagnotiaError, StorageKind};
use lumotia_core::error::{MagnotiaError, StorageKind};
/// Kinds of database-open operation that can fail before the pool is ready.
#[derive(Debug, Clone, Copy)]

View File

@@ -1,28 +1,28 @@
use std::path::PathBuf;
pub fn app_data_dir() -> PathBuf {
magnotia_core::paths::app_paths().app_data_dir()
lumotia_core::paths::app_paths().app_data_dir()
}
/// Path to the SQLite database file.
pub fn database_path() -> PathBuf {
magnotia_core::paths::app_paths().database_path()
lumotia_core::paths::app_paths().database_path()
}
/// Directory for saved audio recordings.
pub fn recordings_dir() -> PathBuf {
magnotia_core::paths::app_paths().recordings_dir()
lumotia_core::paths::app_paths().recordings_dir()
}
/// Directory for crash dumps written by the Rust panic hook.
/// Each crash is a single text file: `<unix-ts>-<short-id>.crash`.
/// Used by the diagnostic-report bundler in Settings → About.
pub fn crashes_dir() -> PathBuf {
magnotia_core::paths::app_paths().crashes_dir()
lumotia_core::paths::app_paths().crashes_dir()
}
/// Directory for the rolling Rust log file (magnotia.log + rotated magnotia.log.1, etc).
/// Subscribers configured in src-tauri/src/lib.rs at startup.
pub fn logs_dir() -> PathBuf {
magnotia_core::paths::app_paths().logs_dir()
lumotia_core::paths::app_paths().logs_dir()
}

View File

@@ -1,5 +1,5 @@
[package]
name = "magnotia-transcription"
name = "lumotia-transcription"
version = "0.1.0"
edition = "2021"
description = "Speech-to-text engine wrappers, model management, and inference concurrency for Magnotia"
@@ -15,18 +15,18 @@ build = "build.rs"
# `whisper-vulkan` is a separate feature so a non-Vulkan target (Android
# without GPU drivers, a CPU-only Windows build) can pull in whisper-rs
# but skip the Vulkan backend. Build CPU-only with:
# cargo build -p magnotia-transcription --no-default-features --features whisper
# cargo build -p lumotia-transcription --no-default-features --features whisper
default = ["whisper", "whisper-vulkan"]
whisper = ["dep:whisper-rs"]
whisper-vulkan = ["whisper-rs?/vulkan"]
[dependencies]
magnotia-core = { path = "../core" }
lumotia-core = { path = "../core" }
# TranscriptionProvider async trait + EngineProfile + ProviderId. The
# trait lives in cloud-providers so an OEM licensee can implement it
# without depending on transcription internals.
magnotia-cloud-providers = { path = "../cloud-providers" }
lumotia-cloud-providers = { path = "../cloud-providers" }
# Async-trait for the LocalProviderAdapter impl.
async-trait = "0.1"
@@ -57,12 +57,12 @@ thiserror = "2"
tracing = "0.1"
[dev-dependencies]
# TcpListener fixture for the download resume tests (mirrors magnotia-llm).
# TcpListener fixture for the download resume tests (mirrors lumotia-llm).
# `macros` and `rt-multi-thread` enable #[tokio::test] and the multi-threaded
# scheduler used by the orchestrator tests.
tokio = { version = "1", features = ["rt", "rt-multi-thread", "sync", "net", "io-util", "macros"] }
tempfile = "3"
# Test-only — used by tests/thread_sweep.rs to label physical vs logical
# core counts in the scaling table. Production code uses the
# `magnotia_core::constants::inference_thread_count` helper instead.
# `lumotia_core::constants::inference_thread_count` helper instead.
num_cpus = "1"

View File

@@ -11,7 +11,7 @@
//! workspace ever pulls `tokenizers` into the dependency graph on a
//! Windows target. If we ever legitimately need it we can reintroduce
//! it via a sidecar (isolated process, separate CRT) rather than
//! linking it into `magnotia_lib`.
//! linking it into `lumotia_lib`.
//!
//! The check is advisory on non-Windows targets — it still prints a
//! cargo:warning if `tokenizers` appears, so the Windows failure isn't

View File

@@ -1,7 +1,7 @@
use std::sync::Arc;
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::{AudioSamples, TranscriptionOptions};
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::{AudioSamples, TranscriptionOptions};
use crate::local_engine::{LocalEngine, TimedTranscript};

View File

@@ -23,11 +23,11 @@ pub use transcribe_rs::SpeechModel;
pub use transcriber::{Transcriber, TranscriberCapabilities};
// Re-export the trait surface so downstream crates depend only on
// `magnotia_transcription` to access both local engines and the
// provider trait without a separate `magnotia_cloud_providers`
// `lumotia_transcription` to access both local engines and the
// provider trait without a separate `lumotia_cloud_providers`
// dependency. This is the seam an OEM licensee uses when they swap
// providers.
pub use magnotia_cloud_providers::{
pub use lumotia_cloud_providers::{
CostClass, EngineProfile, NetworkRequirement, ProviderCapabilities, ProviderId, ProviderKind,
ProviderTranscript, TranscriptionProvider,
};

View File

@@ -4,8 +4,8 @@ use std::time::Instant;
use transcribe_rs::{SpeechModel, TranscribeOptions, TranscriptionResult};
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::{
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::{
AudioSamples, EngineName, ModelId, Segment, Transcript, TranscriptionOptions,
};
@@ -28,7 +28,7 @@ pub struct SpeechModelAdapter(pub Box<dyn SpeechModel + Send>);
impl Transcriber for SpeechModelAdapter {
fn capabilities(&self) -> TranscriberCapabilities {
TranscriberCapabilities {
sample_rate: magnotia_core::constants::WHISPER_SAMPLE_RATE,
sample_rate: lumotia_core::constants::WHISPER_SAMPLE_RATE,
channels: 1,
supports_initial_prompt: false,
}

View File

@@ -2,9 +2,9 @@ use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::sync::{LazyLock, Mutex};
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::model_registry::{find_model, ModelFile};
use magnotia_core::types::{DownloadProgress, ModelId};
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::model_registry::{find_model, ModelFile};
use lumotia_core::types::{DownloadProgress, ModelId};
static ACTIVE_DOWNLOADS: LazyLock<Mutex<HashSet<String>>> =
LazyLock::new(|| Mutex::new(HashSet::new()));
@@ -40,12 +40,12 @@ impl Drop for DownloadReservation {
/// Windows: %LOCALAPPDATA%/magnotia/models
/// Unix: ~/.magnotia/models
pub fn models_dir() -> PathBuf {
magnotia_core::paths::app_paths().models_dir()
lumotia_core::paths::app_paths().models_dir()
}
/// Get the directory path where a specific model's files are stored.
pub fn model_dir(id: &ModelId) -> PathBuf {
magnotia_core::paths::app_paths().speech_model_dir(id)
lumotia_core::paths::app_paths().speech_model_dir(id)
}
/// Check whether all files for a model have been downloaded.
@@ -61,7 +61,7 @@ pub fn is_downloaded(id: &ModelId) -> bool {
/// List all downloaded model IDs.
pub fn list_downloaded() -> Vec<ModelId> {
magnotia_core::model_registry::all_models()
lumotia_core::model_registry::all_models()
.iter()
.filter(|m| is_downloaded(&m.id))
.map(|m| m.id.clone())
@@ -117,7 +117,7 @@ fn verified_manifest_path(dir: &Path) -> PathBuf {
}
fn verified_manifest_matches(
entry: &magnotia_core::model_registry::ModelEntry,
entry: &lumotia_core::model_registry::ModelEntry,
dir: &Path,
) -> bool {
let manifest = match std::fs::read_to_string(verified_manifest_path(dir)) {
@@ -140,7 +140,7 @@ fn verified_manifest_matches(
}
fn write_verified_manifest(
entry: &magnotia_core::model_registry::ModelEntry,
entry: &lumotia_core::model_registry::ModelEntry,
dir: &Path,
) -> std::io::Result<()> {
let mut lines = Vec::with_capacity(entry.files.len() + 1);
@@ -357,7 +357,7 @@ mod tests {
let list = list_downloaded();
// In test environment, no models are downloaded
// This just verifies the function doesn't panic
assert!(list.len() <= magnotia_core::model_registry::all_models().len());
assert!(list.len() <= lumotia_core::model_registry::all_models().len());
}
#[test]
@@ -481,7 +481,7 @@ mod tests {
let file = ModelFile {
filename: leak(dest.file_name().unwrap().to_string_lossy().into_owned()),
url: leak(format!("http://{addr}/fixture.bin")),
size: magnotia_core::types::Megabytes(0),
size: lumotia_core::types::Megabytes(0),
sha256: leak(expected_sha.clone()),
};
let id = ModelId::new("test-fixture");
@@ -516,7 +516,7 @@ mod tests {
let file = ModelFile {
filename: leak(dest.file_name().unwrap().to_string_lossy().into_owned()),
url: leak(format!("http://{addr}/fixture.bin")),
size: magnotia_core::types::Megabytes(0),
size: lumotia_core::types::Megabytes(0),
sha256: leak(expected_sha),
};
let id = ModelId::new("test-fixture");
@@ -571,7 +571,7 @@ mod tests {
let file = ModelFile {
filename: leak(dest.file_name().unwrap().to_string_lossy().into_owned()),
url: leak(format!("http://{addr}/fixture.bin")),
size: magnotia_core::types::Megabytes(0),
size: lumotia_core::types::Megabytes(0),
sha256: leak("0".repeat(64)),
};
let id = ModelId::new("test-fixture");
@@ -599,7 +599,7 @@ mod tests {
let file = ModelFile {
filename: leak(dest.file_name().unwrap().to_string_lossy().into_owned()),
url: leak(format!("http://{addr}/fixture.bin")),
size: magnotia_core::types::Megabytes(0),
size: lumotia_core::types::Megabytes(0),
sha256: leak("deadbeef".repeat(8)),
};
let id = ModelId::new("test-fixture");

View File

@@ -18,12 +18,12 @@
use std::sync::Arc;
use async_trait::async_trait;
use magnotia_cloud_providers::{
use lumotia_cloud_providers::{
CostClass, EngineProfile, ProviderCapabilities, ProviderId, ProviderKind, ProviderTranscript,
TranscriptionProvider,
};
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::types::{AudioSamples, TranscriptionOptions};
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::types::{AudioSamples, TranscriptionOptions};
use crate::local_engine::LocalEngine;
use crate::registry::EngineRegistry;
@@ -68,7 +68,7 @@ impl TranscriptionProvider for LocalProviderAdapter {
ProviderCapabilities {
sample_rate: local
.map(|c| c.sample_rate)
.unwrap_or(magnotia_core::constants::WHISPER_SAMPLE_RATE),
.unwrap_or(lumotia_core::constants::WHISPER_SAMPLE_RATE),
channels: local.map(|c| c.channels).unwrap_or(1),
initial_prompt_supported: local.map(|c| c.supports_initial_prompt).unwrap_or(false),
language_hint_supported: true,
@@ -153,7 +153,7 @@ mod tests {
use std::sync::atomic::{AtomicUsize, Ordering};
use magnotia_core::types::{Segment, Transcript};
use lumotia_core::types::{Segment, Transcript};
/// Mock provider that returns a canned transcript and counts
/// invocations. Used to validate the orchestrator's dispatch logic

View File

@@ -15,7 +15,7 @@
use std::collections::HashMap;
use std::sync::Arc;
use magnotia_cloud_providers::{ProviderId, TranscriptionProvider};
use lumotia_cloud_providers::{ProviderId, TranscriptionProvider};
/// Catalogue of providers known to the orchestrator.
pub struct EngineRegistry {
@@ -82,11 +82,11 @@ mod tests {
use super::*;
use async_trait::async_trait;
use magnotia_cloud_providers::{
use lumotia_cloud_providers::{
CostClass, EngineProfile, ProviderCapabilities, ProviderKind, ProviderTranscript,
};
use magnotia_core::error::Result;
use magnotia_core::types::{AudioSamples, Transcript, TranscriptionOptions};
use lumotia_core::error::Result;
use lumotia_core::types::{AudioSamples, Transcript, TranscriptionOptions};
struct DummyProvider {
id: ProviderId,

View File

@@ -9,8 +9,8 @@
//! `whisper` feature — `WhisperRsBackend` (direct whisper-rs, the only
//! path that pipes `initial_prompt`).
use magnotia_core::error::Result;
use magnotia_core::types::{Segment, TranscriptionOptions};
use lumotia_core::error::Result;
use lumotia_core::types::{Segment, TranscriptionOptions};
/// Static capabilities a `Transcriber` advertises to callers.
///

View File

@@ -10,10 +10,10 @@ use std::path::Path;
use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
use magnotia_core::error::{MagnotiaError, Result};
use magnotia_core::hardware::vulkan_loader_available;
use magnotia_core::tuning::{inference_thread_count, Workload};
use magnotia_core::types::{Segment, TranscriptionOptions};
use lumotia_core::error::{MagnotiaError, Result};
use lumotia_core::hardware::vulkan_loader_available;
use lumotia_core::tuning::{inference_thread_count, Workload};
use lumotia_core::types::{Segment, TranscriptionOptions};
use crate::transcriber::{Transcriber, TranscriberCapabilities};
@@ -42,7 +42,7 @@ impl WhisperRsBackend {
impl Transcriber for WhisperRsBackend {
fn capabilities(&self) -> TranscriberCapabilities {
TranscriberCapabilities {
sample_rate: magnotia_core::constants::WHISPER_SAMPLE_RATE,
sample_rate: lumotia_core::constants::WHISPER_SAMPLE_RATE,
channels: 1,
supports_initial_prompt: true,
}

View File

@@ -9,8 +9,8 @@
use std::env;
use std::time::Instant;
use magnotia_core::hardware::vulkan_loader_available;
use magnotia_core::tuning::{inference_thread_count, Workload};
use lumotia_core::hardware::vulkan_loader_available;
use lumotia_core::tuning::{inference_thread_count, Workload};
use whisper_rs::{FullParams, SamplingStrategy, WhisperContext, WhisperContextParameters};
#[test]