refactor(agents): dedupe config and truncation guards

This commit is contained in:
Peter Steinberger
2026-02-22 17:54:42 +00:00
parent 409a02691f
commit 3286791316
12 changed files with 325 additions and 318 deletions

View File

@@ -33,21 +33,32 @@ const TRUNCATION_SUFFIX =
"The content above is a partial view. If you need more, request specific sections or use " +
"offset/limit parameters to read smaller chunks.]";
type ToolResultTruncationOptions = {
suffix?: string;
minKeepChars?: number;
};
/**
* Truncate a single text string to fit within maxChars, preserving the beginning.
*/
export function truncateToolResultText(text: string, maxChars: number): string {
export function truncateToolResultText(
text: string,
maxChars: number,
options: ToolResultTruncationOptions = {},
): string {
const suffix = options.suffix ?? TRUNCATION_SUFFIX;
const minKeepChars = options.minKeepChars ?? MIN_KEEP_CHARS;
if (text.length <= maxChars) {
return text;
}
const keepChars = Math.max(MIN_KEEP_CHARS, maxChars - TRUNCATION_SUFFIX.length);
const keepChars = Math.max(minKeepChars, maxChars - suffix.length);
// Try to break at a newline boundary to avoid cutting mid-line
let cutPoint = keepChars;
const lastNewline = text.lastIndexOf("\n", keepChars);
if (lastNewline > keepChars * 0.8) {
cutPoint = lastNewline;
}
return text.slice(0, cutPoint) + TRUNCATION_SUFFIX;
return text.slice(0, cutPoint) + suffix;
}
/**
@@ -67,7 +78,7 @@ export function calculateMaxToolResultChars(contextWindowTokens: number): number
/**
* Get the total character count of text content blocks in a tool result message.
*/
function getToolResultTextLength(msg: AgentMessage): number {
export function getToolResultTextLength(msg: AgentMessage): number {
if (!msg || (msg as { role?: string }).role !== "toolResult") {
return 0;
}
@@ -91,7 +102,13 @@ function getToolResultTextLength(msg: AgentMessage): number {
* Truncate a tool result message's text content blocks to fit within maxChars.
* Returns a new message (does not mutate the original).
*/
function truncateToolResultMessage(msg: AgentMessage, maxChars: number): AgentMessage {
export function truncateToolResultMessage(
msg: AgentMessage,
maxChars: number,
options: ToolResultTruncationOptions = {},
): AgentMessage {
const suffix = options.suffix ?? TRUNCATION_SUFFIX;
const minKeepChars = options.minKeepChars ?? MIN_KEEP_CHARS;
const content = (msg as { content?: unknown }).content;
if (!Array.isArray(content)) {
return msg;
@@ -114,10 +131,10 @@ function truncateToolResultMessage(msg: AgentMessage, maxChars: number): AgentMe
}
// Proportional budget for this block
const blockShare = textBlock.text.length / totalTextChars;
const blockBudget = Math.max(MIN_KEEP_CHARS, Math.floor(maxChars * blockShare));
const blockBudget = Math.max(minKeepChars + suffix.length, Math.floor(maxChars * blockShare));
return {
...textBlock,
text: truncateToolResultText(textBlock.text, blockBudget),
text: truncateToolResultText(textBlock.text, blockBudget, { suffix, minKeepChars }),
};
});