agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
123 lines (122 loc) • 6.89 kB
TypeScript
/**
* arguments/dispatch — the inputs layer's half of ToolCalls, in the ONE module
* a plain agent never loads.
*
* Pattern: small helpers over the batch loop's own values — the layer's entry
* for a call (`argumentResolutions`), the arguments the call ran
* with, the rewrites a before-tool chain made — each returning the
* value the loop uses next.
* Role: core/ layer leaf of the inputs layer (honesty layer 2). ToolCalls
* (`stages/toolCalls.ts`) loads this module through `import()` only
* when the layer is armed, or when a call's tool declares rules on an
* agent built without it — the optional-family law of docs-next's
* site budget (`scripts/check-site-budget.mjs`, the `findings/peel.ts`
* precedent). Imports nothing from `findings/` or `stages/`.
* Emits: N/A (one console warning per tool name on the fail-closed path).
*
* @example
* ```ts
* const inputs = deps.inputsLayer === true ? await import('../arguments/dispatch.js') : undefined;
* const runArgs = inputs !== undefined ? inputs.withFills(args, resolution) : args;
* ```
*/
import type { TypedScope } from 'footprintjs';
import type { Tool } from '../../../tools/tools.js';
import type { ToolArgs } from '../../../tools/runChain.js';
import type { MiddlewareDecision } from '../middleware/types.js';
import type { AgentState } from '../types.js';
import type { ArgumentFill, ArgumentResolution } from './resolve.js';
import { secondPauseRefusal, type ServeOptions } from './serve.js';
/**
* The refusal a call reads when the batch's one human question was the
* layer's ask and the call needed a person again (`serve.ts` ·
* `secondPauseRefusal`) — re-exported so ToolCalls reaches it through this
* module's one `import()`.
*/
export { secondPauseRefusal };
/**
* This batch's entries of `argumentResolutions`, by call id — only the entries
* resolved for THIS iteration (`resolve.ts` stamps each with its batch's).
*/
export declare function resolutionsFor(scope: {
readonly argumentResolutions?: readonly ArgumentResolution[];
}, iteration: number): ReadonlyMap<string, ArgumentResolution>;
/** `args` with the entry's fills — a FRESH object; `args` itself when there are none. */
export declare function withFills(args: ToolArgs, resolution: ArgumentResolution | undefined): ToolArgs;
/**
* KEPT ANSWERS, USED (honesty layer 2, step 4 — `kept.ts`): the
* (tool, argument) pairs this batch's calls fill from an answer the turn kept
* are dropped from `argumentAnswersKept` — a kept answer is used once. Called
* before the batch ask merges its own answers, so a fill that is `answered`
* here came from a kept answer and nothing else; a batch that fills none never
* reads the key. A re-run after an interrupt finds them already dropped and
* writes nothing.
*/
export declare function dropUsedKept(scope: TypedScope<AgentState>, resolutions: ReadonlyMap<string, ArgumentResolution>, calls: readonly {
readonly id: string;
readonly name: string;
}[]): void;
/**
* KEEP a refused call's answers (honesty layer 2, step 4 — `kept.ts`): in a
* batch whose one human question was the inputs layer's ask, a call that
* needed a person again was just refused — so the answered values it carried
* (the batch ask's, or a kept one it filled from) are kept for the call the
* model proposes next, which would otherwise leave the argument out and be
* asked the same question again. Returns the argument names kept, for the
* model's sentence (`keptNote`); nothing kept, nothing written.
*/
export declare function keepAnswers(scope: TypedScope<AgentState>, toolName: string, resolution: ArgumentResolution | undefined): readonly string[];
/**
* KEEP a refused call's answers and return the model's sentence for them
* (`serve.ts` · `keptAnswersNote` over `keepAnswers`) — `''` when the call
* carried no answer.
*/
export declare function keptNote(scope: TypedScope<AgentState>, toolName: string, resolution: ArgumentResolution | undefined): string;
/**
* The entry's fills the call RAN with — each whose value is still the value on
* the arguments the call ran with (`callArgs`, after the before-tool chain). A
* middleware that rewrote a filled argument ran the call on ITS value, so a
* clause naming the fill would tell the model the call ran with a value it did
* not run with — a sentence a later path broke (honesty law 7). That clause is
* omitted, never denied: the rewrite is on `middlewareDecisions`
* (`changedKeys`), which the answer's standing and the "Assumed" block read.
* Strict equality on purpose: the note prints the value, so it must be the
* value that ran, byte for byte.
*/
export declare function fillsThatRan(resolution: ArgumentResolution | undefined, ranWith: ToolArgs): readonly ArgumentFill[];
/**
* The past-tense note for a call that RAN on filled values (`serve.ts` ·
* `filledNote`) — one clause per fill it really ran with (`fillsThatRan`), a
* value the tool's view hides never printed. `proposed` is the call's own
* arguments before the fills: an answered fill that REPLACED a value the call
* carried (declared sources ask about an untraced value) says what the call
* had carried; under declared sources (`options.sources`) an answered clause
* also says a later call may cite the answer (`serve.ts` ·
* `ANSWERED_SOURCE_CLAUSE`). `''` when no fill ran.
*/
export declare function noteFor(toolName: string, tool: Tool | undefined, resolution: ArgumentResolution | undefined, ranWith: ToolArgs, proposed?: ToolArgs, options?: ServeOptions): string;
/**
* The before-tool rows of one call's chain, each rewrite stamped with the
* NAMES of the arguments it changed (`changedArgKeys` over its own
* before/after — names only, never values).
*/
export declare function withChangedKeys(rows: readonly MiddlewareDecision[]): MiddlewareDecision[];
/**
* The rows a call's before-tool chain files: a RULED tool's rewrites carry
* `changedKeys` (`withChangedKeys`) — the answer's standing reads a rewritten
* ruled argument with no declared origin as assumed; every other tool's rows
* as the chain wrote them.
*/
export declare function decisionsToRecord(tool: Tool | undefined, rows: readonly MiddlewareDecision[]): readonly MiddlewareDecision[];
/**
* FAIL CLOSED (adopted Q14): the sentence a call reads when its tool declares
* argument rules and the agent was built without the inputs layer — and, once
* per tool name, unconditionally (a refused call is not a style note), a
* warning naming `.inputsLayer()`.
*/
export declare function unmountedRefusal(toolName: string): string;
/**
* Forget every unmounted-rules warning issued so far.
* @internal test seam — the ledger is process-wide and warn-once.
*/
export declare function _resetUnmountedRulesWarnings(): void;