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.6 kB
JavaScript
import { RedactionRule } from 'footprintjs/advanced';
/** The registry symbol a tool carries its arguments view under. */
export const SHOWN_ARGS = Symbol.for('agentfootprint.tool.shownArgs');
/**
* The arguments view a redaction policy implies — footprintjs's own rule
* (`RedactionRule` · `retainRecord`: keys, patterns and fields, the one
* owner), with the placeholder the tool's served result carries
* (`'REDACTED'`, the redacted mirror's), so a hidden key reads the same in
* the arguments as in the result. A fresh rule per call: `RedactionRule`
* remembers marked keys for a run, and two calls are not one run.
*/
export function argsRedactedBy(policy) {
return (args) => new RedactionRule(policy).retainRecord(args, 'REDACTED');
}
/**
* Whether `tool` carries an arguments view — its author declared that some
* argument's value must not reach the record (`flowchartAsTool({ redact })`,
* `runbookAsTool({ redact })`, or the symbol set by hand).
*/
export function carriesArgumentView(tool) {
return (tool !== null &&
typeof tool === 'object' &&
typeof tool[SHOWN_ARGS] === 'function');
}
/**
* What an event may say `tool` was called with: its own view when it carries
* one, else the arguments themselves (same reference). Never throws — a view
* that fails hides everything rather than show what it could not judge.
*/
export function shownArgsOf(tool, args) {
if (tool === null || typeof tool !== 'object')
return args;
const view = tool[SHOWN_ARGS];
if (typeof view !== 'function')
return args;
try {
return view(args);
}
catch {
return Object.fromEntries(Object.keys(args).map((key) => [key, 'REDACTED']));
}
}
/**
* The names of the keys whose value differs between the proposal and the
* arguments as shown: set, rewritten, removed, or hidden by the tool's view.
* Compared by reference, key by key — a link that spreads `...args` keeps the
* untouched keys' references, so only what it changed is named; a rebuilt
* nested value counts as changed (it may name more, never fewer). Plain
* strings, so the list is detached from both objects by construction.
*/
export function changedArgKeys(proposal, shown) {
if (proposal === shown)
return [];
const keys = new Set([...Object.keys(proposal), ...Object.keys(shown)]);
return [...keys].filter((key) => !Object.prototype.hasOwnProperty.call(proposal, key) ||
!Object.prototype.hasOwnProperty.call(shown, key) ||
proposal[key] !== shown[key]);
}
//# sourceMappingURL=toolShownArgs.js.map