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

48 lines (47 loc) • 2.17 kB
/** * Default the tool cache boundary to the last tool, unless the caller chose one. * * Tool definitions sit between the system prompt and the conversation and * rarely change, so with no breakpoint closing that prefix the whole tools * block is re-billed as fresh input every turn. * * Call it after every tool mutation — including any appended `final_result` * tool — and before counting markers for the remaining history budget. * Explicit caller markers are preserved, including a non-last boundary. * Both generate and stream apply the same default. * * Pure — returns a new array. A tool that already carries a breakpoint wins. */ export const withLastToolCacheBreakpoint = (tools) => { if (!tools || tools.length === 0) { return tools; } // Read the ASSEMBLED wire field. An earlier version asked `cacheControlOf`, // which looks at `providerOptions.anthropic.cacheControl` — a shape these // tools no longer have by this point — so the check never fired and a // caller-marked tool got a second, redundant marker. if (tools.some((t) => t.cache_control !== undefined)) { return [...tools]; } const last = tools[tools.length - 1]; return [ ...tools.slice(0, -1), { ...last, cache_control: { type: "ephemeral" } }, ]; }; /** * Read an Anthropic cache breakpoint from a message/part/tool carrier that * still carries `providerOptions.anthropic.cacheControl` — i.e. BEFORE * conversion to the Anthropic wire shape. MessageBuilder marks system messages * that way. Tools are marked after conversion, by * `withLastToolCacheBreakpoint`, which reads the wire-shaped `cache_control` * instead; do not use this reader on an assembled tool. * * Extracted from anthropic/client.ts so `src/lib/core/nativeToolFormat.ts` * can share it without importing the provider client (which would create a * circular import: client.ts -> core/nativeToolFormat.ts -> client.ts). */ export const cacheControlOf = (carrier) => { const cc = carrier?.providerOptions?.anthropic?.cacheControl; return cc?.type === "ephemeral" ? { type: "ephemeral" } : undefined; };