CoolFace
Apppublic

legends810/testingnew

sourceHugging Faceupdated 1y agoView on Hugging Face
0likes
AssistantMessage.tsx121 linesDownload Raw Back to chat
1import { memo } from 'react';2import { Markdown } from './Markdown';3import type { JSONValue } from 'ai';4import Popover from '~/components/ui/Popover';5import { workbenchStore } from '~/lib/stores/workbench';6import { WORK_DIR } from '~/utils/constants';7 8interface AssistantMessageProps {9  content: string;10  annotations?: JSONValue[];11}12 13function openArtifactInWorkbench(filePath: string) {14  filePath = normalizedFilePath(filePath);15 16  if (workbenchStore.currentView.get() !== 'code') {17    workbenchStore.currentView.set('code');18  }19 20  workbenchStore.setSelectedFile(`${WORK_DIR}/${filePath}`);21}22 23function normalizedFilePath(path: string) {24  let normalizedPath = path;25 26  if (normalizedPath.startsWith(WORK_DIR)) {27    normalizedPath = path.replace(WORK_DIR, '');28  }29 30  if (normalizedPath.startsWith('/')) {31    normalizedPath = normalizedPath.slice(1);32  }33 34  return normalizedPath;35}36 37export const AssistantMessage = memo(({ content, annotations }: AssistantMessageProps) => {38  const filteredAnnotations = (annotations?.filter(39    (annotation: JSONValue) => annotation && typeof annotation === 'object' && Object.keys(annotation).includes('type'),40  ) || []) as { type: string; value: any } & { [key: string]: any }[];41 42  let chatSummary: string | undefined = undefined;43 44  if (filteredAnnotations.find((annotation) => annotation.type === 'chatSummary')) {45    chatSummary = filteredAnnotations.find((annotation) => annotation.type === 'chatSummary')?.summary;46  }47 48  let codeContext: string[] | undefined = undefined;49 50  if (filteredAnnotations.find((annotation) => annotation.type === 'codeContext')) {51    codeContext = filteredAnnotations.find((annotation) => annotation.type === 'codeContext')?.files;52  }53 54  const usage: {55    completionTokens: number;56    promptTokens: number;57    totalTokens: number;58    isCacheHit?: boolean;59    isCacheMiss?: boolean;60  } = filteredAnnotations.find((annotation) => annotation.type === 'usage')?.value ?? undefined;61 62  const cacheHitMsg = usage?.isCacheHit ? ' [Cache Hit]' : '';63  const cacheMissMsg = usage?.isCacheMiss ? ' [Cache Miss]' : '';64 65  return (66    <div className="overflow-hidden w-full">67      <>68        <div className=" flex gap-2 items-center text-sm text-bolt-elements-textSecondary mb-2">69          {(codeContext || chatSummary) && (70            <Popover side="right" align="start" trigger={<div className="i-ph:info" />}>71              {chatSummary && (72                <div className="max-w-chat">73                  <div className="summary max-h-96 flex flex-col">74                    <h2 className="border border-bolt-elements-borderColor rounded-md p4">Summary</h2>75                    <div style={{ zoom: 0.7 }} className="overflow-y-auto m4">76                      <Markdown>{chatSummary}</Markdown>77                    </div>78                  </div>79                  {codeContext && (80                    <div className="code-context flex flex-col p4 border border-bolt-elements-borderColor rounded-md">81                      <h2>Context</h2>82                      <div className="flex gap-4 mt-4 bolt" style={{ zoom: 0.6 }}>83                        {codeContext.map((x) => {84                          const normalized = normalizedFilePath(x);85                          return (86                            <>87                              <code88                                className="bg-bolt-elements-artifacts-inlineCode-background text-bolt-elements-artifacts-inlineCode-text px-1.5 py-1 rounded-md text-bolt-elements-item-contentAccent hover:underline cursor-pointer"89                                onClick={(e) => {90                                  e.preventDefault();91                                  e.stopPropagation();92                                  openArtifactInWorkbench(normalized);93                                }}94                              >95                                {normalized}96                              </code>97                            </>98                          );99                        })}100                      </div>101                    </div>102                  )}103                </div>104              )}105              <div className="context"></div>106            </Popover>107          )}108          {usage && (109            <div className="text-sm text-bolt-elements-textSecondary mb-2">110              Tokens: {usage.totalTokens} (prompt: {usage.promptTokens}, completion: {usage.completionTokens})111              <span className="text-sm text-green-500 ml-1">{cacheHitMsg}</span>112              <span className="text-sm text-red-500 ml-1">{cacheMissMsg}</span>113            </div>114          )}115        </div>116      </>117      <Markdown html>{content}</Markdown>118    </div>119  );120});121