import type { AgencyConfig } from "../../config.js"; import type { Code } from "../../runtime/template/code.js"; import type { SpliceDiagnostic, SpliceResult } from "./types.js"; /** Which call this is: the generator being called, and how. Stable across * edits to any of the files involved, which is what makes an entry * replaceable rather than additive. */ export declare function spliceCacheSlot(expression: string, generatorPath: string): string; /** * Whether a remembered answer is still good: a hash over every file that * can change what the generator returns. * * `roots` is every module the runner will import, not just the generator. * A splice may pass an imported value as an argument, and the module * supplying it is imported by the HOST, so it need not appear anywhere in * the generator's own closure: * * import { makeFieldGetters } from "./gen.agency" // imports only std:: * import { FIELDS } from "./fields.agency" // not in gen's closure * * $( makeFieldGetters(FIELDS) ) * * Adding a field to `fields.agency` changes what the generator returns * while leaving the expression text and the generator's closure untouched. * Hashing only the generator meant the memo served the old expansion, and * a fresh `agency compile` hid it because that process starts empty. The * editor, `agency serve`, and watch mode do not. */ export declare function spliceCacheKey(expression: string, roots: readonly string[], config?: AgencyConfig): string; /** * Run `produce` unless this call has already been answered for exactly * this content. * * Failures are cached too. A broken generator is the case the editor hits * hardest, because the user is reading the error while still typing. The * caller re-anchors the diagnostic, since a cached failure carries the * position of whichever splice ran first. */ export declare function cachedGeneratorRun(slot: string, fingerprint: string, produce: () => SpliceResult): SpliceResult; /** * Remember whether a generator may run, against the same fingerprint the * result uses. * * Eligibility is decided before the generator runs, so it sits outside * `cachedGeneratorRun` and used to re-run on every call. That is a closure * walk per check, per splice, per keystroke once the editor is involved. * * Sound on the same fingerprint because that fingerprint now covers every * file the checks read: the generator's closure and every argument * module's closure. * * Note `null` is a real verdict here, meaning eligible. Wrapping it in an * `Entry` is what lets an ordinary `undefined` check distinguish "not * cached" from "cached as fine". */ export declare function cachedEligibility(slot: string, fingerprint: string, judge: () => SpliceDiagnostic | null): SpliceDiagnostic | null; /** Tests only: the cache outlives a single compile by design. */ export declare function clearSpliceCache(): void; /** Tests only: total remembered entries across both stores, so a test * asserting the cache does not grow can see either one leaking. */ export declare function spliceCacheSize(): number;