UNPKG

agentfootprint

Version:

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

126 lines (125 loc) • 6.8 kB
/** * The tool calls of THIS run — one `ToolCallFact` each, in call order. * * Outcome, from typed fields only (never a `why` prose): * - `not-dispatched` — `tool_end.notDispatched` (a batch settled on a pause); * - `declined` — a person was asked and declined: a before-tool deny on * the call a RESUMED leg answers (its start is in the * earlier leg), or a `checkin.decision` with * `approved: false`; * - `refused` — BEFORE-tool only: `tool_end.notExecuted`, a deny * `middleware.decision` with `moment: 'before-tool'`, or a * `permission.check` for this call that did not allow; * - `failed` — `tool_end.error`; * - `unknown` — a start with no recorded end; * - `ran` — otherwise. An AFTER-tool deny keeps `ran` and sets * `withheldBy`: the tool ran and the model read the * rule's refusal (`notExecuted` covers before-tool rules * only, and its absence proves nothing). * * Emptiness is read from what the MODEL read — `modelResult ?? result` — and * never judged on a withheld result. The reader is the ONE emptiness reader * (`core/agent/emptiness.ts` · `readEmptiness`), handed the door this * record holds for the call: its absence (the delivered status, `tools.absent`), * its boundary (`tools.coverage_declared`) and its described envelope * (`tools.semantics_declared`). */ import type { RecordPointer, SentenceVar, ToolCallFact } from '../types.js'; import { type ViewEvent } from '../view.js'; import { type EmptinessReading, type ReadContext } from './common.js'; /** * At most this many calls are LISTED in `facts.calls`; the rest are counted. * A cap on what is listed, never on what is judged: the checks, the error * counts and the withheld count read every call (`CallsRead.all`). */ export declare const MAX_CALLS = 50; export type CoverageSectionKey = 'checked' | 'notChecked' | 'cannotCover'; export interface CoverageItemRead { readonly section: CoverageSectionKey; /** The item's words — `''` when the record keeps them out (`keptOut`, below). */ readonly what: string; readonly short?: string; readonly kind?: 'existence' | 'scope'; /** * Present and `true` when the record keeps the item's WORDS out (a * redaction policy left its placeholder on `what` — under the vocabulary, * the value-kind rule, `redaction/knownStrings.ts`): the item exists, with * its `kind`, and a reader says its words are kept out, never prints them. */ readonly keptOut?: true; /** * Pointer base: the declaration that holds the item — its event * (`tools.absent` / `tools.coverage_declared`), or, for a call before a * pause, its row of the committed `coverageDeclared` state. */ readonly base: (...keys: readonly (string | number)[]) => RecordPointer; readonly position: number; } export interface CoverageRead { readonly kind: 'absent' | 'coverage'; /** The declaration's events — empty when it was read from the committed state. */ readonly events: readonly ViewEvent[]; /** Where the declaration's head is: its tool name when the record holds one, else its call id. */ readonly head: RecordPointer; readonly lookedFor?: { readonly text: string; readonly pointer: RecordPointer; }; /** EVERY declared item — the checks judge them all; the rows print what the item budget allows. */ readonly items: readonly CoverageItemRead[]; readonly tryInsteadTool?: { readonly tool: string; readonly pointer: RecordPointer; }; } /** One call, as the row readers need it (the fact plus the events behind it). */ export interface CallRead { readonly fact: ToolCallFact; readonly start?: ViewEvent; readonly end?: ViewEvent; /** The decision or permission row that refused / withheld it. */ readonly ruleEvent?: ViewEvent; readonly coverage?: CoverageRead; /** The `tools.semantics_declared` row: the described envelope as the record keeps it. */ readonly described?: ViewEvent; readonly emptiness: EmptinessReading; readonly findings?: ViewEvent; /** Where the tool's NAME is on the record (its start, its declaration, or its history message). */ readonly toolPointer?: RecordPointer; /** The tool's name as a sentence var — clipped at `FACT_TEXT_CHARS`, pointing at the full name. */ readonly tool: SentenceVar; /** The full tool name (`''` when unnamed) — for declaration lookups; never printed unclipped. */ readonly toolName: string; /** No event of the call names its tool — counted as unread, never dropped. */ readonly unnamed?: true; } export interface CallsRead { /** EVERY call of this run, in call order — what the checks and counts judge. */ readonly all: readonly CallRead[]; /** The first `MAX_CALLS` of them — what `facts.calls` lists. */ readonly calls: readonly CallRead[]; /** Calls past `MAX_CALLS`, counted, not listed. */ readonly omitted: number; /** Ids of every call of this run (listed or not) — the in-view reader skips them. */ readonly ids: ReadonlySet<string>; } /** The committed state's coverage key: every declaration the run's tools made, tracked. */ export declare const COVERAGE_STATE_KEY = "coverageDeclared"; /** * A call's declaration as the committed state keeps it — its rows of * `coverageDeclared` (tracked state: a limit is a fact about the answer, so it * rides every recording, `core/agent/types.ts` · `coverageDeclared`). * What a call BEFORE a pause declared is read here: its events are in the * earlier leg, its rows are in this record's state. */ export declare function readStateCoverage(rows: readonly unknown[], toolCallId: string, served: boolean): CoverageRead | undefined; /** The permission verdicts that stop a call before it runs. */ export declare const PERMISSION_REFUSALS: ReadonlySet<unknown>; /** The one leaf on `tool_end` that says how the call ended, as the account read it. */ export declare function endPointer(end: ViewEvent, emptiness: EmptinessReading): RecordPointer; /** Every call of this run, first-seen order (a resumed leg's paused call has only an end). */ export declare function readCalls(ctx: ReadContext): CallsRead; /** The declaration's head: its tool name when the row holds one, else the call id it was joined by. */ export declare function coverageHead(coverage: CoverageRead): RecordPointer; /** Pointer to one coverage item's leaf. */ export declare const itemAt: (item: CoverageItemRead, field: 'what' | 'short' | 'kind') => RecordPointer;