( blocks: ContentBlock[], text: string, )
| 288 | * Similar to how appendTextToRootStream handles reasoning for root. |
| 289 | */ |
| 290 | const appendNativeReasoningToBlocks = ( |
| 291 | blocks: ContentBlock[], |
| 292 | text: string, |
| 293 | ): ContentBlock[] => { |
| 294 | if (!text) { |
| 295 | return blocks |
| 296 | } |
| 297 | |
| 298 | const nextBlocks = [...blocks] |
| 299 | const lastBlock = nextBlocks[nextBlocks.length - 1] |
| 300 | |
| 301 | // If last block is already an open native reasoning block, append to it |
| 302 | // Only append if it's a native reasoning block (thinkingOpen === undefined), |
| 303 | // not a closed one or a <think> tag block |
| 304 | if (isNativeReasoningBlock(lastBlock) && lastBlock.type === 'text') { |
| 305 | const updatedBlock: ContentBlock = { |
| 306 | ...lastBlock, |
| 307 | content: lastBlock.content + text, |
| 308 | } |
| 309 | nextBlocks[nextBlocks.length - 1] = updatedBlock |
| 310 | return nextBlocks |
| 311 | } |
| 312 | |
| 313 | // Create a new native reasoning block |
| 314 | const newBlock: ContentBlock = { |
| 315 | type: 'text', |
| 316 | content: text, |
| 317 | textType: 'reasoning', |
| 318 | thinkingCollapseState: 'preview', |
| 319 | thinkingId: generateThinkingId(), |
| 320 | } |
| 321 | |
| 322 | return [...nextBlocks, newBlock] |
| 323 | } |
| 324 | |
| 325 | /** |
| 326 | * Checks if a block is a native reasoning block (not from <think> tags). |
no test coverage detected