use crate::config::Config;
use crate::hook::Host;
use crate::index::{self, Index};
use crate::session::Session;
use crate::{embed, paths, skill};
use serde::Deserialize;
use std::io::Read;
#[derive(Debug, Default, Deserialize)]
struct RawEvent {
#[serde(default)]
session_id: String,
#[serde(default)]
source: String,
}
pub fn run(host: Host) -> anyhow::Result<()> {
if let Err(e) = session_start(host) {
crate::trace::debug("session-start failed", &e);
}
Ok(())
}
fn session_start(host: Host) -> anyhow::Result<()> {
let mut buf = String::new();
std::io::stdin().read_to_string(&mut buf)?;
let ev: RawEvent = serde_json::from_str(&buf).unwrap_or_default();
reindex(host);
if should_rearm(&ev.source) && !ev.session_id.is_empty() {
let path = paths::session_path(&ev.session_id);
let mut session = Session::load(&path);
session.clear();
let _ = session.save(&path);
}
Ok(())
}
fn reindex(host: Host) {
let (cfg, _file) = Config::load(host);
let skills = match skill::discover(&cfg.roots) {
Ok(s) => s,
Err(e) => return crate::trace::debug("session-start: skill discovery failed", &e),
};
let embedder = match embed::build(&cfg.model) {
Ok(e) => e,
Err(e) => return crate::trace::debug("session-start: embedder build failed", &e),
};
let index_path = paths::index_path(host);
let prev = Index::load(&index_path).ok().flatten();
match index::build(&skills, embedder.as_ref(), prev.as_ref()) {
Ok(idx) => {
if let Err(e) = idx.save(&index_path) {
crate::trace::debug("session-start: saving reindexed index failed", &e);
}
}
Err(e) => crate::trace::debug("session-start: index build failed", &e),
}
}
fn should_rearm(source: &str) -> bool {
source.eq_ignore_ascii_case("compact")
}
#[cfg(test)]
mod tests {
use super::*;
use crate::session::Source;
#[test]
fn only_compact_rearms() {
assert!(should_rearm("compact"));
assert!(!should_rearm("startup"));
assert!(!should_rearm("resume"));
assert!(!should_rearm(""));
}
#[test]
fn clear_on_compact_empties_the_ledger() {
let mut s = Session::default();
s.mark("pdf", Source::Ski);
s.mark("xlsx", Source::Model);
if should_rearm("compact") {
s.clear();
}
assert!(s.loaded.is_empty());
}
}