UNPKG

agentfootprint

Version:

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

216 lines • 10.4 kB
/** * auditBounding — HOW the audit chain's bounded mode bounds a value: the * markers, the sanitizer, the leaves and the combinators every shape is built * from (`auditShapes.ts` says WHAT each event keeps; `auditKeptByContract.ts` * names what a record keeps although it may carry a run's value). * * Pattern: small pure rules composed into shapes; every rule records what it is * (`ruleKind`), so a test can walk a shape beside the type it bounds * and hand every rule what its kind forbids. * Role: the bounding layer `auditExport({ payloadMode: 'bounded' })` runs * every payload and every record's meta through (`audit.ts`). No I/O, * no clock. * Emits: N/A. * * THE RULE, the one `otel.ts` maps spans by: **structure is kept, content is * a marker**, bounding is CLOSED by default, and every kept value is CHECKED: * * - Every registered event has a shape that names every field of its * payload type (`shapeOf` is exhaustive by type: a field added to a * payload does not compile until it is classified). * - A field a shape does not name, a value that is not the declared shape, * and every field of an event type the registry does not declare, is a * marker. * - A type says what a field holds; it cannot say what ARRIVES. So nothing is * kept on a type's word: a kept leaf checks at runtime the kind its type * promises — `num` a number, `bool` a boolean, `str` a string, `oneOf` one * of the words it lists — and anything else is a marker. No container is * kept whole: an object is a `shapeOf` (or a `recordOf`), a list a * `listOf`, every child ruled, so a child the type does not declare is a * marker however it got there (structural typing lets an object carry one). * The type walker (`test/type-regressions/AuditBoundingDepth.test.ts`) * holds every rule to the type beneath it; the runtime sweep * (`test/observability-providers/audit-bounded-sweep.test.ts`) hands every * rule what its kind forbids. * - Names are data. A key is kept as an own key of the record, whatever it is * (a name `Object.prototype` holds included: an assignment would drop * `__proto__`, or re-prototype the record), and no rule table is ever asked * for a name it merely inherits. * * Content becomes `'[N chars]'` (a string), `'[type: …]'` (anything else), * `'[keys: …]'` (a free-form record: its key names, never its values), or a * count (`'[N messages]'`, `'[N blocks]'`, `'[N summaries]'`). A kept string is * capped at 256 characters, a list at 32 items. */ /** * Convert any value to a JSON-safe, size-bounded tree: * strings capped, arrays capped with an overflow marker, cycles * broken, depth capped, Date → ISO, bigint → string, non-finite → * null, functions/symbols/undefined dropped (objects) or null * (arrays). Every key an own key. Output always canonicalizes without * throwing. */ export declare function sanitizeJson(value: unknown, depth?: number, seen?: Set<object>): unknown; /** How the bounded mode writes one value. */ export type BoundRule = (value: unknown) => unknown; /** The kind of a value, as a rule checks it at runtime. */ export type ValueKind = 'string' | 'number' | 'boolean' | 'null' | 'array' | 'object'; /** A value's kind — `undefined` for one JSON has no word for (a function, a symbol, a bigint). */ export declare function valueKindOf(value: unknown): ValueKind | undefined; /** * What a rule is, so a test can walk a shape beside the type it bounds and * hand each rule what its kind forbids. Every rule this module builds has one; * a function it did not build has none, and the walkers refuse it. */ export type RuleKind = /** Keeps nothing of the value: its length, its key names, its type or its count. */ { readonly kind: 'marker'; readonly marks: 'chars' | 'keys' | 'type' | 'count'; } /** Keeps a value of this one kind (a string capped); anything else is a marker. */ | { readonly kind: 'leaf'; readonly accepts: 'number' | 'boolean' | 'string'; } /** Keeps a value that is one of these words; anything else is a marker. */ | { readonly kind: 'oneOf'; readonly values: ReadonlySet<string | number | boolean>; } /** An object: each named field by its rule, any other field a marker. */ | { readonly kind: 'shape'; readonly fields: ReadonlyMap<string, BoundRule>; } /** A list: each item by the rule. */ | { readonly kind: 'list'; readonly item: BoundRule; } /** An object with open keys: every key kept, every value by the rule. */ | { readonly kind: 'record'; readonly value: BoundRule; } /** One value or a list of them, each by the rule. */ | { readonly kind: 'orList'; readonly item: BoundRule; } /** `null` kept; anything else by the rule. */ | { readonly kind: 'nullOr'; readonly inner: BoundRule; } /** The first alternative that accepts the value's kind; none, a marker. */ | { readonly kind: 'either'; readonly alternatives: readonly BoundRule[]; } /** One rule or another, by a test of the value — the reason written down. */ | { readonly kind: 'when'; readonly why: string; readonly then: BoundRule; readonly otherwise: BoundRule; } /** A position the record keeps although it may carry a run's value — named (`auditKeptByContract.ts`). */ | { readonly kind: 'byContract'; readonly exception: string; readonly inner: BoundRule; }; /** What a rule is — `undefined` only for a function this module did not build. */ export declare function ruleKind(rule: BoundRule): RuleKind | undefined; /** * The value kinds a rule KEEPS something of at its own position — what * `either` dispatches on. A marker accepts none: it keeps nothing of any value. * * @internal */ export declare function acceptedKinds(rule: BoundRule): ReadonlySet<ValueKind>; export declare function typeofOf(value: unknown): string; /** `'[23 chars]'` — length evidence without content. */ export declare function charsMarker(value: unknown): string; /** `'[keys: a, b, c]'` — shape evidence for free-form Records. */ export declare function keysMarker(value: unknown): string; /** `'[type: object]'` — what kind of value, nothing of it (a tool's result). */ export declare const typeMarker: BoundRule; /** `'[3 messages]'` — a conversation's history. */ export declare const messagesMarker: BoundRule; /** `'[2 blocks]'` — the model's thinking blocks. */ export declare const blocksMarker: BoundRule; /** `'[4 summaries]'` — the previews of what a slot dropped. */ export declare const summariesMarker: BoundRule; /** A count, a duration, a score, an index: kept when it IS a number (non-finite as `null`). */ export declare const num: BoundRule; /** A flag or a verdict: kept when it IS a boolean. */ export declare const bool: BoundRule; /** * The record's own word — an id, a name, a code, a label the app declared: kept * when it IS a string, capped. Where the type is a closed union of words, use * `oneOf`, which keeps only those words. */ export declare const str: BoundRule; /** * One of the listed words (or numbers, or booleans): kept when the value IS one * of them — so what it keeps is always a word this table wrote. Anything else * is a marker. */ export declare function oneOf(...values: readonly (string | number | boolean)[]): BoundRule; /** * Every key of `T` — of EVERY member when `T` is a union. `keyof` of a union is * only the keys all members share, so a field one member alone carries would * escape the shape's exhaustiveness. */ export type AnyKeyOf<T> = T extends unknown ? keyof T : never; /** * An object of a known shape, every field ruled (exhaustive by type, so a field * added to `T` does not compile until it is). A field the rules do not name is * a marker: whatever the value carries at runtime is bounded until someone * decides it is the record's own words. Anything but an object is a marker too. */ export declare function shapeOf<T>(rules: { readonly [K in AnyKeyOf<T>]-?: BoundRule; }): BoundRule; /** A list: each entry by `rule`, capped at 32 like every list. Anything else is a marker. */ export declare function listOf(rule: BoundRule): BoundRule; /** A map with open keys: every key kept (a key is a name), every value by `rule`. Anything else is a marker. */ export declare function recordOf(rule: BoundRule): BoundRule; /** One value, or a list of them, each by `rule` — a guard's declared value is either. */ export declare function orList(rule: BoundRule): BoundRule; /** `null` stays `null` (a declared "none"); anything else by `rule`. */ export declare function nullOr(rule: BoundRule): BoundRule; /** * A value of one of several kinds — a library word or a window, a facet word or * a filter: the first alternative that accepts the value's kind bounds it. A * value no alternative accepts is a marker. */ export declare function either(...alternatives: readonly BoundRule[]): BoundRule; /** * One rule or another, by a test of the value itself, the reason written down — * the few places a field is structure only for some values (a name this * strategy has seen run, the engine's own decision evidence). */ export declare function when(why: string, test: (value: unknown) => boolean, then: BoundRule, otherwise: BoundRule): BoundRule; /** * A position a bounded record keeps although its value may come from the run — * one of the exceptions `auditKeptByContract.ts` names, in one place. The rule * inside still checks the value like every other: an exception keeps a value of * its declared kind, never whatever arrives. */ export declare function byContract(exception: string, rule: BoundRule): BoundRule; /** An event type the registry does not declare (a consumer's own `emit`): every field a marker. */ export declare const unknownEventShape: BoundRule; /** * Tool names this strategy has seen RUN — a `stream.tool_end` without `error`, * `notExecuted` or `notDispatched`, matched to its `tool_start` by * `toolCallId` — so a tool this agent holds, by construction. What a * `tryInsteadTool` name is recognized against (`otel.ts` keeps the same set). */ export declare function createToolRunTracker(): { observe(type: string, payload: unknown): void; ran(name: string): boolean; }; //# sourceMappingURL=auditBounding.d.ts.map