UNPKG

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
/** * 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;