Skip to main content

ailoop_history/
errors.rs

1//! Failure surfaces of compaction and snapshot validation.
2
3use thiserror::Error;
4
5/// Failure surface of [`CompactionStrategy::compact`] (and therefore of
6/// [`History::compact_if_needed`]).
7///
8/// The façade [`Conversation::run`](https://docs.rs/ailoop) /
9/// [`Conversation::stream`](https://docs.rs/ailoop) wraps this in
10/// [`EngineError::Context`](https://docs.rs/ailoop) when compaction
11/// fails mid-run.
12///
13/// [`CompactionStrategy::compact`]: crate::CompactionStrategy::compact
14/// [`History::compact_if_needed`]: crate::History::compact_if_needed
15#[derive(Debug, Error)]
16#[non_exhaustive]
17pub enum CompactionError {
18    /// History has fewer messages than `preserve_n_last`, so there is
19    /// nothing the strategy can drop. Indicates a configuration bug
20    /// rather than a transient failure: raise the budget or lower
21    /// [`HistoryBuilder::preserve_n_last`].
22    ///
23    /// [`HistoryBuilder::preserve_n_last`]: crate::HistoryBuilder::preserve_n_last
24    #[error("Not enough history to compact")]
25    NotEnoughHistory,
26
27    /// A strategy that calls a [`ailoop_core::CompletionModel`]
28    /// (notably [`SummarizeStrategy`](crate::SummarizeStrategy))
29    /// failed to produce a summary. The original error is rendered
30    /// as a string to keep [`CompactionError`] a non-generic,
31    /// object-safe enum usable behind `Box<dyn CompactionStrategy>`.
32    #[error("Summarization failed: {0}")]
33    SummarizationFailed(String),
34}
35
36/// Returned by [`ConversationSnapshot::new`] and
37/// [`History::from_messages`] when the supplied parallel
38/// vectors are inconsistent. Surfaces at restore time so a malformed
39/// snapshot fails loudly instead of corrupting state silently.
40///
41/// [`ConversationSnapshot::new`]: crate::ConversationSnapshot::new
42/// [`History::from_messages`]: crate::History::from_messages
43#[derive(Debug, Error, PartialEq, Eq)]
44#[non_exhaustive]
45pub enum FromMessagesError {
46    /// `messages` and `pinned` were not the same length. Both fields
47    /// carry the observed lengths so callers can report the exact
48    /// mismatch.
49    #[error(
50        "messages and pinned must have the same length (messages: {messages}, pinned: {pinned})"
51    )]
52    LengthMismatch {
53        /// Observed length of the messages vector.
54        messages: usize,
55        /// Observed length of the pin mask.
56        pinned: usize,
57    },
58}