UNPKG

agentfootprint

Version:

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

140 lines (139 loc) • 6.67 kB
/** * scriptRecord — the vocabulary of a code call on the record: the label its * execution record earns, the verdict on a fenced block an answer shows, and * the attachment that travels with an answer. * * Pattern: types only — the words two layers must agree on and cannot import * each other for: the agent's script record (`core/agent/scripts/`, * which re-exports every name here) and the event payloads that carry * it (`events/payloads.ts` · `AgentEvidenceCheckedPayload`, `AgentTurnEndPayload`). * Role: lib/ leaf (L0). No runtime code. * * Design: docs/design/2026-10-script-artifact.md. FOUR FACTS, KEPT APART: * "this is the script submitted" and "this script ran" are facts about a CALL; * "a tool returned this value" is the evidence gate's, from `role: 'tool'` * results only; "this claim holds" has no record. No type here joins them. */ /** * What the record proves about one call of a code-running tool — read from * the runner's EXECUTION evidence first, then from the call's SETTLEMENT, and * never from result delivery (`core/agent/scripts/label.ts` · `scriptLabelOf`): * * - `submitted` — the program is on the record and the call has not returned * (never dispatched, refused before `execute`, or still open). Never "did * not run". * - `returned` — the tool returned and the record holds no execution evidence: * the tool filed no runner facts, or facts that report no outcome. The call * completed; nothing proves the program ran. * - `reported-success` / `reported-failure` — the runner's bare verdict, with * no exit code: no claim that the program ran to an exit. * - `completed` — an explicit exit code 0. * - `completed-with-failure` — an explicit non-zero exit code: the program * reached an exit; what it did before is not known from the exit. * - `outcome-unknown` — no runner facts after a timeout, a cancellation or a * thrown error, or a service error with no exit code. * * A reader must not promote a label to its neighbour. */ export type ScriptLabel = 'submitted' | 'returned' | 'reported-success' | 'reported-failure' | 'completed' | 'completed-with-failure' | 'outcome-unknown'; /** Why a shown block matched no submission. */ export type UnmatchedReason = /** Its content equals no program a call of THIS turn submitted. */ 'no-submission-this-turn' /** Its content is over `MAX_SCRIPT_BYTES`: no row keeps a program that long. */ | 'over-size' /** A reader of a redacted record: the rows' text is kept out. Never in the run. */ | 'kept-out'; /** The verdict on one fenced block of the answer, under `code: 'match'`. */ export type ScriptBlockVerdict = { /** 1-based position among the answer's fenced blocks that were read. */ readonly block: number; /** The matched call's own label — F2, never a fixed "executed". */ readonly label: ScriptLabel; readonly exitCode?: number; /** The provider's id for the call — display only; two calls may share one. */ readonly toolCallId: string; readonly tool: string; /** * The library's identity for the matched call: the 1-based order of the * actual dispatch within its turn. A reused provider id is a new dispatch; * a pause and its settlement are one. */ readonly dispatch: number; /** Other calls of this turn that submitted byte-identical programs (the latest is named). */ readonly alsoMatches?: number; } | { readonly block: number; readonly label: 'unmatched'; readonly reason: UnmatchedReason; }; /** What the match says about one judged answer — on the verdict and `evidence_checked`. */ export interface ScriptsVerdict { /** One entry per fenced block read, in answer order. Never the code. */ readonly blocks: readonly ScriptBlockVerdict[]; /** Script rows of EARLIER turns on the ledger — counted, never compared. */ readonly earlierTurnRows: number; /** Fenced blocks past `MAX_CODE_REGIONS`: read as prose, never matched. */ readonly regionsDropped: number; /** * Calls of this turn past `MAX_SCRIPT_ROWS` (`AgentState.scriptsDropped`): * they filed no row, so a block showing one of them cannot match. Absent * when none was dropped. */ readonly scriptsDropped?: number; } /** One attached script, as `turn_end.scripts.shown` carries it. */ export interface ShownScript { /** The provider's id for the call — display only; two calls may share one. */ readonly toolCallId: string; /** The library's identity for the call: its dispatch order within the turn. */ readonly dispatch: number; /** The name the model called. */ readonly tool: string; /** As declared. */ readonly language?: string; readonly label: ScriptLabel; /** Only when the runner supplied one. */ readonly exitCode?: number; readonly resultWithheld?: 'over-ceiling'; /** A before-tool rule changed the program before dispatch. */ readonly rewritten?: true; /** UTF-8 bytes of the whole program. */ readonly bytes: number; readonly lines: number; /** Present when `text` is a cut: how many bytes of `bytes` it holds. */ readonly truncated?: { readonly shownBytes: number; }; /** The program, cut at `maxBytes` — a model-written string. */ readonly text: string; } /** `turn_end.scripts` — present only under `.scriptTravelsWithTheAnswer()`. */ export interface TurnEndScripts { readonly shown: readonly ShownScript[]; /** * Calls of this turn not attached: past `MAX_ATTACHED_SCRIPTS`, a program * over `MAX_SCRIPT_BYTES` (no text on its row), or a call past * `MAX_SCRIPT_ROWS` (no row). */ readonly omitted: number; /** * The fence the library CLOSED before the attachment: the text before it * (the model's answer, and any library block above) ended inside a fence a * renderer would still be in, so the library wrote the closing fence first * and nothing the model left open could take the programs in. Present only * when it closed one. */ readonly closedFence?: { readonly char: 'backtick' | 'tilde'; readonly length: number; }; /** * `true`: the programs are NOT in the answer's text, only here. The text * before the attachment holds a line after which a renderer could pair * fences another way (an indented fence, raw HTML, display math), so the * library cannot tell what a program would render inside. The labels are * in the text; the programs ride `shown[].text`. Absent otherwise. */ readonly withheldFromText?: true; }