LongTermStore

org.llm4s.agent.harness.LongTermStore
See theLongTermStore companion object
@Experimental
trait LongTermStore extends AppliedKeys

Items kept across threads and runs, by (Namespace, key): /memories/ files (StoreFileBackend) and semantic memory (F7). Its target is Transactional (C4).

The one mutation primitive is modify, a read-modify-write in the store's own transaction, serialisable within its namespace: the outcome already recorded for the effect's key, or the change decided against a StoreView and applied, bounds checked and (key, outcome) recorded with it. An edit therefore never loses a concurrent write, a check that spans keys cannot be raced, and a replay whose first attempt landed returns the first outcome before it re-reads anything. put and delete wrap it in ReplayGuard.transactional; a backend over the store uses modify the same way with its own keys.

ujson.Value is mutable, so a store copies every value it is given and every value it hands out. An implementation keeps its applied keys only until C4's guard forgets them, and never by age.

Attributes

Companion
object
Graph
Supertypes
trait AppliedKeys
class Object
trait Matchable
class Any
Known subtypes

Members list

Value members

Abstract methods

def get(ns: Namespace, key: String): Result[Option[StoreItem]]
def list(ns: Namespace, prefix: String, limit: Int): Result[Listing[StoreEntry]]

The entries of ns whose key starts with prefix, in key order, at most limit.

The entries of ns whose key starts with prefix, in key order, at most limit.

Attributes

def modify[A : ReadWriter](ns: Namespace, key: String, effect: EffectKey, token: FencingToken)(change: StoreView => Result[StoreChange[A]]): Result[A]

In one transaction, serialisable within ns, fenced by token (C4's AppliedKeys): a token older than the newest seen for effect.scope is refused with a Left and changes nothing; otherwise it becomes the newest, and then: if effect was applied, its recorded outcome and no write; otherwise change, decided against the namespace as it is now, which may refuse (Left: nothing written or recorded), then the namespace's and item's bounds, then the write and (effect, outcome) recorded together. An over-limit change is a BackendRefused. The newest token per scope is kept as long as the store keeps that thread's data: durably, in a real store.

In one transaction, serialisable within ns, fenced by token (C4's AppliedKeys): a token older than the newest seen for effect.scope is refused with a Left and changes nothing; otherwise it becomes the newest, and then: if effect was applied, its recorded outcome and no write; otherwise change, decided against the namespace as it is now, which may refuse (Left: nothing written or recorded), then the namespace's and item's bounds, then the write and (effect, outcome) recorded together. An over-limit change is a BackendRefused. The newest token per scope is kept as long as the store keeps that thread's data: durably, in a real store.

The outcome returned is the recorded one, decoded, so a first run and its replay return the same value. A's codec must be a pure function of its value: C4's guard encodes the outcome again for its journal, and a codec that answered differently would record two things.

Attributes

def search(ns: Namespace, query: String, limit: Int): Result[Listing[StoreEntry]]

The entries of ns matching query, at most limit; each store documents how it matches.

The entries of ns matching query, at most limit; each store documents how it matches.

Attributes

Concrete methods

final def delete(ns: Namespace, key: String, ctx: FileContext): Result[Boolean]

Deletes key, guarded under store.delete: true when it existed.

Deletes key, guarded under store.delete: true when it existed.

Attributes

final def put(ns: Namespace, key: String, value: Value, ctx: FileContext): Result[Boolean]

Writes value at key, guarded under store.put: true when the key was new.

Writes value at key, guarded under store.put: true when the key was new.

Attributes

Inherited and Abstract methods

def forget(key: EffectKey, token: FencingToken): Result[Unit]

Removes key from the applied-keys table, fenced by token as described above: Left if token is older than the newest token seen for key.scope; Right(()) if the key is not there.

Removes key from the applied-keys table, fenced by token as described above: Left if token is older than the newest token seen for key.scope; Right(()) if the key is not there.

Attributes

Inherited from:
AppliedKeys

Concrete fields

C4's class for this target.

C4's class for this target.

Attributes