/** * formatFacts — render loaded `Fact` entries into a single system * message for prompt injection. * * Reads from scope: `loadedFacts` * Writes to scope: `formatted` (Message[] — one system message, or empty) * * Facts are tiny and semantically distinct from beats/messages, so they * render as a compact key/value block rather than a narrative paragraph * or per-entry `` tags. The default shape: * * Known facts about the user: * * - user.name: Alice * - user.email: alice@example.com * - user.preferences.color: blue * * Why one block, not one message per fact? * LLMs parse key/value lists efficiently; splitting would waste * tokens on per-message system overhead and break up the list's * visual grouping. * * Why NOT run facts through `pickByBudget`? * Facts are typically 10-50 items, each a handful of tokens. Picking * subsets is rarely useful — the user either knows your name or * they don't. Consumers who *do* want budget-based fact pruning can * copy-paste this stage and wrap it with a picker. */ import type { TypedScope } from 'footprintjs'; import type { MemoryEntry } from '../entry/index.js'; import type { Fact } from './types.js'; import type { FactPipelineState } from './extractFacts.js'; export interface FormatFactsConfig { /** * Header prepended to the injected message. Explains to the LLM what * follows and what it's for. Override if your app has specific * phrasing guidance. */ readonly header?: string; /** Footer appended after the fact list. Empty by default. */ readonly footer?: string; /** * When `true`, appends `(conf 0.xx)` after each fact's value. Off by * default — confidence is usually noise for the LLM and only useful * in audit / debug flows. */ readonly showConfidence?: boolean; /** * Custom per-fact renderer. Receives the entry; returns the block * string (without the leading `- ` bullet). Use for app-specific * formatting: custom attribution, hiding category info, etc. */ readonly renderFact?: (entry: MemoryEntry) => string; /** * Inject the message even when `loadedFacts` is empty. Usually * undesired — an empty list is noise. Off by default. */ readonly emitWhenEmpty?: boolean; } export declare function formatFacts(config?: FormatFactsConfig): (scope: TypedScope) => Promise;