/** * @license * Copyright 2025 Vybestack LLC * SPDX-License-Identifier: Apache-2.0 */ /** * @plan PLAN-20260211-COMPRESSION.P04 * @requirement REQ-CS-004.1, REQ-CS-004.2, REQ-CS-004.3, REQ-CS-004.4 * * Shared utility functions for adjusting compression/truncation boundaries * to avoid splitting tool call/response pairs in conversation history. * * Extracted from GeminiChat as pure standalone functions with no class or * logging dependencies. */ import type { ContentBlock, IContent } from '../../services/history/IContent.js'; /** * Aggregate text from content blocks, handling spacing between text and * non-text blocks. Used by LLM-based compression strategies to collect * streamed response text. */ export declare function aggregateTextFromBlocks(blocks: ContentBlock[], currentText: string, lastBlockWasNonText: boolean): { text: string; lastBlockWasNonText: boolean; }; /** * Adjust compression boundary to not split tool call/response pairs. * Searches for a valid split point that doesn't break tool call/response * pairs. If the initial index lands inside a tool response sequence, it * first tries moving forward, then searches backward for a valid boundary. */ export declare function adjustForToolCallBoundary(history: IContent[], index: number): number; /** * Search forward from the given index to find a valid split point that * doesn't land in the middle of a tool response sequence. If, after * skipping tool responses, the preceding AI message has tool calls * whose responses are not in the kept portion, backs up by one to * include the AI message in the removed portion. */ export declare function findForwardValidSplitPoint(history: IContent[], index: number): number; /** * Search backward from the given start index to find a valid split point. * Skips tool response messages and AI messages whose tool calls don't * have matching responses in the remaining history. Returns the first * valid boundary found, or startIndex if none is found. */ export declare function findBackwardValidSplitPoint(history: IContent[], startIndex: number): number; /** * Build a context-aware continuation directive to replace the static * compression acknowledgment. When active todos exist the directive * references the first task and points the model at todo_read for * full recovery; otherwise it emits a simple "continue" statement. */ export declare function buildContinuationDirective(activeTodos?: string): string; /** * Convert tool_call and tool_response blocks to plain text representations * so the compression request doesn't trip Anthropic's strict tool_use / * tool_result pairing validation. Orphaned tool blocks (from interrupted * loops or the loop-detector halting mid-tool-call) would otherwise cause * 400 errors when sent to the LLM for summarisation. * * Messages whose speaker is 'tool' are re-tagged as 'human' since they * no longer carry structural tool_result blocks. All other block types * (text, thinking, code, media) pass through unchanged. */ export declare function sanitizeHistoryForCompression(messages: readonly IContent[]): IContent[];