UNPKG

agentfootprint

Version:

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

50 lines (49 loc) • 3.02 kB
/** * toolChoice/record — where a classifier's pick and the model's call become record. * * Pattern: one writer for one committed key (`findings/ledger.ts · * recordFindings`, `middleware/ledger.ts · recordDecisions`). * Role: core/ layer leaf. Two call sites, one writer: the tools slot * files the `pick` / `pick-error` row before the model call * (`slots/buildToolsSlot.ts · composeStage`), `stages/callLLM.ts` * files the `outcome` row after the reply. Both go through * `recordToolChoice`, so the key is appended one way and the * matching event fires once per row. * Emits: `agentfootprint.tool_choice.picked` / `.failed` / `.outcome` — * identities (tool names), enums, numbers and a boolean. Never the * descriptions the classifier read, never the user's message. * * ## Append only, a fresh array per write * * A row is never replaced. Every write assigns `[...prior, row]` so the * committed value is a new array (a TypedScope array read is a live proxy * view — spread before use). The tools slot runs in an isolated subflow * whose `toolChoices` input is a FROZEN mount arg named `priorToolChoices`; * it hands the prior rows in explicitly and the mount's outputMapper carries * the fresh list back to the parent key. `callLLM` reads the parent key * itself and passes nothing. */ import type { ToolChoiceEntry, ToolChoiceLedger, ToolChoiceOutcomeRow, ToolChoiceRow } from './types.js'; /** The scope surface this file needs. Structurally a `TypedScope<AgentState>`. */ export interface ToolChoiceScope { toolChoices?: ToolChoiceLedger; $emit(name: string, payload?: unknown): void; } /** * Append one row and emit its event. `prior` is the record as the caller's * frame holds it — passed by the tools slot (an isolated subflow that reads * the parent's rows as a frozen arg), defaulted to `scope.toolChoices` by * `callLLM`, which writes on the scope that owns the key. */ export declare function recordToolChoice(scope: ToolChoiceScope, row: ToolChoiceEntry, prior?: readonly ToolChoiceEntry[] | undefined): void; /** The pick or pick-error row filed for `iteration`, or nothing — the call had no pick. */ export declare function pickRowFor(rows: readonly ToolChoiceEntry[] | undefined, iteration: number): ToolChoiceRow | undefined; /** Whether ANY pick was attempted for `iteration` — a `pick` or a `pick-error` row. */ export declare function pickAttemptedFor(rows: readonly ToolChoiceEntry[] | undefined, iteration: number): boolean; /** * The comparison row for one reply. Pure. `firstAgrees` exists only when * both readings do — a pick with a `chosen` and a reply with a call; `miss` * only when the call was narrowed and the model named a tool outside what * was served (a door is served, so it can never be a miss). */ export declare function outcomeRowFor(pick: ToolChoiceRow | undefined, called: readonly string[], iteration: number): ToolChoiceOutcomeRow;