( messages: Message[], )
| 4995 | messages: Message[], |
| 4996 | ): Message[] |
| 4997 | export function filterOrphanedThinkingOnlyMessages( |
| 4998 | messages: Message[], |
| 4999 | ): Message[] { |
| 5000 | // First pass: collect message.ids that have non-thinking content |
| 5001 | // These will be merged later in normalizeMessagesForAPI() |
| 5002 | const messageIdsWithNonThinkingContent = new Set<string>() |
| 5003 | for (const msg of messages) { |
| 5004 | if (msg.type !== 'assistant') continue |
| 5005 | |
| 5006 | const content = msg.message.content |
| 5007 | if (!Array.isArray(content)) continue |
| 5008 | |
| 5009 | const hasNonThinking = content.some( |
| 5010 | block => block.type !== 'thinking' && block.type !== 'redacted_thinking', |
| 5011 | ) |
| 5012 | if (hasNonThinking && msg.message.id) { |
| 5013 | messageIdsWithNonThinkingContent.add(msg.message.id) |
| 5014 | } |
| 5015 | } |
| 5016 | |
| 5017 | // Second pass: filter out thinking-only messages that are truly orphaned |
| 5018 | const filtered = messages.filter(msg => { |
| 5019 | if (msg.type !== 'assistant') { |
| 5020 | return true |
| 5021 | } |
| 5022 | |
| 5023 | const content = msg.message.content |
| 5024 | if (!Array.isArray(content) || content.length === 0) { |
| 5025 | return true |
| 5026 | } |
| 5027 | |
| 5028 | // Check if ALL content blocks are thinking blocks |
| 5029 | const allThinking = content.every( |
| 5030 | block => block.type === 'thinking' || block.type === 'redacted_thinking', |
| 5031 | ) |
| 5032 | |
| 5033 | if (!allThinking) { |
| 5034 | return true // Has non-thinking content, keep it |
| 5035 | } |
| 5036 | |
| 5037 | // It's thinking-only. Keep it if there's another message with same id |
| 5038 | // that has non-thinking content (they'll be merged later) |
| 5039 | if ( |
| 5040 | msg.message.id && |
| 5041 | messageIdsWithNonThinkingContent.has(msg.message.id) |
| 5042 | ) { |
| 5043 | return true |
| 5044 | } |
| 5045 | |
| 5046 | // Truly orphaned - no other message with same id has content to merge with |
| 5047 | logEvent('tengu_filtered_orphaned_thinking_message', { |
| 5048 | messageUUID: |
| 5049 | msg.uuid as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 5050 | messageId: msg.message |
| 5051 | .id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS, |
| 5052 | blockCount: content.length, |
| 5053 | }) |
| 5054 | return false |
no test coverage detected