remem-ai 0.4.4

Persistent memory for Claude Code — single binary, zero subprocesses
Documentation
use crate::db;
use crate::memory::format::ParsedObservation;

pub(crate) fn clone_pending_batch(
    batch: &[&db::PendingObservation],
) -> Vec<db::PendingObservation> {
    batch
        .iter()
        .map(|pending| db::PendingObservation {
            id: pending.id,
            host: pending.host.clone(),
            session_id: pending.session_id.clone(),
            project: pending.project.clone(),
            tool_name: pending.tool_name.clone(),
            tool_input: pending.tool_input.clone(),
            tool_response: pending.tool_response.clone(),
            cwd: pending.cwd.clone(),
            created_at_epoch: pending.created_at_epoch,
            updated_at_epoch: pending.updated_at_epoch,
            status: pending.status.clone(),
            attempt_count: pending.attempt_count,
            next_retry_epoch: pending.next_retry_epoch,
            last_error: pending.last_error.clone(),
        })
        .collect()
}

pub(crate) fn split_timeout_range(
    start: usize,
    end: usize,
    min_batch_size: usize,
) -> Option<[(usize, usize); 2]> {
    let batch_len = end.checked_sub(start)?;
    if batch_len <= min_batch_size {
        return None;
    }

    let mid = start + (batch_len / 2);
    if mid > start && mid < end {
        Some([(start, mid), (mid, end)])
    } else {
        None
    }
}

pub(crate) fn collect_observation_titles(observations: &[ParsedObservation]) -> Vec<String> {
    observations
        .iter()
        .filter_map(|observation| observation.title.as_deref().map(str::to_string))
        .collect()
}