Skip to main content

innate_core/
lib.rs

1pub mod backup;
2pub mod cli;
3pub mod daemon;
4pub mod embedding;
5pub mod entities;
6pub mod errors;
7pub mod hook;
8pub mod install;
9pub mod kb;
10pub mod llm;
11pub mod llm_trace;
12pub mod mcp;
13pub mod migrate;
14pub mod paths;
15pub mod refine;
16pub mod settings;
17pub mod storage;
18pub mod upgrade;
19pub mod utils;
20pub mod web;
21
22#[cfg(test)]
23mod tests;
24
25pub use errors::{InnateError, Result};
26pub use kb::{
27    AbstainReason, AppraiseParams, Contributor, CurateReport, FlaggedPoint, KnowledgeBase,
28    RecallParams, RecallResult, RecordParams, Situation, Tier, Valence, Verdict, APPRAISE_ADVISORY,
29};
30
31/// Open a KnowledgeBase at `db_path`, injecting LLM providers from `~/.innate/settings.json`
32/// if configured. Falls back to DummyEmbeddingProvider + HeuristicDistiller when no LLM
33/// settings are present.
34pub fn open_kb(db_path: impl AsRef<std::path::Path>) -> Result<KnowledgeBase> {
35    use std::sync::Arc;
36    let s = settings::load()?;
37
38    let embedding: Option<Arc<dyn embedding::EmbeddingProvider>> = s.embedding.as_ref().map(|c| {
39        Arc::new(llm::LlmEmbeddingProvider::new(c.clone())) as Arc<dyn embedding::EmbeddingProvider>
40    });
41
42    // When a remote LLM distiller is configured, wrap it with a deterministic
43    // fallback so knowledge creation never depends on the LLM staying available:
44    // the LLM gets the first 2 attempts per log (quality); after that the
45    // deterministic HeuristicDistiller guarantees capture (stability).
46    let distiller: Option<Arc<dyn refine::Distiller>> = s.llm.as_ref().map(|c| {
47        let primary = llm::build_distiller(c) as Arc<dyn refine::Distiller>;
48        Arc::new(refine::ResilientDistiller::new(
49            primary,
50            Arc::new(refine::HeuristicDistiller),
51            2,
52        )) as Arc<dyn refine::Distiller>
53    });
54
55    let kb = KnowledgeBase::open_with(db_path, embedding, None, distiller, None, None)?;
56    // Opt-in offline reranker (part d): wired only when an LLM is configured. recall
57    // invokes it solely when a caller sets rerank=true, so the hook path stays no-LLM.
58    let kb = match s.llm.as_ref() {
59        Some(c) => kb.with_reranker(Arc::new(llm::LlmReranker::new(c.clone()))),
60        None => kb,
61    };
62    Ok(kb)
63}