UNPKG

@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

98 lines (97 loc) • 4.73 kB
/** * ToolExecutionRecorder — real per-call tool execution capture. * * One recorder is created per generate()/stream() call and attached to the * request options (surviving option spreads). Tools are wrapped exactly once * at the central tool-assembly points (BaseProvider.prepareGenerationContext / * getToolsForStream), so every loop — the AI-SDK loop and the native * Gemini/Anthropic loops alike — records through the same wrapper with real * params, timing, and error status. Memory is bounded: serialized results are * capped at `maxResultChars` and the record list at `maxRecords`. */ import type { Tool, ToolExecutionCaptureOptions, ToolExecutionRecord, StandardRecord, ToolExecutionSummaryInternal } from "../types/index.js"; /** Default cap on serialized result characters kept per record (~8KB). */ export declare const DEFAULT_TOOL_RESULT_CAPTURE_CHARS = 8192; /** Default cap on records kept per turn. */ export declare const DEFAULT_TOOL_EXECUTION_MAX_RECORDS = 500; /** * Serialize a tool result to bounded text. JSON when serializable, else * String(); truncation is explicit so consumers know the text is partial. */ export declare function serializeToolResult(result: unknown, maxChars: number): string; /** * Error-shaped tool results (MCP `isError`, `{error}` payloads) count as * failures even though the loop received them as normal returns. */ /** * True for an `error` value that actually carries something — `true`, a * non-empty string, or a non-empty object/array — never a falsy placeholder * a tool sets on every call (`error: false`, `error: 0`, `error: {}`). */ export declare function isMeaningfulError(error: unknown): boolean; export declare function isErrorShapedToolResult(result: unknown): boolean; /** * Per-call recorder for tool executions. See module doc. */ export declare class ToolExecutionRecorder { #private; constructor(capture?: ToolExecutionCaptureOptions); /** Record one completed (or failed) execution. Never throws. */ record(entry: { toolName: string; params: unknown; result?: unknown; error?: unknown; startedAt: number; durationMs: number; }): void; /** All records captured so far (oldest first, bounded by maxRecords). */ getRecords(): ToolExecutionRecord[]; /** True when at least one execution was recorded. */ hasRecords(): boolean; /** Number of records evicted by the maxRecords cap. */ getDroppedCount(): number; /** * Wrap every executable tool so its invocations are recorded. Wrapping is * idempotent — already-wrapped executes are left untouched, so a generate * that falls back to another path never double-records. */ wrapTools(tools: Record<string, Tool>): Record<string, Tool>; /** * Attach this recorder to a request options object. The property is * enumerable on purpose: downstream stages spread options (`{...options}`) * and the recorder must survive into the provider loops. */ attachTo(options: object): void; /** Retrieve the recorder a request is carrying, if any. */ static from(options: unknown): ToolExecutionRecorder | undefined; } /** * Convert legacy loop-local `{name, input, output}` entries (plus optional * timing/error fields) into `ToolExecutionRecord`s. Used as the fallback when * a path produced executions the recorder did not see (e.g. results captured * before the recorder existed, or breaker/not-found entries that never * reached a real execute()). */ export declare function toToolExecutionRecords(legacyExecutions: unknown[] | undefined, capture?: ToolExecutionCaptureOptions): ToolExecutionRecord[]; /** * Resolve the toolExecutions for a result: recorder records when the request * carried a recorder that saw executions, else a conversion of the loop's * legacy accumulator entries. */ /** * The public `toolCalls` view of a native turn's execution summaries. * * The native generate loops record every executed call in * `ToolExecutionSummaryInternal[]` and surface it as `toolExecutions`, but * never mapped it onto `EnhancedGenerateResult.toolCalls` — the field the type * has always declared and the ai-package formatter used to fill. A caller * reading `result.toolCalls` after a tool ran saw nothing. This is the one * place that mapping lives, so the three native paths cannot drift apart. */ export declare function toolCallsFromSummaries(summaries: ReadonlyArray<ToolExecutionSummaryInternal>): Array<{ toolCallId: string; toolName: string; args: StandardRecord; }>; export declare function resolveToolExecutionRecords(options: unknown, legacyExecutions?: unknown[]): ToolExecutionRecord[];