( prompt: string | undefined, params: Record<string, any> | undefined, content?: Array<TextPart | ImagePart>, )
| 39 | * If you need a specific text part wrapped, put it first or pre-wrap it yourself before calling. |
| 40 | */ |
| 41 | export function buildUserMessageContent( |
| 42 | prompt: string | undefined, |
| 43 | params: Record<string, any> | undefined, |
| 44 | content?: Array<TextPart | ImagePart>, |
| 45 | ): Array<TextPart | ImagePart> { |
| 46 | const promptHasNonWhitespaceText = (prompt ?? '').trim().length > 0 |
| 47 | |
| 48 | // If we have content array (e.g., text + images) |
| 49 | if (content && content.length > 0) { |
| 50 | // Check if content has a non-empty text part |
| 51 | const firstTextPart = content.find((p): p is TextPart => p.type === 'text') |
| 52 | const hasNonEmptyText = firstTextPart && firstTextPart.text.trim() |
| 53 | |
| 54 | // If content has no meaningful text but prompt is provided, prepend prompt |
| 55 | if (!hasNonEmptyText && promptHasNonWhitespaceText) { |
| 56 | const nonTextContent = content.filter((p) => p.type !== 'text') |
| 57 | return [ |
| 58 | { type: 'text' as const, text: asUserMessage(prompt!) }, |
| 59 | ...nonTextContent, |
| 60 | ] |
| 61 | } |
| 62 | |
| 63 | // Find the first text part and wrap it in <user_message> tags |
| 64 | let hasWrappedText = false |
| 65 | const wrappedContent = content.map((part) => { |
| 66 | if (part.type === 'text' && !hasWrappedText) { |
| 67 | hasWrappedText = true |
| 68 | // Check if already wrapped |
| 69 | const alreadyWrapped = parseUserMessage(part.text) !== undefined |
| 70 | if (alreadyWrapped) { |
| 71 | return part |
| 72 | } |
| 73 | return { |
| 74 | type: 'text' as const, |
| 75 | text: asUserMessage(part.text), |
| 76 | } |
| 77 | } |
| 78 | return part |
| 79 | }) |
| 80 | return wrappedContent |
| 81 | } |
| 82 | |
| 83 | // Only prompt/params, combine and return as simple text |
| 84 | const textParts = buildArray([ |
| 85 | promptHasNonWhitespaceText ? prompt : undefined, |
| 86 | params && JSON.stringify(params, null, 2), |
| 87 | ]) |
| 88 | return [ |
| 89 | { |
| 90 | type: 'text', |
| 91 | text: asUserMessage(textParts.join('\n\n')), |
| 92 | }, |
| 93 | ] |
| 94 | } |
| 95 | |
| 96 | export function parseUserMessage(str: string): string | undefined { |
| 97 | const match = str.match(/<user_message>(.*?)<\/user_message>/s) |
no test coverage detected