Skip to main content

MemoryStore

Struct MemoryStore 

Source
pub struct MemoryStore { /* private fields */ }
Expand description

The main memory store — manages agent-level markdown files with a hybrid search index.

Blueprint-managed files (SOUL.md, lifecycle files) live in config_dir (.starpod/config/). Runtime data files (daily logs, agent-written files) live in agent_home (.starpod/). The FTS5/vector database lives in db_dir (.starpod/db/). User-specific files (USER.md, MEMORY.md, daily logs) are handled by UserMemoryView, not this struct.

§Search Pipeline

  • search — FTS5 + temporal decay (always available)
  • vector_search — cosine similarity (requires embedder)
  • hybrid_search — FTS5 + vector → RRF fusion → decay → MMR

§Security

All file read/write operations validate paths via scoring::validate_path to prevent directory traversal. Writes are capped at 1 MB.

Implementations§

Source§

impl MemoryStore

Source

pub async fn new( agent_home: &Path, config_dir: &Path, db_dir: &Path, ) -> Result<Self>

Create a new MemoryStore.

  • agent_home: the .starpod/ directory (runtime data, general read/write)
  • config_dir: the .starpod/config/ directory (SOUL.md, lifecycle files)
  • db_dir: the .starpod/db/ directory (contains memory.db)
Source

pub async fn new_user(user_dir: &Path) -> Result<Self>

Create a lightweight per-user memory store.

Uses user_dir for both file storage and the SQLite database (user_dir/memory.db). Skips seeding default lifecycle files (SOUL.md, HEARTBEAT.md, etc.) since those belong to the agent-level store.

The store has max_connections(1) to keep resource usage low when many users each get their own store.

Any existing .md files in user_dir are indexed on creation.

Source

pub fn agent_home(&self) -> &Path

Get the agent home directory path (.starpod/).

Source

pub fn config_dir(&self) -> &Path

Get the config directory path (.starpod/config/).

Source

pub fn has_bootstrap(&self) -> bool

Returns true if BOOTSTRAP.md exists and has non-empty content.

Source

pub fn clear_bootstrap(&self) -> Result<()>

Delete BOOTSTRAP.md (called after successful bootstrap execution).

Source

pub fn bootstrap_context(&self) -> Result<String>

Build agent-level bootstrap context from SOUL.md only.

User-specific context (USER.md, MEMORY.md, daily logs) is handled by UserMemoryView::bootstrap_context().

Source

pub fn set_half_life_days(&mut self, days: f64)

Set the half-life for temporal decay on search results.

Source

pub fn set_mmr_lambda(&mut self, lambda: f64)

Set the MMR lambda for diversity vs relevance balance.

Source

pub fn set_chunk_size(&mut self, size: usize)

Set the target chunk size in characters for indexing.

Source

pub fn set_chunk_overlap(&mut self, overlap: usize)

Set the overlap in characters between chunks.

Source

pub fn set_bootstrap_file_cap(&mut self, cap: usize)

Set the maximum characters to include from a single file in bootstrap context.

Source

pub async fn search( &self, query: &str, limit: usize, ) -> Result<Vec<SearchResult>>

Full-text search across all indexed content.

Results are re-ranked with temporal decay: recent daily logs score higher than older ones, while evergreen files (SOUL.md, HEARTBEAT.md) are unaffected.

Source

pub fn set_embedder(&mut self, embedder: Arc<dyn Embedder>)

Set the embedder for vector search.

Vector search: embed the query, compare against stored vectors, return top-K.

Returns empty vec if no embedder is configured.

Hybrid search: run FTS5 + vector search, fuse with RRF, apply MMR.

Falls back to FTS5-only when no embedder is configured. Pipeline: FTS5 + vector → RRF fusion → temporal decay → MMR diversity.

Source

pub fn read_file(&self, name: &str) -> Result<String>

Read a file from the appropriate directory (config_dir for config files, agent_home otherwise).

Source

pub async fn write_file(&self, name: &str, content: &str) -> Result<()>

Write a file and reindex it.

Config files (SOUL.md, lifecycle files) are written to config_dir, everything else to agent_home.

Source

pub async fn append_daily(&self, text: &str) -> Result<()>

Append a timestamped entry to today’s daily log.

Source

pub async fn reindex(&self) -> Result<()>

Full reindex of agent-level markdown files.

Indexes config files from config_dir (SOUL.md, lifecycle files) and runtime files from agent_home (memory/ daily logs, agent-written files). User-level files are not indexed here — they’re handled per-user.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more