agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
91 lines • 4.64 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.factPipeline = void 0;
/**
* factPipeline — key/value fact memory preset.
*
* Distills stable user claims out of each turn and recalls them as a
* compact key/value block. Complements `narrativePipeline` (beats are
* "what happened") — facts are "what's true right now."
*
* READ : LoadFacts → FormatFacts
* WRITE : LoadFacts → ExtractFacts → WriteFacts
*
* Why `LoadFacts` on BOTH sides?
* - Read side: obvious — inject what we know.
* - Write side: surfaces existing facts to the extractor via
* `scope.loadedFacts`, so LLM-based extractors can UPDATE rather
* than duplicate. Costs one extra `store.list` per turn; saves
* many LLM-emitted duplicate facts.
*
* **Default extractor**: `patternFactExtractor()` — zero-dep, zero-cost
* regex heuristics for common identity / contact disclosures. Opt into
* `llmFactExtractor({ provider })` when you want semantic-quality
* extraction (preferences, commitments, task statuses).
*
* **Stable ids**: every fact is stored under `fact:${key}`, so writing
* `user.name = "Alice"` twice in two turns produces ONE entry in the
* store, not two. Updates overwrite in place — there's no
* accumulation, no "fact history" by default. Consumers who need fact
* history should run `narrativePipeline` alongside.
*
* Most consumers reach for `factPipeline` indirectly through
* `defineMemory({ type: MEMORY_TYPES.SEMANTIC, strategy: { kind:
* MEMORY_STRATEGIES.EXTRACT, extractor: 'pattern' | 'llm' }, store })`.
*
* @example Direct usage (low-level — custom flowchart composition):
* ```ts
* import { factPipeline, llmFactExtractor, InMemoryStore } from 'agentfootprint/memory';
*
* // Cheap default — regex heuristics, no LLM cost.
* const pipeline = factPipeline({ store: new InMemoryStore() });
*
* // Or opt into LLM-backed extraction (pass any LLMProvider):
* const hqPipeline = factPipeline({
* store: new InMemoryStore(),
* extractor: llmFactExtractor({ provider: yourLLMProvider }),
* });
* ```
*/
const footprintjs_1 = require("footprintjs");
const extractFacts_js_1 = require("../facts/extractFacts.js");
const writeFacts_js_1 = require("../facts/writeFacts.js");
const loadFacts_js_1 = require("../facts/loadFacts.js");
const formatFacts_js_1 = require("../facts/formatFacts.js");
const patternFactExtractor_js_1 = require("../facts/patternFactExtractor.js");
function factPipeline(config) {
const extractor = config.extractor ?? (0, patternFactExtractor_js_1.patternFactExtractor)();
const loadConfig = {
store: config.store,
...(config.loadLimit !== undefined && { limit: config.loadLimit }),
...(config.tiers && { tiers: config.tiers }),
};
const formatConfig = {
...(config.formatHeader !== undefined && { header: config.formatHeader }),
...(config.formatFooter !== undefined && { footer: config.formatFooter }),
...(config.formatShowConfidence !== undefined && {
showConfidence: config.formatShowConfidence,
}),
};
const extractConfig = {
extractor,
...(config.writeTier && { tier: config.writeTier }),
...(config.writeTtlMs !== undefined && { ttlMs: config.writeTtlMs }),
};
// ── Read subflow: LoadFacts → FormatFacts
const read = (0, footprintjs_1.flowChart)('LoadFacts', (0, loadFacts_js_1.loadFacts)(loadConfig), 'load-facts', {
description: 'Load stored Fact entries (ids starting with `fact:`) into scope.loadedFacts',
})
.addFunction('FormatFacts', (0, formatFacts_js_1.formatFacts)(formatConfig), 'format-facts', 'Render loaded facts as one system message; writes scope.formatted')
.build();
// ── Write subflow: LoadFacts → ExtractFacts → WriteFacts
// LoadFacts first so llmFactExtractor can see existing facts and
// update rather than duplicate.
const write = (0, footprintjs_1.flowChart)('LoadFacts', (0, loadFacts_js_1.loadFacts)(loadConfig), 'load-facts-for-extract', { description: 'Surface existing facts to the extractor for update-awareness' })
.addFunction('ExtractFacts', (0, extractFacts_js_1.extractFacts)(extractConfig), 'extract-facts', 'Distill scope.newMessages into Fact entries')
.addFunction('WriteFacts', (0, writeFacts_js_1.writeFacts)({ store: config.store }), 'write-facts', 'Batch-persist extracted facts via store.putMany (overwrite on key collision)')
.build();
return { read, write };
}
exports.factPipeline = factPipeline;
//# sourceMappingURL=fact.js.map