agentfootprint
Version:
The explainable agent framework — backtrack a wrong answer to the exact context that caused it (evidence, not guesses). Built on footprintjs.
51 lines • 2.13 kB
JavaScript
/**
* lease — the app's explicit, bounded hold on one conversation's client.
*
* Pattern: a handle that releases at most once, by hand or by `await using`.
* Role: § 3.3 and § 5.2 of the design. `acquire` is for code that drives a
* sequence itself, or a host that must keep a conversation's client
* from eviction for a whole turn (it holds one around `agent.run()`, and
* the provider then finds the same client). It is the only way to
* protect a client between calls: there is no hidden grace period.
*
* The `acquire` that opened it was the operation; the held lease is not one. It
* is bounded by `maxLeaseMs`: past it, it is revoked at the next pool
* interaction and reported, and its next use throws `lease-expired`. Calls
* already in flight keep their own leases until they settle.
*/
import { ASYNC_DISPOSE } from '../../strategies/lifecycle.js';
import { noteRefusal } from './boundTool.js';
import { listTools } from './listTools.js';
import { UseFacts } from './record.js';
/** The lease handle for `held`, on `key`'s client. */
export function leaseHandle(pool, key, held) {
const release = () => {
if (held.released)
return;
held.released = true;
pool.endLease(held);
pool.interact();
};
const handle = {
async tools(options) {
pool.interact();
if (held.revoked || held.released)
throw pool.refused('lease-expired');
const facts = new UseFacts(pool.settings.name, 'list');
try {
return await listTools(pool, key, options?.signal, facts);
}
catch (error) {
noteRefusal(facts, error);
throw error;
}
},
release,
[ASYNC_DISPOSE]: async () => release(),
};
// The computed key gives TypeScript a symbol index rather than the one
// well-known member `AsyncDisposable` names; at runtime it IS
// `Symbol.asyncDispose` on every engine this package supports.
return handle;
}
//# sourceMappingURL=lease.js.map