agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
63 lines • 2.88 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyReplayRetirements = exports.retireReplayHistory = exports.replayMessageFingerprint = exports.replayRetirements = void 0;
const canonicalJson_js_1 = require("../lib/canonicalJson.js");
const sha256_js_1 = require("../lib/sha256.js");
/** Narrow a transport report before a checkpoint owner retains it. */
function replayRetirements(preparation) {
const seen = new Set();
return preparation.omissions.flatMap((omission) => {
if (seen.has(omission.messageIndex))
return [];
seen.add(omission.messageIndex);
const replacement = preparation.request.messages[omission.messageIndex];
if (replacement === undefined)
throw new Error('Replay omission has no matching prepared message.');
return [
{
...(omission.replayId !== undefined && { replayId: omission.replayId }),
messageFingerprint: omission.messageFingerprint,
thinkingBlocks: replacement.thinkingBlocks,
...(replacement.replay !== undefined && { replay: replacement.replay }),
},
];
});
}
exports.replayRetirements = replayRetirements;
/** A local matching key, not a signature validator or public authentication. */
function replayMessageFingerprint(message) {
return (0, sha256_js_1.sha256Hex)((0, canonicalJson_js_1.canonicalJson)({
role: message.role,
content: message.content,
toolCalls: message.toolCalls,
thinkingBlocks: message.thinkingBlocks,
}));
}
exports.replayMessageFingerprint = replayMessageFingerprint;
/** Apply only reported thinking omissions, retaining all host-owned metadata. */
function retireReplayHistory(history, preparation) {
return applyReplayRetirements(history, replayRetirements(preparation));
}
exports.retireReplayHistory = retireReplayHistory;
/** One identity rule for live history, retries and both checkpoint doors. */
function applyReplayRetirements(history, retirements) {
if (retirements.length === 0)
return history;
let changed = false;
const next = history.map((message) => {
const omission = retirements.find((item) => item.replayId !== undefined
? message.replay?.id === item.replayId
: !message.replay?.id && replayMessageFingerprint(message) === item.messageFingerprint);
if (omission === undefined || !message.thinkingBlocks?.length)
return message;
changed = true;
return {
...message,
thinkingBlocks: omission.thinkingBlocks,
...(omission.replay !== undefined && { replay: omission.replay }),
};
});
return changed ? next : history;
}
exports.applyReplayRetirements = applyReplayRetirements;
//# sourceMappingURL=replayHistory.js.map