UNPKG

agentfootprint

Version:

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

92 lines • 4.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.readCacheUsage = exports.applyCacheMarkers = exports.bedrockPromptCaching = void 0; const bedrockModels_js_1 = require("./bedrockModels.js"); function bedrockPromptCaching(model) { const facts = (0, bedrockModels_js_1.bedrockCacheFacts)(model); return facts === undefined ? undefined : { mode: 'breakpoints', maxBreakpoints: facts.maxBreakpoints, reportsUsage: true, ...(!facts.tools && { fields: ['system', 'messages'] }), }; } exports.bedrockPromptCaching = bedrockPromptCaching; /** Translate only valid original boundaries; a dropped message never marks a * neighbor. Deduplicate, cap, then insert backwards so indices never shift. * TTLs follow wire order (tools → system → messages), independent of marker * arrival order: a long TTL after a short one is safely reduced to default. */ function applyCacheMarkers(body, markers, model, positions) { const facts = (0, bedrockModels_js_1.bedrockCacheFacts)(model); if (facts === undefined) return; const boundaries = new Map(); for (const marker of markers) { if (!Number.isSafeInteger(marker.boundaryIndex) || marker.boundaryIndex < 0) continue; let array; let index = marker.boundaryIndex; let order = 0; let identity = ''; if (marker.field === 'tools' && facts.tools) { array = body.toolConfig?.tools; identity = `tools:${index}`; } else if (marker.field === 'system') { // The port carries one composed system string, as the Anthropic wire // does. A system marker covers that single block, not invented pieces. array = body.system; index = 0; order = 1; identity = 'system'; } else if (marker.field === 'messages') { const position = positions[index]; if (position === undefined) continue; array = body.messages[position.message]?.content; index = position.content; order = position.message + 2; identity = `message:${position.message}:${index}`; } if (array === undefined || index >= array.length || identity === '') continue; // A duplicate never upgrades a short cache request to a pricier long TTL. const previous = boundaries.get(identity); const long = marker.ttl === 'long' && facts.longTtl; boundaries.set(identity, { array, index, order, long: long && (previous?.long ?? true) }); if (boundaries.size >= facts.maxBreakpoints) break; } const selected = [...boundaries.values()] .sort((a, b) => a.order - b.order || a.index - b.index) .slice(0, facts.maxBreakpoints); let shortSeen = false; const points = selected.map((boundary) => { const long = boundary.long && !shortSeen; if (!long) shortSeen = true; const point = { cachePoint: { type: 'default', ...(long && { ttl: '1h' }) }, }; return { ...boundary, point }; }); for (const { array, index, point } of points.reverse()) array.splice(index + 1, 0, point); } exports.applyCacheMarkers = applyCacheMarkers; /** Present zero is measured; absent or malformed cache counters stay absent. * inputTokens is fresh input (AWS excludes both cache reads and writes), the * same semantics the port cache meter expects from Anthropic's adapter. */ function readCacheUsage(usage) { const count = (value) => Number.isSafeInteger(value) && value >= 0; return { ...(count(usage?.cacheReadInputTokens) && { cacheRead: usage?.cacheReadInputTokens }), ...(count(usage?.cacheWriteInputTokens) && { cacheWrite: usage?.cacheWriteInputTokens }), }; } exports.readCacheUsage = readCacheUsage; //# sourceMappingURL=bedrockCacheWire.js.map