agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
93 lines • 5.67 kB
TypeScript
/**
* callLifetime — one MCP tool call, from the moment it is sent until it settles:
* what cancels it while it runs, and what its settling stops.
*
* Pattern: open / close around `callTool` (`mcpClient.ts` · `wrapMcpTool`).
* Role: The call's side of the evidence seam (`requestLedger.ts` is the
* transport's). Three things are true of a call while it runs, and
* none of them may outlive it:
*
* 1. ITS CANCELLATION reaches the SDK. The call's context signal (the run's,
* for a call the agent dispatched) and the client's own `signal` are linked
* into one signal the SDK request is given — so a cancelled run makes the
* SDK reject the call, drop its response handler and send the server
* `notifications/cancelled`, whether or not the request could be matched to
* the call. The link is undone when the call settles: the SDK keeps its
* abort listener on the signal it was given, and a link that outlived the
* call would cancel a request that had already finished.
* 2. ITS MARKER is issued when the connection has a ledger, with its ticket
* when the call carries the run's evidence port: a library-private string
* in the request's `_meta` (`callMarker.ts`), which ties the request to
* the call even when the SDK copies the params, and which the transport
* takes out before anything is sent.
* 3. ITS SETTLING ENDS ITS SERIES. However `callTool` settles — answered,
* failed, or given up by the SDK (its own timeout) — a retry series still
* sending the request is cut there and then, inside the call: it files
* `cancelled` before the call's result is read, and sends nothing more.
* 4. ITS VERDICT REACHES ITS RECORD. A series that has ended waits for the
* call to settle before it files, because only the call can say whether
* the answer completed — a 200 can carry a tool error. The call leaves its
* verdict in the request's shared replay facts (`replay.ts` ·
* `RequestReplay`) before it settles the series' wait.
* 5. "MAY HAVE RUN" IS RAISED HERE — footprintjs's law, under the
* `'app-authorized'` policy (`replay.ts` · `RequestReplay`, its
* `uncertain`). A received refusal or error is preserved: a 429, a 503,
* a JSON-RPC or tool error — or a chain in which every attempt received
* one — keeps the server's error as it came, its effect still `unknown`.
* A call that genuinely lacked an answer somewhere — an attempt with no
* response at all, or a request the HTTP layer accepted whose JSON-RPC
* answer never came — and then fails, fails with footprintjs's
* `UnknownEffectError`, its final error (a later refusal's, or the
* timeout) as the `cause`: that error alone would read as "failed, try
* again". A call that completes returns normally. Under `'compatibility'`
* the caller sees the error it always did; the record still says the
* effect is unknown. A cancellation never raises it: a call its caller
* cancelled ends with the caller's reason, as it always did.
*
* In dev mode, a ticket that no request was matched to by the time the call
* settled, when a `tools/call` request DID go out, is named once per
* connection: the SDK rebuilt the params without the marker, so the call's
* attempts could not be matched to it. Its cancellation still reached the
* request (1, and the ledger's own watch on `notifications/cancelled`). Under
* `'app-authorized'` such a request is never sent at all
* (`replayUnavailable.ts`).
*/
import type { CallVerdict } from './replay.js';
import type { RequestLedger } from './requestLedger.js';
/** A call that has been opened: the params to send, the signal its SDK request runs under, and how to close it. */
export interface OpenCall<P extends object = object> {
/**
* What to hand the SDK: the call's params, with its private marker in
* `_meta` when a ledger watches the connection (`callMarker.ts`). The
* transport takes the marker out again: the server never sees it.
*/
readonly params: P;
/** What cancels the SDK request — absent when nothing can. */
readonly signal?: AbortSignal;
/**
* The call failed with `error` (`verdict` says how far it got): the error it
* fails with — `error` itself, or, under `'app-authorized'`, footprintjs's
* `UnknownEffectError` with `error` as its `cause` when the call genuinely
* lacked an answer somewhere (see 5 above).
*/
failed(error: unknown, verdict: CallVerdict): unknown;
/**
* The call settled with `verdict`: leave it for the record, settle it in the
* ledger (its answer is no longer awaited), undo the link, cut a series
* still sending, check its request was matched.
*/
close(verdict: CallVerdict): void;
}
/**
* Open one call.
*
* @param params the request's params. The call sends them marked
* (`OpenCall.params`): the marker, not the object, is how the ledger knows
* the request is this call's — it survives an SDK that copies the params.
* @param ctx the call's context: its signal, and the run's evidence port if any.
* @param clientSignal the client's own `signal` (`McpClientOptions.signal`).
* @param ledger the connection's ledger, when the library built its transport.
* @param server the client's name, for the dev-mode note.
*/
export declare function openCall<P extends object>(params: P, ctx: unknown, clientSignal: AbortSignal | undefined, ledger: RequestLedger | undefined, server: string): OpenCall<P>;
//# sourceMappingURL=callLifetime.d.ts.map