@juspay/neurolink
Version:
The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002
71 lines (70 loc) • 3.94 kB
TypeScript
/**
* On-demand tool discovery (`tools.discovery: true`).
*
* Instead of sending every external MCP tool's full schema on every request,
* the model receives the hot set (built-in tools, per-call tools, explicitly
* requested tools, and previously discovered tools) plus ONE `search_tools`
* meta-tool whose description embeds a compact name+summary catalog of the
* deferred tools. Calling `search_tools` loads matching tools:
* - immediately into the live tool record — the AI SDK path re-reads the
* record between agent-loop steps, and the native loops (Vertex
* Gemini/Claude, AI Studio, chat-completions, direct Anthropic) re-resolve
* against it on a dispatch miss and refresh their wire declarations per
* step — so discovered tools are callable on the very next step, and
* - into the session pin set (all providers include them in full on every
* subsequent call of the session).
*
* The record additionally carries a symbol-keyed {@link DeferredToolResolver}
* (see `resolveDeferredTool`) so a loop can hydrate a cataloged tool the
* model called directly by name WITHOUT a prior search_tools call — the
* catalog advertises exact names, so models legitimately do this.
*
* Evidence for this design: catalogs past ~30-50 tools measurably degrade
* tool-selection accuracy, and deferral+search both cuts definition tokens by
* ~85% and RAISES selection accuracy (Anthropic MCP-eval 49%→74% on Opus 4).
* The catalog construction (byte-stable, name-sorted, char-budgeted with a
* degradation ladder) mirrors the proven skills-index pattern in
* src/lib/skills/skillTools.ts.
*/
import type { Tool } from "../types/index.js";
/**
* Above this many tools, a WARN suggests enabling `tools.discovery` when it
* is off. Chosen from the measured degradation range (30-50 tools).
*/
export declare const LARGE_CATALOG_WARN_THRESHOLD = 40;
/** True when the value is a search_tools meta-tool generated by this module. */
export declare function isDiscoveryMetaTool(tool: unknown): boolean;
/**
* Partition a (post-gate) tools record for discovery: deferrable tools that
* are not pinned are removed from the record and replaced by one
* `search_tools` meta-tool. Returns the hot record; when nothing is
* deferrable the input record is returned unchanged.
*
* The returned record is mutated by search_tools on hydration (call-scoped —
* BaseProvider builds a fresh merged record per call), which is what makes
* discovered tools callable on subsequent steps of the same agent loop on
* providers that re-read the record between steps.
*/
export declare function partitionToolsForDiscovery(tools: Record<string, Tool>, args: {
/** External-tool names present in `tools` that are allowed to defer. */
deferrableNames: string[];
/** Session-pinned names (previously discovered) — never deferred. */
pinnedNames: ReadonlySet<string>;
/** Called with newly discovered names — persists session pins. */
onHydrate: (names: string[]) => void;
}): Record<string, Tool>;
/**
* Hydrate-and-return a deferred tool by name, when `record` was produced by
* `partitionToolsForDiscovery` and `name` is in its deferred catalog.
* Returns `undefined` for records without a resolver (discovery off) and for
* names that are genuinely unknown — callers keep their hallucinated-name
* handling for that case.
*/
export declare function resolveDeferredTool(record: Record<string, Tool> | undefined, name: string): Tool | undefined;
/**
* Live tool lookup for native agent loops on a dispatch miss: first re-reads
* the record (a tool hydrated by search_tools after the loop built its
* pre-step snapshot), then falls back to auto-hydrating from the deferred
* catalog. Returns `undefined` only when the name is genuinely unknown.
*/
export declare function resolveLiveTool(record: Record<string, Tool> | undefined, name: string): Tool | undefined;