UNPKG

@juspay/neurolink

Version:

Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applicatio

79 lines 3.41 kB
/** * Tool output preview generation. * Generates head/tail previews of large tool outputs for context-efficient LLM calls. * @module */ /** Default maximum preview size in bytes (50KB) */ export const DEFAULT_MAX_PREVIEW_BYTES = 50 * 1024; /** Default maximum preview lines */ export const DEFAULT_MAX_PREVIEW_LINES = 2_000; /** Default head ratio (25% of preview budget) */ export const DEFAULT_HEAD_RATIO = 0.25; /** Tool name referenced in truncation notices for on-demand full-output access */ export const RETRIEVE_CONTEXT_TOOL_NAME = "retrieve_context"; /** Default tail ratio (75% of preview budget) */ export const DEFAULT_TAIL_RATIO = 0.75; /** * Generate a head/tail preview of a tool output string. * If the output is within limits, returns it unchanged with truncated: false. * If over limits, keeps the first 25% and last 75% with an omission notice. * * Industry pattern: 25/75 head/tail split. Head captures schema/headers/structure, * tail captures the most recent and typically most relevant data. */ export function generateToolOutputPreview(output, options) { const maxBytes = options?.maxBytes ?? DEFAULT_MAX_PREVIEW_BYTES; const maxLines = options?.maxLines ?? DEFAULT_MAX_PREVIEW_LINES; const rawHeadRatio = options?.headRatio ?? DEFAULT_HEAD_RATIO; const rawTailRatio = options?.tailRatio ?? DEFAULT_TAIL_RATIO; // Clamp ratios to valid range to avoid negative omittedBytes const headRatio = Math.max(0, Math.min(1, rawHeadRatio)); const tailRatio = Math.max(0, Math.min(1, rawTailRatio)); const originalSize = Buffer.byteLength(output, "utf-8"); const lines = output.split("\n"); const exceedsBytes = originalSize > maxBytes; const exceedsLines = lines.length > maxLines; if (!exceedsBytes && !exceedsLines) { return { preview: output, truncated: false, originalSize }; } // Line-based split const headLineCount = Math.max(1, Math.floor(maxLines * headRatio)); const tailLineCount = Math.max(1, maxLines - headLineCount); let head; let tail; if (exceedsLines) { head = lines.slice(0, headLineCount).join("\n"); tail = lines.slice(-tailLineCount).join("\n"); } else { head = lines .slice(0, Math.max(1, Math.floor(lines.length * headRatio))) .join("\n"); tail = lines .slice(-Math.max(1, Math.ceil(lines.length * tailRatio))) .join("\n"); } // Byte-based cap on each portion const headMaxBytes = Math.floor(maxBytes * headRatio); const tailMaxBytes = maxBytes - headMaxBytes; if (Buffer.byteLength(head, "utf-8") > headMaxBytes) { head = Buffer.from(head, "utf-8") .subarray(0, headMaxBytes) .toString("utf-8"); } if (Buffer.byteLength(tail, "utf-8") > tailMaxBytes) { const tailBuf = Buffer.from(tail, "utf-8"); tail = tailBuf.subarray(tailBuf.length - tailMaxBytes).toString("utf-8"); } const omittedBytes = Math.max(0, originalSize - Buffer.byteLength(head, "utf-8") - Buffer.byteLength(tail, "utf-8")); const notice = `\n\n[... ${omittedBytes} bytes omitted. ` + `Use ${RETRIEVE_CONTEXT_TOOL_NAME} tool to access full output ...]\n\n`; return { preview: head + notice + tail, truncated: true, originalSize, }; } //# sourceMappingURL=toolOutputLimits.js.map