UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

98 lines • 5.09 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.narrativePipeline = void 0; /** * narrativePipeline — beats-based memory preset. * * Compresses each turn into `NarrativeBeat`s on write, recalls them * as a story paragraph on read. Two subflows, shared store: * * READ : LoadRecent → PickByBudget → FormatAsNarrative * WRITE : ExtractBeats → WriteBeats * * Contrast with `defaultPipeline` (raw messages, block-formatted) — * the read side is structurally identical; only the format stage and * write path differ. `LoadRecent` + `PickByBudget` don't care whether * the entry payload is a `Message` or a `NarrativeBeat` — they operate * on `MemoryEntry<T>` generically. * * **Why narrative memory?** * Raw-message recall grows linearly with conversation length and * loses salience signal. Beats compress 100 turns of chat into * ~20 summary sentences, each with `refs[]` traceable back to the * source messages. The picker prefers high-importance beats; the * formatter composes them into a single cohesive paragraph. * * **Default extractor**: `heuristicExtractor()` — zero-dep, zero-cost. * Produces sensible-but-baseline beats. Opt into `llmExtractor({ provider })` * when you want semantic quality. * * @example * Most consumers reach for `narrativePipeline` indirectly through * `defineMemory({ type: MEMORY_TYPES.NARRATIVE, strategy: { kind: * MEMORY_STRATEGIES.EXTRACT, extractor: 'pattern' | 'llm' }, store })`. * * @example Direct usage (low-level — custom flowchart composition): * ```ts * import { narrativePipeline, llmExtractor, InMemoryStore } from 'agentfootprint/memory'; * * // Cheap default — heuristic beats, no LLM cost. * const pipeline = narrativePipeline({ store: new InMemoryStore() }); * * // Or opt into LLM-backed beats (pass any LLMProvider): * const pipelineHQ = narrativePipeline({ * store: new InMemoryStore(), * extractor: llmExtractor({ provider: yourLLMProvider }), * }); * ``` */ const footprintjs_1 = require("footprintjs"); const loadRecent_js_1 = require("../stages/loadRecent.js"); const pickByBudget_js_1 = require("../stages/pickByBudget.js"); const extractBeats_js_1 = require("../beats/extractBeats.js"); const writeBeats_js_1 = require("../beats/writeBeats.js"); const formatAsNarrative_js_1 = require("../beats/formatAsNarrative.js"); const heuristicExtractor_js_1 = require("../beats/heuristicExtractor.js"); /** * Build the narrative read + write pipelines sharing a single store. * Returns `{ read, write }` ready to be passed to `Agent.memory()` via the appropriate `defineMemory` config (or used directly via `mountMemoryRead`/`mountMemoryWrite`). */ function narrativePipeline(config) { const extractor = config.extractor ?? (0, heuristicExtractor_js_1.heuristicExtractor)(); const loadConfig = { store: config.store, ...(config.loadCount !== undefined && { count: config.loadCount }), ...(config.tiers && { tiers: config.tiers }), }; const pickConfig = { ...(config.reserveTokens !== undefined && { reserveTokens: config.reserveTokens }), ...(config.minimumTokens !== undefined && { minimumTokens: config.minimumTokens }), ...(config.maxEntries !== undefined && { maxEntries: config.maxEntries }), }; const formatConfig = { ...(config.formatHeader !== undefined && { header: config.formatHeader }), ...(config.formatFooter !== undefined && { footer: config.formatFooter }), ...(config.formatShowRefs !== undefined && { showRefs: config.formatShowRefs }), ...(config.formatLeadIn !== undefined && { leadIn: config.formatLeadIn }), }; const extractConfig = { extractor, ...(config.writeTier && { tier: config.writeTier }), ...(config.writeTtlMs !== undefined && { ttlMs: config.writeTtlMs }), }; // ── Read subflow: LoadRecent → PickByBudget (decider + 3 branches) → FormatAsNarrative let readBuilder = (0, footprintjs_1.flowChart)('LoadRecent', (0, loadRecent_js_1.loadRecent)(loadConfig), 'load-recent', { description: 'Load N most-recent beats from storage into scope.loaded', }); readBuilder = (0, pickByBudget_js_1.pickByBudget)(pickConfig)(readBuilder); const read = readBuilder .addFunction('Format', (0, formatAsNarrative_js_1.formatAsNarrative)(formatConfig), 'format-as-narrative', 'Compose selected beats into a story paragraph; writes scope.formatted') .build(); // ── Write subflow: ExtractBeats → WriteBeats const write = (0, footprintjs_1.flowChart)('ExtractBeats', (0, extractBeats_js_1.extractBeats)(extractConfig), 'extract-beats', { description: 'Compress scope.newMessages into NarrativeBeat entries' }) .addFunction('WriteBeats', (0, writeBeats_js_1.writeBeats)({ store: config.store }), 'write-beats', 'Batch-persist extracted beats via store.putMany') .build(); return { read, write }; } exports.narrativePipeline = narrativePipeline; //# sourceMappingURL=narrative.js.map