pub struct Summarizing { /* private fields */ }Expand description
LLM-powered summarisation of old turns when context fills.
Since Step 18.5 (#247) this provider owns no summarisation logic of its
own: when its anchored fullness figure crosses the budget it delegates to
the SAME prune → boundary → redacted summary → marker assembly pipeline
the agentic loop uses ([crate::agentic::compress], Step 18.4). The
pre-18.4 implementation — its own prompt template, placeholder text, and
anti-thrash counters — is deleted; the summary message in history is now
the pipeline’s marked compaction message ([SUMMARY_PREFIX]).
Fullness tracking is unchanged (Step 18.1): last backend-reported prompt
size plus the estimated content delta since — the old per-turn
input + output running sum double-counted history and triggered
spurious compressions.
Continuity (Step 18.5): the latest compaction message is offered to the
caller once via MemoryProvider::take_compaction_record for durable
persistence, and MemoryProvider::restore_turns rehydrates it — the
restored working set is [compaction message] + [turns recorded after it], so the next compression chains off the previous summary instead of
re-summarizing from scratch.
Configure: [memory] provider = "summarizing", plus an optional explicit
context_tokens override. The compression budget (max_tokens) is a
construction-time value injected by the caller with the same precedence
as TokenBudget (Step 18.2, #247): explicit config override →
capability-derived (max_ok_input else safe_context) →
DEFAULT_CONTEXT_TOKENS. Fixed per session; the loop’s pre-send guard
tracks mid-session capability ratchets live.
Implementations§
Source§impl Summarizing
impl Summarizing
pub fn new(max_tokens: u32) -> Self
Sourcepub fn with_estimation(
self,
est: TokenEstimation,
summary_input_cap_floor_chars: usize,
) -> Self
pub fn with_estimation( self, est: TokenEstimation, summary_input_cap_floor_chars: usize, ) -> Self
Builder: set the token-estimation heuristic + summarizer cap floor from
config ([context.estimation] / [context] summary_input_cap_floor_chars).
Sourcepub fn with_budget(self, tokens: u32) -> Self
pub fn with_budget(self, tokens: u32) -> Self
Inject a resolved token budget (builder form of the max_tokens
constructor argument). Same ≥1 clamp as Summarizing::new.
See TokenBudget::with_budget for the resolution precedence the
caller is expected to apply (Step 18.2, #247).
Sourcepub fn with_summarizer(
self,
f: impl Fn(String) -> SummarizeFuture + Send + Sync + 'static,
) -> Self
pub fn with_summarizer( self, f: impl Fn(String) -> SummarizeFuture + Send + Sync + 'static, ) -> Self
Inject a summariser (required for real summaries; tests can use a
stub). Takes the loop’s async crate::agentic::SummarizeFn shape
since Step 18.5 — the TUI passes the very same summarizer it builds
for the loop, so there is exactly one HTTP wiring. The old sync
Fn(&str) -> Result<String> form (whose TUI impl blocked inside
sync_turn) is gone with the logic that called it.
Trait Implementations§
Source§impl MemoryProvider for Summarizing
impl MemoryProvider for Summarizing
Source§fn build_messages(&self, system_prompt: &str, new_task: &str) -> Vec<MemMessage>
fn build_messages(&self, system_prompt: &str, new_task: &str) -> Vec<MemMessage>
Source§fn sync_turn<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 mut self,
user: &'life1 str,
assistant: &'life2 str,
metrics: &'life3 TurnMetrics,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn sync_turn<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 mut self,
user: &'life1 str,
assistant: &'life2 str,
metrics: &'life3 TurnMetrics,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Source§fn reset(&mut self)
fn reset(&mut self)
Source§fn restore_turns(&mut self, turns: &[ConversationTurn])
fn restore_turns(&mut self, turns: &[ConversationTurn])
Source§fn take_compaction_record(&mut self) -> Option<String>
fn take_compaction_record(&mut self) -> Option<String>
user = the marked message, assistant = empty, token
columns NULL — it is not a backend-measured turn) so a later restore
can rehydrate the same working-set shape via Self::restore_turns.
Default: None — providers that never compress mint nothing.Source§fn on_pre_compress<'life0, 'life1, 'async_trait>(
&'life0 self,
_messages: &'life1 [MemMessage],
) -> Pin<Box<dyn Future<Output = String> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn on_pre_compress<'life0, 'life1, 'async_trait>(
&'life0 self,
_messages: &'life1 [MemMessage],
) -> Pin<Box<dyn Future<Output = String> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
messages; return it as a string
to include in the compression summary. Return empty string for nothing.Source§fn usage(&self) -> Option<(String, usize, usize)>
fn usage(&self) -> Option<(String, usize, usize)>
/memory command).
Returns (label, current, max) — e.g. ("turns", 12, 20).Source§fn initialize<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 SessionContext,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn initialize<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_ctx: &'life1 SessionContext,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn system_prompt_block(&self) -> Option<String>
fn system_prompt_block(&self) -> Option<String>
Source§fn prefetch<'life0, 'life1, 'async_trait>(
&'life0 self,
_query: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn prefetch<'life0, 'life1, 'async_trait>(
&'life0 self,
_query: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn on_session_end<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_messages: &'life1 [MemMessage],
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn on_session_end<'life0, 'life1, 'async_trait>(
&'life0 mut self,
_messages: &'life1 [MemMessage],
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn replace_note(&mut self, _old_substring: &str, _new_text: &str) -> Result<()>
fn replace_note(&mut self, _old_substring: &str, _new_text: &str) -> Result<()>
old_substring with
new_text (Step 19.3 — the save_note tool’s replace action).
Default: NotesUnsupported, same routing contract as add_note.Source§fn remove_note(&mut self, _substring: &str) -> Result<()>
fn remove_note(&mut self, _substring: &str) -> Result<()>
substring (Step 19.3 —
the save_note tool’s remove action).
Default: NotesUnsupported, same routing contract as add_note.Auto Trait Implementations§
impl !RefUnwindSafe for Summarizing
impl !UnwindSafe for Summarizing
impl Freeze for Summarizing
impl Send for Summarizing
impl Sync for Summarizing
impl Unpin for Summarizing
impl UnsafeUnpin for Summarizing
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<T> ErasedDestructor for Twhere
T: 'static,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more