UNPKG

agentfootprint

Version:

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

132 lines (131 loc) • 6.95 kB
/** * `recordingView` — ONE indexed pass over a recording, filtered to THIS run. * * Every reader of the account asks the view, never the raw `events` array, so * "which event is where" has one owner (and `failureCauses`, when it ships, * reuses it). * * Whose events: the rule `bridge/eventMeta.ts` · `eventBelongsToRun` owns (an * event that names a run belongs to that run; one that names none, to runs of * its session). The run is identified by the agentfootprint run id — NOT * `snapshot.runId`, which is footprintjs's executor id and a different id space * (filtering on it would drop every event). In order: * 1. `options.runId` — the stored artifact's `meta.origin.runId`; * 2. else the one run id on the recording's `agent.run_configured` events; * 3. with more than one (a shared-agent recording made before runs kept their * own events): the run that owns `turn_end` — never simply the first; * 4. with none of these, NOTHING is filtered and `scope` says `'unfiltered'`. * * Tolerance: an event that is not an object with a string `type` and an object * `payload` is passed over and counted in `unread`. Indices are the RECORDING's * indices, so a pointer lands on the event the reader can open. * * A REDACTED recording (a run under an agent's `redact`) holds a placeholder * where the policy selected a value: `[REDACTED]` for a payload field (or for a * whole payload, under `emitPatterns`), and `REDACTED` for a state key. Its * snapshot says it was served under a policy (`redaction/marker.ts`); in such * a record — and ONLY there; a tool can return the string `'REDACTED'` too — * a placeholder is NO value: a field or key that holds one reads as absent, * never as a result to judge or a pause to report — and it is NAMED * (`ViewEvent.redacted`, `RecordingView.stateKeptOut`), so a fact that would * otherwise say "not recorded" can say "kept out" (`keptOut`, * `RecordingView.isStateKeptOut`). An event whose whole payload is kept out * is still an event of the run: its type and meta are read, its payload is * empty. * * THE GUARD. A reader that touches a kept-out field without asking about it * would state a fact about a placeholder ("no tool ran" from a kept-out * `toolCallId`). So the view watches: every kept-out field or state key a * reader TOUCHES (reads, or tests with `in`) is noted, and so is every one it * ASKS about; `keptOutRead()` lists the touched ones never asked about, and * the account refuses to tell over them (`account.ts` · `notToldAccount`). * An unredacted recording is read through no guard at all. */ import { isPlaceholder } from '../redaction/marker.js'; /** An event of the run, narrowed to what a reader may touch, at its recording index. */ export interface ViewEvent { readonly index: number; readonly type: string; readonly payload: Readonly<Record<string, unknown>>; readonly meta: Readonly<Record<string, unknown>>; /** * What the record keeps out of this payload (a redaction policy left its * placeholder there): the names of the fields that hold it, or `'whole'` * when the policy kept the whole payload out. A kept-out field reads as * absent in `payload`; ask {@link keptOut} before saying a value does not * exist. Absent when nothing was kept out. */ readonly redacted?: readonly string[] | 'whole'; } /** * Whether the record keeps `field` of `event`'s payload out (see * `ViewEvent.redacted`) — and a reader that asks has handled it, so touching * the field afterwards is not a read of a placeholder (the view's guard). */ export declare function keptOut(event: ViewEvent | undefined, field: string): boolean; export interface RecordingView { /** This run's events, in recording order. */ readonly events: readonly ViewEvent[]; /** The run id the filter keyed on (absent when `scope` is `'unfiltered'`). */ readonly runId?: string; readonly sessionId?: string; readonly scope: 'own-run' | 'unfiltered'; /** Events of another run — never read. */ readonly foreign: number; /** Events passed over because their shape did not fit. */ readonly unread: number; /** * The record was SERVED under a redaction policy — its snapshot carries the * marker (`redaction/marker.ts`). Only then is a placeholder a value the * record keeps out; in any other record it is a value like any other. */ readonly servedUnderPolicy: boolean; /** `snapshot.sharedState`, when it is an object — without the keys it keeps out. */ readonly state?: Readonly<Record<string, unknown>>; /** The state keys the record keeps out (they hold the redaction placeholder). */ readonly stateKeptOut: readonly string[]; /** Whether the record keeps state `key` out — asking handles it (the view's guard). */ isStateKeptOut(key: string): boolean; /** * `snapshot.sharedState` exactly as the record holds it, placeholders and * all — for a reader that judges kept-out keys itself (the standing fold, * `core/agent/assessment/assess.ts` · `assessAnswer`). Every other reader * reads `state`. */ readonly stateAsRecorded?: Readonly<Record<string, unknown>>; /** * `snapshot.initialState`, when it is an object with a `history` — on a * resumed leg, the state the run PAUSED with (a fresh run's is empty). The * part of the answer before the pause is read from it * (`facts/pausedLeg.ts`). */ readonly pausedWith?: Readonly<Record<string, unknown>>; /** Every event of one type (the agentfootprint prefix is optional). */ ofType(type: string): readonly ViewEvent[]; /** * What readers read but the record keeps out: every kept-out payload field * (`<event type> · <field>`) and state key (`state · <key>`) a reader * touched without asking about it first (`keptOut`, `isStateKeptOut`). A * fact read from one would be a fact about a placeholder. Empty when there * is none — always, for a recording nothing was kept out of. */ keptOutRead(): readonly string[]; first(type: string): ViewEvent | undefined; last(type: string): ViewEvent | undefined; } export declare const isRecord: (value: unknown) => value is Record<string, unknown>; export declare const str: (value: unknown) => string | undefined; export declare const num: (value: unknown) => number | undefined; /** * Whether `value` is a redaction placeholder — a value the record keeps out. * Asked only of a record SERVED under a policy (`redaction/marker.ts` · * `servedUnderPolicy`): anywhere else the same string is a value a tool or a * person really produced. */ export declare const isKeptOut: typeof isPlaceholder; export declare function recordingView(recording: { readonly events?: unknown; readonly snapshot?: unknown; }, options?: { readonly runId?: string; }): RecordingView;