use super::*;
#[cfg(feature = "bundled-embedder")]
const DEFAULT_CONFIG_TOML: &str = "\
# Auto-generated by `mnem init`. Override with `mnem config set <key> <val>`
# or edit this file. See https://github.com/Uranid/mnem/blob/main/CONFIGURABLES.md
[embed]
provider = \"onnx\"
model = \"all-MiniLM-L6-v2\"
";
#[cfg(not(feature = "bundled-embedder"))]
const DEFAULT_CONFIG_TOML: &str = "\
# Auto-generated by `mnem init`. Override with `mnem config set <key> <val>`
# or edit this file. See https://github.com/Uranid/mnem/blob/main/CONFIGURABLES.md
[embed]
provider = \"ollama\"
model = \"nomic-embed-text\"
";
#[cfg(feature = "bundled-embedder")]
const DEFAULT_PROVIDER_DESC: &str = "onnx:all-MiniLM-L6-v2";
#[cfg(not(feature = "bundled-embedder"))]
const DEFAULT_PROVIDER_DESC: &str = "ollama:nomic-embed-text";
#[derive(clap::Args, Debug)]
#[command(after_long_help = "\
Examples:
mnem init # create .mnem/ in the current directory
mnem init ~/notes # create ~/notes/.mnem/
mnem -R ~/notes status # verify by reading op_id + head commit
")]
pub(crate) struct Args {
pub path: Option<std::path::PathBuf>,
}
pub(crate) fn run(_override: Option<&Path>, args: Args) -> Result<()> {
let target = args
.path
.unwrap_or_else(|| std::env::current_dir().unwrap_or_default());
let data_dir = target.join(repo::MNEM_DIR);
if data_dir.exists() {
bail!(
"already a mnem repository at {}\n\
hint: remove the existing `.mnem/` if you meant a fresh repo, or run \
`mnem status` to inspect it. See docs/RUNBOOK.md#6-mid-commit-crash-recovery \
for recovery semantics.",
data_dir.display()
);
}
let (bs, ohs) = repo::create_or_open_stores(&data_dir)?;
let r = ReadonlyRepo::init(bs, ohs)?;
let cfg_path = config::path_of(&data_dir);
if !cfg_path.exists() {
match std::fs::write(&cfg_path, DEFAULT_CONFIG_TOML) {
Ok(()) => {
println!(
" seeded config: {} ([embed] {})",
cfg_path.display(),
DEFAULT_PROVIDER_DESC
);
}
Err(e) => {
eprintln!(
"(warn: failed to seed {}: {e}; run `mnem config set embed.provider {}` manually)",
cfg_path.display(),
DEFAULT_PROVIDER_DESC.split(':').next().unwrap_or("ollama")
);
}
}
}
seed_anchor_node(&r, &data_dir);
println!("initialised mnem repo in {}", data_dir.display());
println!(" root op: {}", r.op_id());
crate::global::register_repo(&target);
Ok(())
}
pub(crate) fn init_mnem_dir(parent: &Path) -> Result<()> {
let data_dir = parent.join(repo::MNEM_DIR);
if data_dir.exists() {
return Ok(());
}
let (bs, ohs) = repo::create_or_open_stores(&data_dir)?;
let r = ReadonlyRepo::init(bs, ohs)?;
let cfg_path = config::path_of(&data_dir);
if !cfg_path.exists() {
let _ = std::fs::write(&cfg_path, DEFAULT_CONFIG_TOML);
}
seed_anchor_node(&r, &data_dir);
Ok(())
}
use mnem_core::anchor::ANCHOR_NODE_UUID as ANCHOR_NODE_ID;
const ANCHOR_CHANGE_ID_BYTES: [u8; 16] = *b"mnem/anchor/v1\0\0";
const ANCHOR_TIME_MICROS: u64 = 0;
fn seed_anchor_node(repo: &ReadonlyRepo, _data_dir: &std::path::Path) {
use mnem_core::id::ChangeId;
use mnem_core::repo::CommitOptions;
let anchor_id = NodeId::parse_uuid(ANCHOR_NODE_ID)
.expect("ANCHOR_NODE_ID is a valid UUID; this is a compile-time constant");
let node = Node::new(anchor_id, "Meta");
let mut tx = repo.start_transaction();
match tx.add_node(&node) {
Ok(_) => {}
Err(_) => return,
}
let opts = CommitOptions::new("mnem init", "seed anchor node")
.with_time_micros(ANCHOR_TIME_MICROS)
.with_change_id(ChangeId::from_bytes_raw(ANCHOR_CHANGE_ID_BYTES));
let _ = tx.commit_opts(opts);
}