agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
70 lines (69 loc) • 3.46 kB
TypeScript
/**
* runbook/dispatch — the bridge's wrapper over `ctx.tools`.
*
* Pattern: decorator over {@link ToolDispatch}. The RAW dispatch (delivered
* by the agent) returns every result untouched; POLICY about what a
* result means belongs to the consumer — and this is the runbook's
* policy: every inner outcome is RECORDED (for the coverage fold and
* the provenance carry), and an inner ABSENCE short-circuits the
* procedure unless the call site declared it survivable.
* Role: core/runbook, pure.
* Emits: N/A.
*
* WHY an absence short-circuits: "the inventory found nothing" IS the
* runbook's answer, and it must go back EXACTLY as it arrived so the
* framework still reads it as an absence — a verdict reached over a source
* that answered "nothing here" would be the confident-partial-answer failure
* this whole envelope exists to prevent. A stage that can genuinely carry on
* without the source says so at the call site (`{ allowAbsent: true }`) and
* owns stating the gap (usually as a coverage entry).
*/
import type { ToolAbsence } from '../../semantics/coverage/types.js';
import type { ToolDispatch } from '../../tools/tools.js';
/** One inner call, as the bridge recorded it. */
export interface InnerCallRecord {
readonly tool: string;
readonly outcome: 'ok' | 'absent' | 'error';
/** The raw returned value (`'ok'` and `'absent'` outcomes). */
readonly result?: unknown;
}
/** The marker property that survives any error wrapping between a stage and
* the bridge's catch. */
declare const ABSENCE_SIGNAL: "af_runbook_absence";
/**
* The control signal an un-survivable inner absence throws through the
* chart. The engine commits staged state and rethrows (commit-on-error is
* the law upstream), so the bridge catches this at `executor.run` and
* returns the absence verbatim.
*/
export declare class RunbookAbsenceSignal extends Error {
readonly absence: ToolAbsence;
readonly [ABSENCE_SIGNAL] = true;
constructor(absence: ToolAbsence, innerTool: string);
}
/** Recognize the signal on an error OR anywhere down its `cause` chain — an
* engine layer that wraps the stage's throw must not defeat the pass-through. */
export declare function absenceSignalOf(err: unknown): RunbookAbsenceSignal | undefined;
/** What `recordingDispatch` hands back: the dispatch the procedure closes
* over, and the record the envelope folds. */
export interface RecordedDispatch {
readonly tools: ToolDispatch;
readonly records: readonly InnerCallRecord[];
}
/**
* Wrap the delivered dispatch (or its absence) for one runbook invocation.
*
* With NO dispatch delivered (`ctx.tools` absent — a hand-built context, a
* door with no dispatch map) the wrapper is the fail-closed teacher: `has`
* answers false and `call` refuses naming the fix, so a procedure that needs
* inner tools fails loudly at its first call instead of half-running.
*/
export declare function recordingDispatch(delivered: ToolDispatch | undefined, runbookName: string): RecordedDispatch;
/**
* The definition-time probe dispatch — handed to the procedure factory ONCE
* at `runbookAsTool(...)` so the bridge can read the chart's declared
* contract. Stage bodies do not run at build; a factory that calls tools at
* build time hears exactly why that cannot work.
*/
export declare function probeDispatch(runbookName: string): ToolDispatch;
export {};