(content: unknown)
| 12 | export type ContentBlock = ContentTextBlock | { type: string; [key: string]: unknown }; |
| 13 | |
| 14 | export function contentToString(content: unknown): string { |
| 15 | if (typeof content === 'string') return content; |
| 16 | if (content == null) return ''; |
| 17 | if (Array.isArray(content)) { |
| 18 | return content |
| 19 | .map((b) => { |
| 20 | if (typeof b === 'string') return b; |
| 21 | const block = b as { type?: string; text?: unknown }; |
| 22 | // OpenAI blocks carry type:'text'; Gemini-lineage agents (Qwen Code, |
| 23 | // AionUI) send part-style `{ text }` with no type at all — accept any |
| 24 | // block whose `text` is a string and whose type doesn't say it's |
| 25 | // something else. (#200) |
| 26 | if (typeof block?.text === 'string' && (block.type === 'text' || block.type === undefined)) { |
| 27 | return block.text; |
| 28 | } |
| 29 | return ''; |
| 30 | }) |
| 31 | .join(''); |
| 32 | } |
| 33 | return ''; |
| 34 | } |
| 35 | |
| 36 | export function flattenMessageContent(messages: ChatMessage[]): ChatMessage[] { |
| 37 | return messages.map((m) => ({ |
no outgoing calls
no test coverage detected