remainder

package
v0.1.2 Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: AGPL-3.0 Imports: 9 Imported by: 0

Documentation

Overview

Package remainder owns the truncated-result spool and its caller-scoped visibility grants.

When a tool result is shortened, the full body is stored under a content reference and the principal that received the truncation notice is granted read access. The model pages that body via the host's read_output tool.

Invariants:

  • INV-AG-10 / INV-CE-07-A: a reference is handed to the model only after a successful store; a store failure yields an empty ref (plain notice).
  • INV-CE-07-C: store failure must not fail the tool call.
  • Visibility is caller-scoped: only the principal that received the grant may Load the ref (stricter than open ledger_read digest lookup).

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNotFound means the ref is unknown (never spooled, or never stored).
	ErrNotFound = errors.New("remainder not found")
	// ErrDenied means content exists (or was granted to someone else) but the
	// calling principal was not the recipient of the remainder ref.
	ErrDenied = errors.New("remainder access denied")
	// ErrExpired means the principal once held a grant but the remainder is no
	// longer available (retention expiry or explicit expiry). Distinct from
	// not-found so the model does not treat a timed-out ref as a corrupt key.
	ErrExpired = errors.New("remainder expired")
)

Sentinel load failures. The read_output tool maps each to a distinct model-visible status so callers can tell them apart.

View Source
var ErrStoreUnavailable = errors.New("remainder content store unavailable")

ErrStoreUnavailable is returned by FailingStore on every write.

Functions

func CapWithSpool

func CapWithSpool(spool *Spool, principal string, result string, maxBytes int) (string, bool)

CapWithSpool shortens result so the whole return value fits in maxBytes, spools the original body for principal, and appends an honest truncation notice. When no truncation is needed the original body is returned unchanged.

maxBytes <= 0 means uncapped (no truncation). A nil spool (or failed store) yields a notice without a ref - the call still succeeds (INV-CE-07-C).

func CapWithSpoolRef

func CapWithSpoolRef(spool *Spool, principal string, result string, maxBytes int) (body, ref string, truncated bool)

CapWithSpoolRef is CapWithSpool that also reports the ref it minted.

A second shaping pass needs the ref itself, not just the notice that names it: re-cutting the original body means naming the SAME remainder again, and recovering that ref by parsing it back out of the notice would make the notice's wording a load-bearing interface. The ref is empty when the body was not truncated, when there is no spool, or when the store failed.

func Fit

func Fit(body string, total, maxBytes int, ref, trailer string) string

Fit builds "content + trailer + notice" within maxBytes from an ALREADY stored body: it performs no store, reports total as the body's true size, and names ref (empty for a plain notice).

The trailer is caller-supplied framing charged inside the same envelope. Its whole reason for existing is that a status line appended AFTER a built body would push the result past the budget that built it; composed here, the envelope bound holds by construction.

func ParseTruncationNotice

func ParseTruncationNotice(s string) (prefix string, kept, total int, ref string, ok bool)

ParseTruncationNotice recognizes a TruncationNotice trailer at the end of s. It reports the content preceding the trailer (prefix), the kept/total byte counts, the named remainder ref (empty when the notice carried none), and whether s ended with a well-formed notice at all.

This exists so a renderer can distinguish "this result was truncated" from "this is just a tool result that happens to contain the word truncated" - parsing the exact format TruncationNotice emits, not guessing from a substring match.

func TruncationNotice

func TruncationNotice(kept, total int, ref string) string

TruncationNotice formats the model-visible truncation trailer.

When ref is non-empty the notice names the remainder and directs the model to read_output. When ref is empty (store failed, or no spool) the notice still reports kept/total honestly and invents no reference.

Types

type ContentStore

type ContentStore interface {
	StoreContent(ctx context.Context, ref string, data []byte) error
	LoadContent(ctx context.Context, ref string) ([]byte, error)
}

ContentStore is the durable byte store the spool writes to. ledger repositories satisfy it; the interface keeps this package free of ledger imports so agent and runtime layers can use it without cycles.

StoreContent must be idempotent: storing the same data twice returns the same ref and the store must not grow unboundedly for duplicates — determinism of refs across repeated prepares depends on it.

type ContentStoreAdapter

type ContentStoreAdapter struct {
	Store         ContentStore
	NotFoundError error
}

ContentStoreAdapter adapts a store whose not-found sentinel is known.

func (ContentStoreAdapter) CheckSpoolGrant

func (a ContentStoreAdapter) CheckSpoolGrant(ctx context.Context, ref, principal string) (bool, error)

CheckSpoolGrant forwards the durable spool grant lookup to the wrapped store when it implements SpoolGrantStore; otherwise it reports no durable grant.

func (ContentStoreAdapter) GrantSpool

func (a ContentStoreAdapter) GrantSpool(ctx context.Context, ref, principal string) error

GrantSpool forwards the durable spool grant to the wrapped store when it implements SpoolGrantStore; otherwise it is a no-op (nil), so the adapter never breaks a store that only provides in-process visibility.

func (ContentStoreAdapter) IsContentNotFound

func (a ContentStoreAdapter) IsContentNotFound(err error) bool

IsContentNotFound reports whether err is the configured not-found sentinel.

func (ContentStoreAdapter) LoadContent

func (a ContentStoreAdapter) LoadContent(ctx context.Context, ref string) ([]byte, error)

LoadContent forwards to the wrapped store.

func (ContentStoreAdapter) StoreContent

func (a ContentStoreAdapter) StoreContent(ctx context.Context, ref string, data []byte) error

StoreContent forwards to the wrapped store.

type FailingStore

type FailingStore struct{}

FailingStore implements ContentStore but rejects every StoreContent call. Used to prove INV-CE-07-C / INV-AG-10: a failed spool omits the ref.

func (FailingStore) IsContentNotFound

func (FailingStore) IsContentNotFound(err error) bool

IsContentNotFound always true for the not-found sentinel.

func (FailingStore) LoadContent

func (FailingStore) LoadContent(context.Context, string) ([]byte, error)

LoadContent always reports not found.

func (FailingStore) StoreContent

func (FailingStore) StoreContent(context.Context, string, []byte) error

StoreContent always fails.

type MemoryStore

type MemoryStore struct {
	// contains filtered or unexported fields
}

MemoryStore is an in-process ContentStore for tests and host wiring that does not share the ledger repository. It is keyed by content reference: the same body always mints the same ref (sdkadapter.Mint is deterministic), so re-storing a duplicate lands on the same key and never grows the store.

func NewMemoryStore

func NewMemoryStore() *MemoryStore

NewMemoryStore returns an empty memory-backed content store. Storing the same content twice yields the same ref and does not duplicate storage.

func (*MemoryStore) Delete

func (m *MemoryStore) Delete(ref string)

Delete removes a ref so subsequent loads report not-found / expired.

func (*MemoryStore) IsContentNotFound

func (m *MemoryStore) IsContentNotFound(err error) bool

IsContentNotFound reports whether err is this store's absence sentinel.

func (*MemoryStore) Len

func (m *MemoryStore) Len() int

Len reports how many bodies are stored. Tests that assert nothing was spooled need to distinguish "stored nothing" from "stored something under a ref I did not predict"; counting is the only way to say the former.

func (*MemoryStore) LoadContent

func (m *MemoryStore) LoadContent(_ context.Context, ref string) ([]byte, error)

LoadContent retrieves previously stored bytes.

func (*MemoryStore) StoreContent

func (m *MemoryStore) StoreContent(_ context.Context, ref string, data []byte) error

StoreContent persists raw bytes under ref. It is idempotent: re-storing the same content under the same ref (dedupe by ref) is a no-op, so repeated prepares do not grow the store (see the ContentStore contract in spool.go).

type NotFoundReporter

type NotFoundReporter interface {
	IsContentNotFound(err error) bool
}

NotFoundReporter is implemented by stores that surface a typed not-found error (ledger.ErrContentNotFound). When the store does not implement it, any LoadContent error is treated as not-found for visibility decisions.

type Spool

type Spool struct {
	// contains filtered or unexported fields
}

Spool stores truncated tool-result bodies and gates reads by principal.

func NewSpool

func NewSpool(store ContentStore) *Spool

NewSpool returns a principal-scoped remainder spool over store. A nil store is allowed: Spool then never mints refs (degrades to plain notices).

func (*Spool) Load

func (s *Spool) Load(ctx context.Context, principal, ref string) ([]byte, error)

Load returns the stored body when principal holds a live grant. Errors are the package sentinels ErrNotFound, ErrDenied, or ErrExpired.

func (*Spool) MarkExpired

func (s *Spool) MarkExpired(ref string)

MarkExpired marks every grant on ref as expired. Used by retention and tests. The stored bytes may still be present; Load reports ErrExpired either way.

func (*Spool) Spool

func (s *Spool) Spool(ctx context.Context, principal string, data []byte) string

Spool stores the full body under a content-addressed output ref and grants principal read access. It returns the minted ref, or "" when the body is empty, the principal is empty, the store is nil, or the write fails. A failed write never invents a ref (INV-AG-10 / INV-CE-07-A/C).

type SpoolGrantStore

type SpoolGrantStore interface {
	// GrantSpool durably records that principal holds a grant on ref.
	GrantSpool(ctx context.Context, ref, principal string) error
	// CheckSpoolGrant reports whether principal holds a durable grant on ref.
	CheckSpoolGrant(ctx context.Context, ref, principal string) (bool, error)
}

SpoolGrantStore is the optional durable grant surface of a ContentStore. Spool grants are normally in-memory (they vanish on restart), so stores that also persist grants - currently the sqlite-backed ledger repository - expose them here. The spool calls GrantSpool best-effort and consults CheckSpoolGrant only on the in-memory grant miss path, so a store without this interface keeps today's purely in-process visibility semantics.

Jump to

Keyboard shortcuts

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