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

55 lines (54 loc) • 3.1 kB
/** * In-turn context guard for Gemini-shaped agent loops (native Vertex + AI * Studio + Gemini 3). * * These loops already had `createContextGuard`, but it is **stop-only**: once * the projected prompt crosses the threshold it breaks the loop and synthesizes * an answer from whatever it has. That avoids a provider rejection, but it also * ends the turn early — the model stops doing work it was mid-way through. * * This module brings them to parity with the other loops: reclaim budget and * CONTINUE, falling back to the existing stop only when reclaiming cannot get * back under the line. The reclaim policy is shared with every other provider * via `loopGuardCore`; this module owns only the Gemini shape mapping. * * Gemini history is `{ role, parts[] }`, where a part is a `functionCall` * (tool invocation) or `functionResponse` (its result). One model turn can * carry several `functionCall` parts and the following user turn carries the * matching `functionResponse` parts, so the CONTENT is the batch unit — * dropping a call turn together with its response turn can never orphan a part, * which Gemini rejects. */ import type { GeminiGuardContent, LoopGuardPlan } from "../types/index.js"; /** Marker left where dropped history used to be. */ export declare const GEMINI_ELISION_NOTE = "[Earlier tool exchanges were removed to fit the context window.]"; /** True when this content carries tool results worth previewing. */ export declare function isGeminiToolResponseContent(content: GeminiGuardContent): boolean; /** Head/tail preview for an oversized tool response payload. */ export declare function previewGeminiToolResponseText(text: string): string; /** * Decide what to reclaim from a Gemini agent loop. * * Returns `undefined` when the history still fits, in which case the caller * must leave it byte-identical — any rewrite invalidates the provider's cached * prefix, so "no change" has to mean no change. * * `observedPromptTokens` must be a count for the payload ABOUT TO BE SENT — * every Gemini-shaped loop plans only when its `createContextGuard` trips, and * that guard's `projectedNextPromptTokens` is exactly that: the provider's real * count for the last request plus the growth measured since. Dividing it by * this module's estimate of the current history therefore compares two views of * one payload, which is what makes the correction meaningful. A count for an * EARLIER request must not be passed here: the loop has appended a model turn * and its tool turn since, so the denominator would always be the larger of the * two, the ratio would read below 1 and the `Math.max(1, …)` floor would pin * calibration at 1 — silently disabling the correction. `planAnthropicLoopReclaim` * carries `previousSentEstimate` for callers in that other position. */ export declare function planGeminiLoopReclaim(args: { contents: readonly GeminiGuardContent[]; availableInputTokens: number; fixedOverheadTokens?: number; provider?: string; observedPromptTokens?: number; }): LoopGuardPlan | undefined;