agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
94 lines (93 loc) • 4.67 kB
TypeScript
/**
* openRecording — a saved run, reopened as evidence a model can navigate.
*
* Pattern: pure adapter. One shape in (`Recording`), one shape out
* (`TraceToolpackArtifacts`). No engine, no agent, no I/O.
* Role: the door between the two halves of this library that already
* knew about each other's data and had no way to say so.
*
* `recordRun(agent)` freezes a run into `{ snapshot, events, structure }` —
* the shape a viewer reads. The trace toolpack reads a different shape.
* Until now, a team with a recording on disk from last Tuesday and a
* question about it had to reassemble the bag by hand, which meant
* reassembling it differently in every integration and losing the
* narrative and the events on the way.
*
* const recording = JSON.parse(fs.readFileSync('run.json', 'utf8'));
* const tools = traceToolpack(openRecording(recording));
* await callTraceTool(tools, 'run_overview');
*
* WHAT SURVIVES THE ROUND TRIP, AND WHAT DOES NOT
* ───────────────────────────────────────────────
* A recording is JSON. Everything the toolpack needs from the snapshot
* survives that (the commit log, the execution tree, shared state, the
* mode discriminants) and so do the events. Two things do not:
*
* - `controlDeps` is a LOOKUP FUNCTION built by a recorder that watched
* the run happen. A function does not serialize, and nothing in a
* finished recording can rebuild one. So slices opened over a
* recording carry the toolpack's existing "⚠ control edges
* unavailable" marker — the honest answer, already written.
* - The narrative survives only if it was ATTACHED. `recordRun`
* deliberately attaches no narrative recorder (see its header), so a
* recording made without `narrative()` has none, and `read_narrative`
* is simply not mounted. This function lifts it from the snapshot's
* recorder rows when it IS there.
*
* `structure` — the build-time chart — has no reader in the toolpack: the
* toolpack navigates what a run DID, and the chart says what it COULD do.
* It is left on the recording for the viewers that draw it.
*/
import type { TraceToolpackArtifacts } from './types.js';
import { type PackedRecording } from '../recorders/observability/recordingPack.js';
/**
* The recording shape — structurally the `Recording` that `recordRun`
* produces, restated here so this module stays a leaf (it must not pull
* the recorder layer into a pure adapter's import graph). A `Recording`
* satisfies it by construction.
*/
export interface OpenableRecording {
readonly snapshot: unknown;
readonly events?: readonly unknown[];
readonly structure?: unknown;
}
/** A recorder row as it rides `snapshot.recorders`. */
interface RecorderRow {
readonly id?: string;
readonly name?: string;
readonly data?: unknown;
}
/**
* The narrative recorder's row: `data` is an array of `{ text, depth }`.
*
* @internal Exported for the bug-report bundler, which writes the same lines to
* `narrative.txt`. One shape-detector, one answer to "is there a narrative in
* this snapshot?" — two copies would disagree the first time the row changes.
*/
export declare function narrativeFrom(snapshot: {
recorders?: readonly RecorderRow[];
}): string[] | undefined;
/**
* Reopen a saved recording as toolpack artifacts.
*
* @param recording the `{ snapshot, events, structure }` bundle from
* `recordRun(...).toRecording()` — live, or parsed back
* from JSON — or the same recording packed
* (`packRecording`), which is expanded first.
*
* A packed recording is expanded only when its plain form is within
* `unpackRecording`'s default bound (`DEFAULT_UNPACK_MAX_BYTES`, 512 MiB): the
* toolpack previews a value by serializing it, so it walks what it reads as a
* tree, and a few KB packed can stand for far more than any plain recording
* could hold. A larger recording you trust is opened by expanding it first,
* with the bound you choose:
* `openRecording(unpackRecording(packed, { maxBytes }))`.
*
* @throws PackedRecordingTooLargeError for a packed recording over that bound.
* @throws when the recording carries no usable snapshot. A toolpack over
* an empty bag would answer every question with "nothing
* happened", which is the one answer a debugging session must
* never be given by mistake.
*/
export declare function openRecording(input: OpenableRecording | PackedRecording): TraceToolpackArtifacts;
export {};