@@ -261,8 +261,8 @@ export function getToolResultTextLength(msg: AgentMessage): number {
|
261 | 261 | } |
262 | 262 | let totalLength = 0; |
263 | 263 | for (const block of content) { |
264 | | -if (block && typeof block === "object" && (block as { type?: string }).type === "text") { |
265 | | -const text = (block as TextContent).text; |
| 264 | +if (isToolResultTextBlock(block)) { |
| 265 | +const text = block.text; |
266 | 266 | if (typeof text === "string") { |
267 | 267 | totalLength += text.length; |
268 | 268 | } |
@@ -299,10 +299,10 @@ export function truncateToolResultMessage(
|
299 | 299 | |
300 | 300 | // Distribute the budget proportionally among text blocks |
301 | 301 | const newContent = content.map((block: unknown) => { |
302 | | -if (!block || typeof block !== "object" || (block as { type?: string }).type !== "text") { |
| 302 | +if (!isToolResultTextBlock(block)) { |
303 | 303 | return block; // Keep non-text blocks (images) as-is |
304 | 304 | } |
305 | | -const textBlock = block as TextContent; |
| 305 | +const textBlock = block; |
306 | 306 | if (typeof textBlock.text !== "string") { |
307 | 307 | return block; |
308 | 308 | } |
@@ -316,17 +316,33 @@ export function truncateToolResultMessage(
|
316 | 316 | 1, |
317 | 317 | Math.min(maxChars, Math.max(minKeepChars + defaultSuffix.length, proportionalBudget)), |
318 | 318 | ); |
319 | | -return Object.assign({}, textBlock, { |
320 | | -text: truncateToolResultText(textBlock.text, blockBudget, { |
321 | | -suffix: suffixFactory, |
322 | | - minKeepChars, |
323 | | -}), |
| 319 | +const truncatedText = truncateToolResultText(textBlock.text, blockBudget, { |
| 320 | +suffix: suffixFactory, |
| 321 | + minKeepChars, |
324 | 322 | }); |
| 323 | +const nextBlock = Object.assign({}, textBlock, { text: truncatedText }); |
| 324 | +if (typeof textBlock.content === "string") { |
| 325 | +nextBlock.content = truncatedText; |
| 326 | +} |
| 327 | +return nextBlock; |
325 | 328 | }); |
326 | 329 | |
327 | 330 | return { ...msg, content: newContent } as AgentMessage; |
328 | 331 | } |
329 | 332 | |
| 333 | +function isToolResultTextBlock( |
| 334 | +block: unknown, |
| 335 | +): block is TextContent & { content?: unknown; type: "text" | "toolResult" } { |
| 336 | +if (!block || typeof block !== "object") { |
| 337 | +return false; |
| 338 | +} |
| 339 | +const type = (block as { type?: unknown }).type; |
| 340 | +return ( |
| 341 | +(type === "text" || type === "toolResult") && |
| 342 | +typeof (block as { text?: unknown }).text === "string" |
| 343 | +); |
| 344 | +} |
| 345 | + |
330 | 346 | /** |
331 | 347 | * Truncate oversized tool results in an array of messages (in-memory). |
332 | 348 | * Returns a new array with truncated messages. |
|