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.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeDecayFactors = exports.computeDecayFactor = void 0;
/**
* Maximum compounding boost from `accessCount`. Caps the access term at
* ~10×; tuned against the intuition that "a heavily used memory is important
* but not more important than an exact-match recent memory."
*/
const MAX_BOOST_MULTIPLIER = 10;
/**
* Compute the decay factor for an entry at a given moment.
*
* @param entry The memory entry to score. Must have `lastAccessedAt` and
* `accessCount` set (storage adapters populate these).
* @param now The reference time (unix ms). Defaults to `Date.now()`.
* @param policy Optional override — when omitted, uses `entry.decayPolicy`.
* Stages can pass a stage-wide default so entries without a
* per-entry policy still decay consistently. If neither is
* set, returns 1.0 (no decay applied).
*
* @returns Scaling factor in `[0, MAX_BOOST_MULTIPLIER]` — stages multiply
* this against their existing relevance score.
*/
function computeDecayFactor(entry, now = Date.now(), policy) {
const effective = policy ?? entry.decayPolicy;
if (!effective)
return 1;
const ageMs = Math.max(0, now - entry.lastAccessedAt);
// Time factor: 2^(-age / halfLife).
// - halfLifeMs === 0 models "instant decay" — any age > 0 ⇒ 0.
// Without this guard, 0/0 → NaN poisons the result.
// - halfLifeMs > 0 uses the standard exponential.
let timeFactor;
if (effective.halfLifeMs === 0) {
timeFactor = ageMs === 0 ? 1 : 0;
}
else {
timeFactor = Math.pow(2, -ageMs / effective.halfLifeMs);
}
// Access factor: clamp `accessBoost` to a positive value before
// exponentiating. A negative or zero boost would either produce NaN
// (fractional powers of negatives) or collapse relevance to 0 for any
// accessCount > 0 — neither is the intended semantic. The documented
// contract is accessBoost > 0; this clamp hardens against misconfigs.
const safeBoost = Math.max(Number.EPSILON, effective.accessBoost);
const rawBoost = Math.pow(safeBoost, entry.accessCount);
const accessFactor = Math.min(rawBoost, MAX_BOOST_MULTIPLIER);
return timeFactor * accessFactor;
}
exports.computeDecayFactor = computeDecayFactor;
/**
* Compute decay for multiple entries in one call. Order-preserving; returns
* one factor per entry. Convenience for stages that rank whole batches.
*/
function computeDecayFactors(entries, now = Date.now(), policy) {
return entries.map((e) => computeDecayFactor(e, now, policy));
}
exports.computeDecayFactors = computeDecayFactors;
//# sourceMappingURL=decay.js.map