Help us shape the future of Go! Take the 2026 Go Developer Survey

inmemory

package module
v0.1.0-preview.17 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package inmemory is an in-memory store for development and tests: no PostgreSQL. It keeps only what the contract needs (insert a finalized record, read one back, the text search, when each record was last injected, the embeddings of contract 1.6 with their nearest-neighbour search, and the lessons view's read of contract 1.7), honouring scope and the authorization bounds the way the PostgreSQL store's row-level security does. Its text search is the .NET in-memory store's: words normalized to Unicode form KC and lower-cased, the English stopwords PostgreSQL drops left out of a query, and a record matching at least the minimum number of query terms (fewer for a shorter query), weighted 3 for the task summary and 1 each for the task ID and the lesson. Nothing survives the process.

It is its own module, so the core requires no module: Unicode normalization is golang.org/x/text.

Index

Constants

View Source
const MaxIndexedLength = 100_000

MaxIndexedLength is the most text indexed per record, in UTF-16 code units, across its task ID, task summary and lesson in that order: the bound the PostgreSQL store's search column applies.

Variables

View Source
var ErrAuthorizationDenied = ae.ErrAuthorizationDenied

ErrAuthorizationDenied is a record whose scope lies outside the authorization bounds: the core's agentexperience.ErrAuthorizationDenied, so errors.Is matches either.

Functions

func CosineDistance

func CosineDistance(left, right []float32) float64

CosineDistance is 1 - cos of two vectors of equal length, clamped to [0, 2]: the components are 32-bit floats, the arithmetic double. NaN when either has no magnitude (a zero vector).

func Permits

func Permits(bounds ae.AuthorizationBounds, scope ae.Scope) bool

Permits reports whether bounds permit scope: the tenant always, and every bounded field exactly.

func QueryTerms

func QueryTerms(text string) []string

QueryTerms are the distinct terms a query searches for: its words, less stopwords and words shorter than two characters. Empty when nothing is left, and then nothing matches.

Types

type Embedding

type Embedding struct {
	ModelID        string
	Dimension      int
	ContentHash    string
	SourceRevision int64
	Vector         []float32
}

Embedding is a record's stored embedding (contract 1.6): the model, the dimension, the content hash of the summary that was embedded, the record revision it was read at, and the vector, its components 32-bit floats.

type Event

type Event struct {
	Event      ae.InitialLifecycleEvent
	Actor      string
	RecordedAt time.Time
}

Event is a record's initial lifecycle event as InsertFinalized stored it, with its actor and recording time.

type HoldoutRow

type HoldoutRow struct {
	RunID        ae.UUID
	ExperienceID ae.UUID
	Revision     int64
	Arm          ae.HoldoutArm
	Scope        ae.Scope
	AssignedAt   ae.Instant
}

HoldoutRow is one holdout assignment row (contract 1.8): a run, a record its block named at the revision it was rendered from, the arm, the record's own scope, and when, as agent_experience.experience_holdout_assignments holds it.

type Injection

type Injection struct {
	LastInjectedAt ae.Instant
	InjectionCount int64
}

Injection is when a record was last injected in its own scope, and how many injected blocks delivered it.

type Store

type Store struct {
	// Clock is the store's own clock, which an injection's instant is clamped to, as PostgreSQL clamps it to its own;
	// nil reads agentexperience.Now. Set it before the store is used.
	Clock func() ae.Instant
	// contains filtered or unexported fields
}

Store holds records in memory, for development and tests. It is safe for concurrent use. The zero value is not usable: make one with New.

func New

func New(records ...ae.ExperienceRecord) (*Store, error)

New is a store holding records (each experience ID once).

func (*Store) Embedding

func (s *Store) Embedding(id ae.UUID) (Embedding, bool)

Embedding is a record's stored embedding, for tests; ok is false when it has none.

func (*Store) Erase

func (s *Store) Erase(id ae.UUID) bool

Erase erases a record, as the .NET erasure (agent_experience.purge_experience_record) does as the schema's owner, for tests: the record is no longer read, searched, listed or recorded, and its ID can never be stored again. Its injection summary and embedding go, and so do its holdout rows: every row that names it, and, when no other live record of its run remains in its tenant, every row of that run in its tenant. It answers false for an ID it does not hold.

func (*Store) Event

func (s *Store) Event(id ae.UUID) (Event, bool)

Event is the initial lifecycle event stored with a record; ok is false for a record written without one (InsertRecord, New) or none at all.

func (*Store) Get

func (s *Store) Get(_ context.Context, bounds ae.AuthorizationBounds, scope ae.Scope, id ae.UUID) (*ae.ExperienceRecord, error)

Get reads one record in exactly scope; (nil, nil) when there is none, or the bounds do not permit it.

func (*Store) HoldoutRows

func (s *Store) HoldoutRows() []HoldoutRow

HoldoutRows are every holdout assignment row, ordered by run then record: for inspection in tests.

func (*Store) Injections

func (s *Store) Injections() map[ae.UUID]Injection

Injections are when each record was last injected and how often: for inspection in tests.

func (*Store) InsertFinalized

func (s *Store) InsertFinalized(ctx context.Context, bounds ae.AuthorizationBounds, finalized *ae.FinalizedExperience,
	actor string, recordedAt *time.Time) error

InsertFinalized writes a copy of a finalized record and its initial lifecycle event. It refuses a done context, a blank actor, an event that is not the record's own, a record outside the bounds (ErrAuthorizationDenied) and a record already stored.

func (*Store) InsertRecord

func (s *Store) InsertRecord(ctx context.Context, bounds ae.AuthorizationBounds, record *ae.ExperienceRecord) error

InsertRecord writes one record exactly as given, with no lifecycle event: for seeding and tests.

func (*Store) ListLessonRecords

func (s *Store) ListLessonRecords(ctx context.Context, bounds ae.AuthorizationBounds, scope ae.Scope,
	statuses []ae.ExperienceStatus, limit int) (ae.LessonRecords, error)

ListLessonRecords is the lessons view's read (contract 1.7): the live records held in exactly scope, newest first (created_at descending, then experience ID ascending), filtered to statuses (nil: every status), at most limit, each with when it was last injected. Injections are always tracked here. It never writes, honours the bounds (ErrAuthorizationDenied for a scope outside them) and refuses a limit outside 1 to 500 and empty or undefined statuses.

func (*Store) RecordHoldoutAssignment

func (s *Store) RecordHoldoutAssignment(ctx context.Context, bounds ae.AuthorizationBounds, scope ae.Scope,
	assignment ae.HoldoutAssignment) error

RecordHoldoutAssignment records a run's holdout assignment in scope, as sql/record-holdout-assignment.sql does: one row per named record held live in exactly scope, at the revision named (a record named twice counts once, at its first revision); a row already there for the run and record is kept as it is; the instant, truncated to whole microseconds, is clamped to the store's Clock. Nothing is written for a run whose own records (those captured from the run, in scope's tenant) are all erased. It refuses a done context, an assignment HoldoutRecords refuses, and a scope outside the bounds (ErrAuthorizationDenied).

func (*Store) RecordInjection

func (s *Store) RecordInjection(ctx context.Context, bounds ae.AuthorizationBounds, scope ae.Scope,
	experienceIDs []ae.UUID, injectedAt ae.Instant) error

RecordInjection records that experienceIDs were injected in scope at injectedAt, as sql/record-injection.sql does: only a record held in exactly scope counts, the instant (truncated to whole microseconds) is clamped to the store's Clock and only moves forward, and the count rises by one and saturates at agentexperience.MaxInjectionCount. It refuses a done context, more than agentexperience.MaxRecordInjectionIDs IDs or a nil one, and a scope outside the bounds (ErrAuthorizationDenied).

func (*Store) Records

func (s *Store) Records() []ae.ExperienceRecord

Records are copies of every record held, in the order they were written: for inspection in tests.

func (*Store) Search

func (s *Store) Search(ctx context.Context, bounds ae.AuthorizationBounds, parameters ae.SearchParameters) ([]ae.SearchRow, error)

Search is the text search: records in exactly the requested scope, of an eligible status and confidence, matching enough query terms; by relevance, then experience ID, at most the limit. Nothing outside the bounds. Parameters that fail Validate are an error.

func (*Store) SearchVectors

func (s *Store) SearchVectors(ctx context.Context, bounds ae.AuthorizationBounds,
	query ae.VectorQuery) (ae.VectorSearchResult, error)

SearchVectors is the nearest-neighbour search: embeddings of the query's model and dimension, of records in exactly the query's scope with an eligible status and confidence (and not model-authored, when excluded), by cosine distance, ties by experience ID, NaN last, at most the limit. With none, the outcome says why: ModelMismatch or DimensionMismatch when eligible embeddings exist but none is comparable, else Found and empty. Nothing outside the bounds. A query that fails Validate is an error.

func (*Store) SetInjection

func (s *Store) SetInjection(id ae.UUID, injection Injection)

SetInjection replaces a record's injection summary: for seeding tests (a count near saturation, say).

func (*Store) WriteEmbedding

func (s *Store) WriteEmbedding(ctx context.Context, bounds ae.AuthorizationBounds,
	write ae.EmbeddingWrite) (ae.EmbeddingWriteResult, error)

WriteEmbedding stores a record's embedding as sql/write-experience-embedding.sql does: only for a record held in exactly the write's scope and still at exactly its source revision (Written); otherwise Stale with the record's revision, or Missing for an unknown record or one in another scope or outside the bounds. A row stored from a newer revision is never replaced by an older one. A write that fails Validate is an error, and stores nothing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL