UNPKG

agentfootprint

Version:

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

59 lines • 2.75 kB
/** * BreakpointCacheStrategy — for a provider that caches a prefix only where * the request marks it (`promptCaching.mode: 'breakpoints'`; Anthropic's * `cache_control`). * * Chosen by CAPABILITY (`cacheStrategyFor`), never by provider name: built * from the provider's own declaration, so `withRetry(anthropic())` or an * application's routing wrapper caches exactly like the adapter it wraps. * * What it DOES: * - clamp the candidate markers to the declared `maxBreakpoints`, keeping * the first N in slot order (the most stable prefixes first); * - put them on `LLMRequest.cacheMarkers`, where the adapter reads them; * - read cache metrics off the PORT usage the adapter normalised — * `not applicable` when the declaration says the adapter reports none. * What it does NOT: touch the wire. The adapter owns `cache_control` * (`adapters/llm/anthropicCacheWire.ts`), and content is never edited. */ import { notApplicable } from '../../lib/claim/claim.js'; import { readPortCacheUsage } from '../portUsage.js'; export class BreakpointCacheStrategy { name = 'breakpoints'; maxBreakpoints; reportsUsage; who; fields; /** * @param declared the provider's `promptCaching` declaration * @param who names the adapter in the meter's evidence sentences, * e.g. `"the 'anthropic' provider"` */ constructor(declared, who = 'the provider') { this.maxBreakpoints = declared.maxBreakpoints; this.reportsUsage = declared.reportsUsage; this.who = who; this.fields = declared.fields; } async prepareRequest(req, candidates, ctx) { // The agent-side kill switch, honoured here too: the CacheGate should // already have emptied the candidates, but a buggy gate must not be able // to put markers on a request whose run said caching is off. if (ctx.cachingDisabled || candidates.length === 0) { return { request: req, markersApplied: [] }; } const supported = this.fields === undefined ? candidates : candidates.filter((marker) => this.fields?.includes(marker.field)); const markersApplied = supported.length <= this.maxBreakpoints ? supported : supported.slice(0, this.maxBreakpoints); return { request: { ...req, cacheMarkers: markersApplied }, markersApplied }; } extractMetrics(usage) { if (!this.reportsUsage) { return notApplicable(`${this.who} declares that it does not report cache token counts ` + '(promptCaching.reportsUsage: false)'); } return readPortCacheUsage(usage, this.who); } } //# sourceMappingURL=BreakpointCacheStrategy.js.map