types

package
v0.29.0 Latest Latest
Warning

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

Go to latest
Published: Aug 12, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Index

Constants

View Source
const (
	MaxLinks            = 128
	MaxLinkSignificance = 1_000_000
)

Link validation bounds. Links are a client-supplied input into the decay maths: an item's summed link significance is damped and weighted into its value, and for a memory its event's is too. An uncapped count would let one item's links dominate every scan that reads them, and an uncapped per-link significance would push the damped contribution up without limit, so both are bounded here. The damping (see hippocampus.linkContribution) is what stops a merely large number of links making an item unforgettable; these bounds are what stop the graph itself growing without limit.

The same two bounds apply to memory links and event links: they are one mechanism, and an asymmetry between them would only ever be a trap.

View Source
const (
	MaxMetadataKeys        = 32
	MaxMetadataKeyLength   = 64
	MaxMetadataValueLength = 512
	MaxMetadataBytes       = 4096
)

Metadata validation bounds. Metadata is the multi-dimensional classification that group - one freeform 128-character label - could only ever carry one of, so it is client-supplied, opaque to the server, and stored per item. That combination is exactly what needs bounding: unbounded metadata is a body by another name. It would escape memory.limit.sizeBytes, distort UsedBytes and therefore capacity pressure, and become an eviction-accounting problem - which is why the serialised length is counted toward the body limit (see Memory.ValidateInsert) and toward the store's byte accounting rather than absorbed into db.evictionRowOverheadBytes' flat allowance.

These are constants rather than configuration, like the link bounds above them: they exist to keep a client from turning the store into something it cannot account for, and a deployment that could raise them could defeat that. MaxMetadataBytes is the binding constraint - the per-key and per-value caps only stop one pathological entry consuming the whole budget - and is deliberately far above db.evictionRowOverheadBytes, which is why it must be measured rather than absorbed.

Variables

This section is empty.

Functions

func CopyMetadata added in v0.26.0

func CopyMetadata(metadata map[string]string) map[string]string

CopyMetadata returns a copy of a metadata map, or nil for an empty one. Conversions to and from the proto messages copy rather than alias, because the proto map belongs to the caller and a stored item aliasing it would change under a caller that reused the message.

func DedupeLinkIds added in v0.26.0

func DedupeLinkIds(ids []string) []string

DedupeLinkIds returns ids with duplicates removed, preserving first-occurrence order. Unlinking the same target twice is harmless but pointless work, and the deduplicated list is what the aggregate recalculation should be handed.

func LinksToProto added in v0.26.0

func LinksToProto(links []Link) []*contract.Link

func MarshalMetadata added in v0.26.0

func MarshalMetadata(metadata map[string]string) (any, error)

MarshalMetadata encodes metadata for storage, returning nil for an empty map.

nil - stored as SQL NULL - rather than "" or "{}" is load-bearing, not tidiness. SQLite's json_extract raises "malformed JSON" on an empty string, so a column defaulting to the empty string the way group_name does would make the FIRST metadata-filtered query fail against every row written before the column existed. NULL is what json_extract, ->> and JSON_EXTRACT all return nothing for, so a row with no metadata is uniformly excluded by a key predicate on all three drivers.

func MetadataSerialisedLen added in v0.26.0

func MetadataSerialisedLen(metadata map[string]string) int

MetadataSerialisedLen is the byte length metadata occupies once stored, and is what both the memory.limit.sizeBytes check and the transfer batch sizer measure. It is the length of exactly what MarshalMetadata produces, so the figure a write is validated against is the figure the store will hold.

func MetadataToTerms added in v0.26.0

func MetadataToTerms(metadata map[string]string) []string

MetadataToTerms renders metadata as the sorted "key=value" strings the search index holds.

The index stores metadata as a keyword array in exactly this shape rather than as an object, because the keys are client-supplied: an object mapping would mint a new index field per distinct key and a client generating keys per request would exhaust the cluster's field limit. A keyword array cannot, term-filters exactly, ANDs naturally as several term filters, and is byte-identical to the filter's wire form - so a filter needs no conversion to become a term.

func ParseMetadataFilters added in v0.26.0

func ParseMetadataFilters(pairs []string) (map[string]string, error)

ParseMetadataFilters turns the repeated "key=value" filter strings into the map the store filters on, splitting each on the first separator. Every pair must match for an item to be returned.

The key is validated with the same rule a written key is - see validMetadataKey for why that matters here and not only on the write path. The value is not: it is bound as a query parameter and compared for equality, so it needs no charset, and a value that could never have been stored simply matches nothing.

func UnmarshalMetadata added in v0.26.0

func UnmarshalMetadata(src any) (map[string]string, error)

UnmarshalMetadata decodes a stored metadata column. A NULL or empty column reads as nil rather than an empty map, so a round trip through the store leaves an item exactly as it was written.

src is whatever the driver scanned: []byte on SQLite and MySQL, and either []byte or string on Postgres depending on how the JSONB column comes back.

func ValidateLinks(links []Link, owner string, kind string) error

ValidateLinks checks a set of links declared by one item. owner is the id of the item declaring them, so a self-link can be rejected: an item linked to itself would count its own significance twice in its own value, and means nothing as an association. kind names the item type for the error message ("memory"/"event").

It does NOT check that the targets exist - that needs the store, so the RPC layer does it and returns NotFound. Duplicate targets are rejected rather than silently collapsed: the store upserts per pair, so a duplicate in one request would otherwise mean the last one silently wins.

func ValidateMetadata added in v0.26.0

func ValidateMetadata(metadata map[string]string, kind string) error

ValidateMetadata checks one item's metadata against the bounds above. kind names the item type for the error message ("memory"/"event"), matching ValidateLinks.

It does NOT check the total against memory.limit.sizeBytes - that limit covers the body too, so the combined check belongs with the body, in Memory.ValidateInsert.

Types

type Event

type Event struct {
	Id                   string // if not provided, will be a uuid
	TimeStart            int64  // time.Time.Now().UnixNano()
	TimeEnd              int64  // time.Time.Now().UnixNano()
	Significance         int32
	Name                 string // limited to 256 characters
	Description          string // limited to 1024 characters
	Links                []Link
	LinkSignificance     int64  // Sum of the significances of this event's links, both directions. This is a calculated value, maintained by the store.
	MemoriesConsolidated bool   // if true, some memories related to this event have been consolidated (deleted)
	Group                string // optional grouping/context label; limited to 128 characters

	// Metadata, ClearMetadata and ClearGroup mirror the same three fields on Memory exactly - one
	// mechanism, same bounds (types/metadata.go), same write-only clearing semantics. An asymmetry
	// between the two would only ever be a trap.
	Metadata      map[string]string
	ClearMetadata bool
	ClearGroup    bool

	// SignificanceLevelID is the resolved significance registry level id, set by the RPC layer via
	// db.ResolveSignificanceLevel before a create/update reaches the store. nil means unranked on a
	// create, or "leave significance unchanged" on a partial update. It is internal - never part of
	// the proto conversion.
	SignificanceLevelID *int64
}

func EventFromProto

func EventFromProto(event *contract.Event) Event

func (*Event) SetDefaults

func (e *Event) SetDefaults()

func (*Event) ToProto

func (e *Event) ToProto() *contract.Event

func (*Event) Validate

func (e *Event) Validate(update bool) error
type Link struct {
	Id           string
	Significance int32
}

Link is one directed edge from the item carrying it to the item it names. The near end is implied by whatever holds the link, so only the far end is recorded here; LinkEdge is the read form that says which way a link points.

func LinksFromProto added in v0.26.0

func LinksFromProto(links []*contract.Link) []Link

func (*Link) ToProto added in v0.26.0

func (l *Link) ToProto() *contract.Link

type LinkDirection added in v0.26.0

type LinkDirection int

LinkDirection mirrors contract.LinkDirection without the db package having to depend on the contract package, and is what a read uses to say which way a returned link points.

const (
	LinkDirectionBoth LinkDirection = iota
	LinkDirectionOutbound
	LinkDirectionInbound
)

func LinkDirectionFromProto added in v0.26.0

func LinkDirectionFromProto(d contract.LinkDirection) LinkDirection

LinkDirectionFromProto resolves a requested direction, defaulting UNSPECIFIED to BOTH: the graph is stored directed but valued symmetrically, so both directions are what a caller asking about an item's links almost always means.

func (LinkDirection) ToProto added in v0.26.0

func (d LinkDirection) ToProto() contract.LinkDirection

type LinkEdge added in v0.26.0

type LinkEdge struct {
	Id           string
	Significance int32
	Direction    LinkDirection
	Created      int64
}

LinkEdge is a stored link as read back: the far end, the weight, and which way it points relative to the item that was asked about.

func (*LinkEdge) ToProto added in v0.26.0

func (e *LinkEdge) ToProto() *contract.LinkEdge

type Memory

type Memory struct {
	Id           string // if not provided, will be a uuid
	TimeStamp    int64  // time.Time.Now().UnixNano()
	Significance int32  // the level's rank on read; on write the requested absolute value (0 = unranked)
	EventId      string
	Body         string // optionally limited "memory.limit.sizeBytes"
	IsBinary     bool
	TimeRecalled int64  // time of the most recent recall; zero if never recalled
	RecallCount  int32  // number of times the memory has been recalled
	IsSummary    bool   // set on the memory created by ReplaceMemoriesWithSummary
	Group        string // optional grouping/context label; limited to 128 characters

	// Metadata is the multi-dimensional classification group could only carry one dimension of;
	// see types/metadata.go for the bounds and why they are constants. ClearMetadata and ClearGroup
	// are write-only update instructions, never populated on a read: every other updatable field
	// reads its zero value as "leave unchanged", so without them neither field could be unset once
	// set.
	Metadata      map[string]string
	ClearMetadata bool
	ClearGroup    bool

	// Links are this memory's associative links. On a write they are the links to create (targets
	// must already exist); on a read they are populated only when the caller asked for them.
	// LinkSignificance is the store-maintained sum of this memory's link significances in both
	// directions - a calculated value, never accepted from a client.
	Links            []Link
	LinkSignificance int64

	// SignificanceLevelID is the resolved significance registry level id, set by the RPC layer via
	// db.ResolveSignificanceLevel before a create/update reaches the store. nil means unranked on a
	// create, or "leave significance unchanged" on a partial update. It is internal - never part of
	// the proto conversion.
	SignificanceLevelID *int64
}

func MemoryFromProto

func MemoryFromProto(memory *contract.Memory) Memory

func (*Memory) SetDefaults

func (m *Memory) SetDefaults()

func (*Memory) ToProto

func (m *Memory) ToProto() *contract.Memory

func (*Memory) ValidateInsert

func (m *Memory) ValidateInsert(maxMemoryBodyLength int, update bool) error

Jump to

Keyboard shortcuts

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