UNPKG

agentfootprint

Version:

The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.

75 lines (74 loc) • 4.07 kB
/** * arguments/kept — the person's answers a call could not use, kept for the * call the model proposes next. * * Pattern: Map leaf, pure. The kept answer's shape and the functions that read * and change the list: ToolCalls keeps and drops entries * (`dispatch.ts` · `keepAnswers`, `dropUsedKept`, loaded by * `stages/toolCalls.ts` under the arm), the layer's mount hands this turn's * entries to `sf-inputs` (`honesty/mounts.ts`), and the layer's one * table fills from them (`resolve.ts` · `verifyPlan`). * Role: core/ layer leaf of the inputs layer (honesty layer 2). On every * armed agent's graph (the mount and `dispatch.ts` import it), so it * imports types only. * Emits: N/A. * * ## Why an answer is kept * * The batch that asked resumes with the person's answer, and that resume has * no second pause to give (one human question per resume): a call of the batch * that needs a person again — its check-in, a middleware `ask`, a credential * consent, the tool's own pause — is refused by name. The model may propose * the call again, and it leaves the `ask` argument out, as the served schema * tells it to. Were the answer dropped, the library would ask the person the * SAME question again and refuse the second step again, every batch, until the * iterations ran out. So the refused call's answered values are KEPT * (`AgentState.argumentAnswersKept`), and the next call of the same tool that * leaves the same argument out, this turn, runs with the person's answer — * filed `answered`, no second question — and its own step pauses then, in a * batch that asked nothing. * * A kept answer is used ONCE: the batch whose calls filled from it drops it, * and only another refusal by the same law keeps it again. Every other batch * asks as the layer always asks — once per batch — so an answer is never * stretched over calls the person was not asked about. * * Working state, the class of `argumentResolutions`: it holds the RAW value, * because the call must run with it — never a row, an event or a lens view. * Written only when a call carrying an answer is refused by that law, so a run * that never meets the case never writes the key: the mount hands it to the * layer only when it holds an answer of this turn, and ToolCalls reads it only * when it keeps an answer or drops one it filled from. */ import type { InputValue } from '../../../tools/inputRequest.js'; /** One answer kept for the next call of its (tool, argument), this turn. */ export interface KeptAnswer { /** `AgentState.turnNumber` when the answer was kept — never read in another turn. */ readonly turn: number; readonly toolName: string; readonly argument: string; /** The person's answer, raw, in this argument's own spelling. */ readonly value: InputValue; } /** The kept answers of `turn`, detached — an entry of another turn, or of an unknown shape, is never read. */ export declare function keptThisTurn(kept: unknown, turn: number): KeptAnswer[]; /** The kept answer for one (tool, argument), if any. */ export declare function keptAnswerFor(kept: readonly KeptAnswer[] | undefined, toolName: string, argument: string): KeptAnswer | undefined; /** * This turn's list with a refused call's answered values kept — each replacing * an entry kept earlier for the same (tool, argument), so the list holds one * answer per pair. Entries of another turn are dropped. */ export declare function withKept(kept: unknown, turn: number, toolName: string, answers: readonly { readonly argument: string; readonly value: InputValue; }[]): KeptAnswer[]; /** * This turn's list without the (tool, argument) pairs a batch filled from — * `undefined` when nothing is left, so the key is cleared rather than left * holding an empty list. */ export declare function withoutUsed(kept: unknown, turn: number, used: readonly { readonly toolName: string; readonly argument: string; }[]): KeptAnswer[] | undefined;