From b193e187d95b43971b05ffa283d000fbbc5eebfe Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Thu, 13 Aug 2026 06:18:59 +0300 Subject: [PATCH 1/2] feat(module): expose query-less document recall Co-authored-by: Medulla --- api/src/null.rs | 8 ++++++++ api/src/provider/content.rs | 15 +++++++++++++++ crates/tinymemory-module/src/provider.rs | 14 ++++++++++++++ crates/tinymemory-module/src/service/mod.rs | 13 +++++++++++++ 4 files changed, 50 insertions(+) diff --git a/api/src/null.rs b/api/src/null.rs index df2bc69..1956100 100644 --- a/api/src/null.rs +++ b/api/src/null.rs @@ -266,6 +266,14 @@ impl MemoryDocuments for NullMemoryProvider { ) -> Result { unsupported(Capability::Documents) } + + async fn recall_documents( + &self, + _namespace: &str, + _limit: usize, + ) -> Result { + unsupported(Capability::Documents) + } } #[async_trait] diff --git a/api/src/provider/content.rs b/api/src/provider/content.rs index cde5867..53a1a2d 100644 --- a/api/src/provider/content.rs +++ b/api/src/provider/content.rs @@ -137,6 +137,21 @@ pub trait MemoryDocuments: Send + Sync { query: &str, limit: usize, ) -> Result; + + /// Recall the highest-ranked context from a namespace without a query. + /// + /// This is a distinct engine operation rather than a query with an empty + /// string: query-less recall applies the namespace's freshness and + /// priority ranking without introducing a synthetic search term. + /// + /// # Errors + /// + /// Backend failures only; an empty namespace returns empty context. + async fn recall_documents( + &self, + namespace: &str, + limit: usize, + ) -> Result; } /// The time-ordered summary tree: buffered leaves rolled up into hour → day → diff --git a/crates/tinymemory-module/src/provider.rs b/crates/tinymemory-module/src/provider.rs index 123a097..710f56a 100644 --- a/crates/tinymemory-module/src/provider.rs +++ b/crates/tinymemory-module/src/provider.rs @@ -392,6 +392,20 @@ impl MemoryDocuments for ModuleMemoryProvider { .map_err(|error| Self::other("query_documents", error))?; Self::cross(&context, "convert document query result") } + + async fn recall_documents( + &self, + namespace: &str, + limit: usize, + ) -> Result { + let limit = u32::try_from(limit).unwrap_or(u32::MAX); + let context = self + .client + .recall_namespace_context_data(namespace, limit) + .await + .map_err(|error| Self::other("recall_documents", error))?; + Self::cross(&context, "convert document recall result") + } } #[async_trait] diff --git a/crates/tinymemory-module/src/service/mod.rs b/crates/tinymemory-module/src/service/mod.rs index f39800f..56dafd1 100644 --- a/crates/tinymemory-module/src/service/mod.rs +++ b/crates/tinymemory-module/src/service/mod.rs @@ -359,6 +359,19 @@ impl MemoryService { Ok(response) } + async fn recall_documents( + &self, + namespace: String, + limit: usize, + ) -> BusResult { + let response = require_family!(self, as_documents, Capability::Documents) + .recall_documents(&namespace, limit) + .await + .map_err(|error| into_bus_error(&error))?; + ensure_response_fits(&response, "RecallDocuments")?; + Ok(response) + } + async fn append(&self, request: IngestRequest) -> BusResult<()> { require_family!(self, as_tree, Capability::Tree) .append(request) From c5796a2d0bfcbf0605431ccc6adf7b9f8f80b364 Mon Sep 17 00:00:00 2001 From: Steven Enamakel Date: Thu, 13 Aug 2026 06:27:10 +0300 Subject: [PATCH 2/2] fix(api): preserve provider compatibility Co-authored-by: Medulla --- api/src/provider/content.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/api/src/provider/content.rs b/api/src/provider/content.rs index 53a1a2d..ba99bfa 100644 --- a/api/src/provider/content.rs +++ b/api/src/provider/content.rs @@ -18,6 +18,7 @@ use async_trait::async_trait; +use crate::capabilities::Capability; use crate::chunks::Chunk; use crate::error::MemoryError; use crate::provider::types::{IngestItem, IngestOutcome, SourceScope}; @@ -146,12 +147,16 @@ pub trait MemoryDocuments: Send + Sync { /// /// # Errors /// - /// Backend failures only; an empty namespace returns empty context. + /// [`MemoryError::Unsupported`] when a provider predating this optional + /// operation does not implement it, otherwise backend failures. An empty + /// namespace returns empty context. async fn recall_documents( &self, - namespace: &str, - limit: usize, - ) -> Result; + _namespace: &str, + _limit: usize, + ) -> Result { + Err(MemoryError::unsupported(Capability::Documents)) + } } /// The time-ordered summary tree: buffered leaves rolled up into hour → day →