UNPKG

agentfootprint

Version:

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

104 lines • 5.16 kB
/** * definitions — the tool lists a pool serves, and when each stops being served. * * Pattern: one list type, two owners — a client incarnation, or a shared entry. * Role: § 6 of the design. A definition is what one `tools/list` entry says: * name, description, input schema, and the declarations its `_meta` * carries. The executable half (the connection) is never shared. * * - PER CLIENT (the default): a conversation's list is its own client's, and * it belongs to that client INCARNATION alone — a replacement client, even * one opened from the same plan, is a new session whose list may differ, * so it lists again. * - SHARED, only under the app's declared contract: one entry per context * (`plan.ts`), listed on the client of whichever conversation needs it, * bounded at `MAX_DEFINITION_ENTRIES` entries; a list longer than * `MAX_SHARED_TOOLS` is used by its own client and not shared. * * A list stops being served in four ways, plus a time limit: the configuration * (a new context is a new list), the server's tools-changed notice, the app's * `permissionsChanged`, and `toolsChanged`. Invalidation moves the list's * GENERATION at once — every tool bound to an older one is refused — and marks * it to be listed again. A lapsed time limit lists again at the next list, and * moves the generation only if the new list differs. A generation counts within * one list: a replacement client and a new entry start counts of their own, and * a binding names the list it came from, so no number of an old list can match * a new one. A listing still in flight when its list's generation moved is * discarded, never written. * * Every list is a frozen plain-data copy (`mcp/plainData.ts` · `copyJsonObject`), * written once per generation, by one listing at a time. */ import type { Tool } from '../../tools/tools.js'; import type { McpListedTool } from '../types.js'; /** One definition, frozen, and its canonical JSON — what "the same definition" compares. */ export interface Definition { readonly listed: McpListedTool; readonly canonical: string; } /** A frozen copy of `listed`, or `undefined` when it is not plain JSON data. */ export declare function definitionOf(listed: McpListedTool): Definition | undefined; /** * One list: an incarnation's own or a shared entry. Its `id` is stable for its * life; its `generation` moves on invalidation, and on a time-limit relisting * that changed it. */ export declare class DefinitionList { readonly id: string; private current; private tools; /** Has any listing been written? */ private written; /** 0 until the first listing is written. */ generation: number; /** Invalidated: listed again before it is served. */ stale: boolean; /** When it was last written, on the pool's clock. */ listedAt: number; /** The listing in flight, joined by anyone who needs the same list. */ listing: Promise<void> | undefined; /** Can it be served at `now`, as it stands? */ servable(now: number, ttlMs: number): boolean; /** * Invalidate: every older binding is refused, the next list lists again, and * a listing in flight is discarded — even a first one, before anything was * written. Generations only ever increase. */ invalidate(): void; /** The definition named `name`, at the current generation. */ definition(name: string): Definition | undefined; /** The client's own wrapped tool named `name` (per-client lists only). */ tool(name: string): Tool | undefined; /** Every definition, in listing order. */ all(): readonly Definition[]; /** * Write a listing that began at generation `began`. Refused — `false`, nothing * written — when the generation moved while it ran. A first write moves the * generation to a number no binding has seen; a write after invalidation keeps * the moved one; a time-limit rewrite moves it only when the list differs. */ write(began: number, definitions: readonly Definition[], tools: readonly Tool[] | undefined, now: number): boolean; } /** A shared entry: a list and the tenant its context carries. */ export interface SharedEntry { readonly list: DefinitionList; readonly tenant: string; } /** * The shared definition entries, by context — bounded at * `MAX_DEFINITION_ENTRIES`, the least recently used dropped first. A dropped * entry's bindings are refused as stale: the entry they name is gone. */ export declare class SharedDefinitions { private readonly maxEntries; private readonly entries; constructor(maxEntries?: number); get size(): number; /** The entry for `context`, created empty when there is none; most recently used. */ entryFor(context: string, tenant: string): SharedEntry; /** The entry for `context` if it still exists — never created. */ peek(context: string): SharedEntry | undefined; /** Invalidate every entry `matches` selects. */ invalidate(matches: (entry: SharedEntry) => boolean): void; } //# sourceMappingURL=definitions.d.ts.map