agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
76 lines (75 loc) • 4.21 kB
TypeScript
/**
* artifacts/payload — one owner for how a payload is measured, carried and
* digested.
*
* Three adapters store the same three payload shapes (string, `Uint8Array`,
* JSON value). If each measured or serialized on its own, `bytes` on the meta
* could disagree with what a digest was computed over, and a digest written by
* one adapter would not verify in another. So the laws live once, here:
*
* • `measure` — `bytes` is the UTF-8 length of text/JSON, the byteLength of
* binary. The number a consumer decides from, computed one way.
* • `encode/decode` — the durable adapters persist ONE envelope
* (`text` / `binary` base64 / `json`), so a file written by
* `fileArtifacts` is legible to a debugging human and identical in law to
* a row written by `sqliteArtifacts`.
* • `digest` — sha-256 over the SAME canonical bytes `measure` counts, via
* `globalThis.crypto.subtle` (browser + Node, zero dependencies).
*
* A payload JSON cannot carry (a function, a bigint, `undefined`, a cyclic
* object) is refused BY NAME at put — storing an approximation and returning
* it later as the real thing is the exact accepted-and-silently-wrong failure
* a claim check exists to prevent.
*/
/**
* The canonical bytes of a payload — what `bytes` counts and what a digest
* is computed over. Throws {@link InvalidArtifactError} for a value that
* cannot be carried faithfully.
*/
export declare function canonicalPayloadBytes(data: unknown): Uint8Array;
/** Payload size in bytes — UTF-8 for text/JSON, byteLength for binary. */
export declare function measureArtifactBytes(data: unknown): number;
/**
* Which of the three payload shapes a value is. The durable envelope carries
* it, and so does an object store's metadata — the canonical bytes alone
* cannot say whether `"7"` was the string `'7'` or the JSON number `7`, and a
* store that guessed would hand back a different value than it was given.
*/
export type PayloadShape = 'text' | 'binary' | 'json';
/** The shape a payload will be stored under. Total: everything that is not a
* string or a `Uint8Array` rides as JSON (and is refused at measure/encode if
* JSON cannot carry it). */
export declare function payloadShapeOf(data: unknown): PayloadShape;
/**
* Rebuild a payload from its CANONICAL BYTES and its shape — the read half of
* `canonicalPayloadBytes`, for stores that hold the bytes themselves (an
* object body, a stream) rather than the text envelope.
*
* Round-trip law: `decodeCanonicalPayload(payloadShapeOf(x),
* canonicalPayloadBytes(x))` equals `x` for every payload this library
* accepts — which is what lets `bytes`, the digest, and the stored object all
* be the same bytes in every adapter.
*/
export declare function decodeCanonicalPayload(shape: PayloadShape, bytes: Uint8Array): unknown;
/** `sha-256:<hex>` over the canonical bytes. */
export declare function computeArtifactDigest(data: unknown): Promise<string>;
/** How a payload rides a file or a SQL TEXT column. One shape, two adapters.
*
* `'external'` (9.25.0) is the STREAMED case and exists only where a store
* can hold bytes beside the envelope: the payload is not in `value` at all —
* `value` names the sibling file that holds it, and the artifact reads back
* as binary. Only `fileArtifacts` writes it; `decodeArtifactData` refuses it
* by name, because a decoder that cannot reach the bytes must not pretend. */
export interface EncodedPayload {
readonly shape: PayloadShape | 'external';
/** `text`: the string. `binary`: base64. `json`: the JSON serialization.
* `external`: the name of the sibling file holding the raw bytes. */
readonly value: string;
}
/** Encode for durable storage. Validates exactly as `measure` does. */
export declare function encodeArtifactData(data: unknown): EncodedPayload;
/** Decode what {@link encodeArtifactData} wrote. Total over its own output;
* an `'external'` envelope is the one thing it refuses, by name — the bytes
* live beside the envelope and only the adapter that wrote them can reach
* them. */
export declare function decodeArtifactData(encoded: EncodedPayload): unknown;