use std::path::Path;
use crate::collective::Route;
use crate::harness::Level;
use crate::vectors::model::{built_with, enabled, model_dir, model_present};
const LESSONS: &str = "lessons.jsonl";
#[must_use]
pub fn checks(routes: &[Route]) -> Vec<(Level, String)> {
if !cfg!(feature = "vectors") {
return vec![(Level::Ok, "vectors: not in this build (--no-default-features): end-of-turn checks match words only".into())];
}
if !enabled() {
return vec![(Level::Ok, "vectors: off (BORG_VECTORS=off): end-of-turn checks match words only".into())];
}
against(routes, &model_dir())
}
pub(super) fn against(routes: &[Route], model: &Path) -> Vec<(Level, String)> {
if !model_present(model) {
let msg = format!("vectors: model missing at {} (end-of-turn checks match words only): run `borg vectors --fetch`", model.display());
return vec![(Level::Warn, msg)];
}
let warns: Vec<(Level, String)> = routes
.iter()
.filter_map(|r| match r {
Route::Collective { name, home, .. } => index_problem(&home.join(LESSONS), model).map(|p| (name, home.join(LESSONS), p)),
Route::Off => None,
})
.map(|(name, lessons, p)| (Level::Warn, format!("vectors: collective {name:?} {p}: run `borg vectors --rebuild --store {}`", lessons.display())))
.collect();
let ok = (Level::Ok, format!("vectors: model at {}", model.display()));
std::iter::once(ok).chain(warns).collect()
}
fn index_problem(lessons: &Path, model: &Path) -> Option<&'static str> {
if !lessons.is_file() {
return None;
}
match built_with(lessons, model) {
None => Some("has no vector index"),
Some(false) => Some("has a vector index built with another model"),
Some(true) => None,
}
}
#[must_use]
pub fn hint() -> Option<String> {
let model = model_dir();
(enabled() && !model_present(&model))
.then(|| format!("vectors: model missing at {}: `borg setup` or `borg vectors --fetch` turns on vector recall", model.display()))
}