(messages: Message[])
| 5064 | * the API rejects them with a 400. |
| 5065 | */ |
| 5066 | export function stripSignatureBlocks(messages: Message[]): Message[] { |
| 5067 | let changed = false |
| 5068 | const result = messages.map(msg => { |
| 5069 | if (msg.type !== 'assistant') return msg |
| 5070 | |
| 5071 | const content = msg.message.content |
| 5072 | if (!Array.isArray(content)) return msg |
| 5073 | |
| 5074 | const filtered = content.filter(block => { |
| 5075 | if (isThinkingBlock(block)) return false |
| 5076 | if (feature('CONNECTOR_TEXT')) { |
| 5077 | if (isConnectorTextBlock(block)) return false |
| 5078 | } |
| 5079 | return true |
| 5080 | }) |
| 5081 | if (filtered.length === content.length) return msg |
| 5082 | |
| 5083 | // Strip to [] even for thinking-only messages. Streaming yields each |
| 5084 | // content block as a separate same-id AssistantMessage (claude.ts:2150), |
| 5085 | // so a thinking-only singleton here is usually a split sibling that |
| 5086 | // mergeAssistantMessages (2232) rejoins with its text/tool_use partner. |
| 5087 | // If we returned the original message, the stale signature would survive |
| 5088 | // the merge. Empty content is absorbed by merge; true orphans are handled |
| 5089 | // by the empty-content placeholder path in normalizeMessagesForAPI. |
| 5090 | |
| 5091 | changed = true |
| 5092 | return { |
| 5093 | ...msg, |
| 5094 | message: { ...msg.message, content: filtered }, |
| 5095 | } as typeof msg |
| 5096 | }) |
| 5097 | |
| 5098 | return changed ? result : messages |
| 5099 | } |
| 5100 | |
| 5101 | /** |
| 5102 | * Creates a tool use summary message for SDK emission. |
no test coverage detected