agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
65 lines • 2.88 kB
JavaScript
import { retireReplayHistory } from '../../thinking/replayHistory.js';
import { RECEIPT_KEY } from '../../lib/conventions.js';
import { typedEmit } from './typedEmit.js';
function isHistory(value) {
return (Array.isArray(value) &&
value.every((m) => typeof m === 'object' &&
m !== null &&
'role' in m &&
'content' in m &&
typeof m.content === 'string'));
}
/** Create once per call. Retry/fallback reports append, never overwrite. */
export function replayPreparedHook(scope, receiptMinted, onPersisted) {
return (preparation) => {
if (preparation.omissions.length === 0)
return;
const history = scope.$getValue?.('history');
if (isHistory(history)) {
const retired = retireReplayHistory(history, preparation);
if (retired !== history) {
if (scope.$setValue === undefined)
throw new Error('Replay retirement requires writable history.');
scope.$setValue('history', retired);
}
}
// The checkpoint owner sees a successfully persisted history edit before
// optional receipt/observation work. A failed grouped stage cannot map
// this write outward, including if receipt annotation itself fails.
onPersisted?.(preparation);
// This flag is set by the mint's call site, never inferred from an old
// receipt inherited by a resumed or receipt-disabled run.
if (receiptMinted && scope.$getValue !== undefined && scope.$setValue !== undefined) {
const held = scope.$getValue(RECEIPT_KEY);
if (held !== undefined)
scope.$setValue(RECEIPT_KEY, {
...held,
replayPreparations: [
...(held.replayPreparations ?? []),
{
boundary: 'provider-adapter',
phase: 'prepared',
omittedBlocks: preparation.omissions.length,
},
],
});
}
for (const omission of preparation.omissions) {
try {
typedEmit(scope, 'agentfootprint.agent.thinking_omitted', {
providerName: preparation.provider,
model: preparation.model,
messageIndex: omission.messageIndex,
blockIndex: omission.blockIndex,
reason: omission.reason,
phase: 'prepared',
});
}
catch {
// A broken telemetry sink cannot turn already-preserved state into
// a failed model call. The retirement above is outside this catch.
}
}
};
}
//# sourceMappingURL=replayHooks.js.map