2024-07-15 14:32:42 +02:00
|
|
|
import { ImagePart, TextPart, UserContent } from 'ai'
|
2024-06-11 10:51:02 +02:00
|
|
|
import ky, { HTTPError } from 'ky'
|
|
|
|
|
2024-07-15 14:32:42 +02:00
|
|
|
type Props = {
|
2024-06-11 10:51:02 +02:00
|
|
|
input: string
|
2024-07-15 14:32:42 +02:00
|
|
|
shouldDownloadImages: boolean
|
|
|
|
}
|
|
|
|
export const splitUserTextMessageIntoBlocks = async ({
|
|
|
|
input,
|
|
|
|
shouldDownloadImages,
|
|
|
|
}: Props): Promise<UserContent> => {
|
2024-07-30 17:08:01 +02:00
|
|
|
const urlRegex = /(^|\n\n)(https?:\/\/.+)(\n\n|$)/g
|
2024-06-11 10:51:02 +02:00
|
|
|
const match = input.match(urlRegex)
|
|
|
|
if (!match) return input
|
2024-07-15 14:32:42 +02:00
|
|
|
let parts: (TextPart | ImagePart)[] = []
|
2024-06-11 10:51:02 +02:00
|
|
|
let processedInput = input
|
|
|
|
|
|
|
|
for (const url of match) {
|
|
|
|
const textBeforeUrl = processedInput.slice(0, processedInput.indexOf(url))
|
|
|
|
if (textBeforeUrl.trim().length > 0) {
|
|
|
|
parts.push({ type: 'text', text: textBeforeUrl })
|
|
|
|
}
|
|
|
|
const cleanUrl = url.trim()
|
|
|
|
|
|
|
|
try {
|
|
|
|
const response = await ky.get(cleanUrl)
|
|
|
|
if (
|
|
|
|
!response.ok ||
|
|
|
|
!response.headers.get('content-type')?.startsWith('image/')
|
|
|
|
) {
|
|
|
|
parts.push({ type: 'text', text: cleanUrl })
|
|
|
|
} else {
|
|
|
|
parts.push({
|
2024-07-15 14:32:42 +02:00
|
|
|
type: 'image',
|
|
|
|
image: shouldDownloadImages
|
|
|
|
? await response.arrayBuffer()
|
|
|
|
: url.trim(),
|
2024-06-11 10:51:02 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
if (err instanceof HTTPError) {
|
|
|
|
console.log(err.response.status, await err.response.text())
|
|
|
|
} else {
|
|
|
|
console.error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
processedInput = processedInput.slice(
|
|
|
|
processedInput.indexOf(url) + url.length
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (processedInput.trim().length > 0) {
|
|
|
|
parts.push({ type: 'text', text: processedInput })
|
|
|
|
}
|
|
|
|
|
|
|
|
return parts
|
|
|
|
}
|