import { memo, Fragment } from 'react'; import { Markdown } from './Markdown'; import type { JSONValue } from 'ai'; import Popover from '~/components/ui/Popover'; import { workbenchStore } from '~/lib/stores/workbench'; import { WORK_DIR } from '~/utils/constants'; import WithTooltip from '~/components/ui/Tooltip'; import type { Message } from 'ai'; import type { ProviderInfo } from '~/types/model'; interface AssistantMessageProps { content: string; annotations?: JSONValue[]; messageId?: string; onRewind?: (messageId: string) => void; onFork?: (messageId: string) => void; append?: (message: Message) => void; chatMode?: 'discuss' | 'build'; setChatMode?: (mode: 'discuss' | 'build') => void; model?: string; provider?: ProviderInfo; } function openArtifactInWorkbench(filePath: string) { filePath = normalizedFilePath(filePath); if (workbenchStore.currentView.get() !== 'code') { workbenchStore.currentView.set('code'); } workbenchStore.setSelectedFile(`${WORK_DIR}/${filePath}`); } function normalizedFilePath(path: string) { let normalizedPath = path; if (normalizedPath.startsWith(WORK_DIR)) { normalizedPath = path.replace(WORK_DIR, ''); } if (normalizedPath.startsWith('/')) { normalizedPath = normalizedPath.slice(1); } return normalizedPath; } export const AssistantMessage = memo( ({ content, annotations, messageId, onRewind, onFork, append, chatMode, setChatMode, model, provider, }: AssistantMessageProps) => { const filteredAnnotations = (annotations?.filter( (annotation: JSONValue) => annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'), ) || []) as { type: string; value: any } & { [key: string]: any }[]; let chatSummary: string | undefined = undefined; if (filteredAnnotations.find((annotation) => annotation.type === 'chatSummary')) { chatSummary = filteredAnnotations.find((annotation) => annotation.type === 'chatSummary')?.summary; } let codeContext: string[] | undefined = undefined; if (filteredAnnotations.find((annotation) => annotation.type === 'codeContext')) { codeContext = filteredAnnotations.find((annotation) => annotation.type === 'codeContext')?.files; } const usage: { completionTokens: number; promptTokens: number; totalTokens: number; } = filteredAnnotations.find((annotation) => annotation.type === 'usage')?.value; return (
<>
{(codeContext || chatSummary) && ( }> {chatSummary && (

Summary

{chatSummary}
{codeContext && (

Context

{codeContext.map((x) => { const normalized = normalizedFilePath(x); return ( { e.preventDefault(); e.stopPropagation(); openArtifactInWorkbench(normalized); }} > {normalized} ); })}
)}
)}
)}
{usage && (
Tokens: {usage.totalTokens} (prompt: {usage.promptTokens}, completion: {usage.completionTokens})
)} {(onRewind || onFork) && messageId && (
{onRewind && (
)}
{content}
); }, );