Spaces:
Running
Running
import type { Message } from 'ai'; | |
import { useCallback, useState } from 'react'; | |
import { StreamingMessageParser } from '~/lib/runtime/message-parser'; | |
import { workbenchStore } from '~/lib/stores/workbench'; | |
import { createScopedLogger } from '~/utils/logger'; | |
const logger = createScopedLogger('useMessageParser'); | |
const messageParser = new StreamingMessageParser({ | |
callbacks: { | |
onArtifactOpen: (data) => { | |
logger.trace('onArtifactOpen', data); | |
workbenchStore.showWorkbench.set(true); | |
workbenchStore.addArtifact(data); | |
}, | |
onArtifactClose: (data) => { | |
logger.trace('onArtifactClose'); | |
workbenchStore.updateArtifact(data, { closed: true }); | |
}, | |
onActionOpen: (data) => { | |
logger.trace('onActionOpen', data.action); | |
// we only add shell actions when when the close tag got parsed because only then we have the content | |
if (data.action.type === 'file') { | |
workbenchStore.addAction(data); | |
} | |
}, | |
onActionClose: (data) => { | |
logger.trace('onActionClose', data.action); | |
if (data.action.type !== 'file') { | |
workbenchStore.addAction(data); | |
} | |
workbenchStore.runAction(data); | |
}, | |
onActionStream: (data) => { | |
logger.trace('onActionStream', data.action); | |
workbenchStore.runAction(data, true); | |
}, | |
}, | |
}); | |
const extractTextContent = (message: Message) => | |
Array.isArray(message.content) | |
? (message.content.find((item) => item.type === 'text')?.text as string) || '' | |
: message.content; | |
export function useMessageParser() { | |
const [parsedMessages, setParsedMessages] = useState<{ [key: number]: string }>({}); | |
const parseMessages = useCallback((messages: Message[], isLoading: boolean) => { | |
let reset = false; | |
if (import.meta.env.DEV && !isLoading) { | |
reset = true; | |
messageParser.reset(); | |
} | |
for (const [index, message] of messages.entries()) { | |
if (message.role === 'assistant' || message.role === 'user') { | |
const newParsedContent = messageParser.parse(message.id, extractTextContent(message)); | |
setParsedMessages((prevParsed) => ({ | |
...prevParsed, | |
[index]: !reset ? (prevParsed[index] || '') + newParsedContent : newParsedContent, | |
})); | |
} | |
} | |
}, []); | |
return { parsedMessages, parseMessages }; | |
} | |