Merge branch 'main' into docs/label-api-reference
This commit is contained in:
commit
5b64ddbe73
@ -7,7 +7,10 @@ import SimpleTextMessage from '../SimpleTextMessage'
|
||||
type Ref = HTMLDivElement
|
||||
|
||||
const ChatItem = forwardRef<Ref, ThreadMessage>((message, ref) => (
|
||||
<div ref={ref} className="py-4 even:bg-secondary dark:even:bg-secondary/20">
|
||||
<div
|
||||
ref={ref}
|
||||
className="relative py-4 first:pb-14 even:bg-secondary dark:even:bg-secondary/20"
|
||||
>
|
||||
<SimpleTextMessage {...message} />
|
||||
</div>
|
||||
))
|
||||
|
||||
@ -35,63 +35,69 @@ const MessageToolbar = ({ message }: { message: ThreadMessage }) => {
|
||||
}
|
||||
return (
|
||||
<div className="flex flex-row items-center">
|
||||
{message.status === MessageStatus.Pending && (
|
||||
<StopCircle
|
||||
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
|
||||
size={20}
|
||||
onClick={() => stopInference()}
|
||||
/>
|
||||
)}
|
||||
{message.status !== MessageStatus.Pending &&
|
||||
message.id === messages[0]?.id && (
|
||||
<RefreshCcw
|
||||
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
|
||||
size={20}
|
||||
onClick={() => {
|
||||
const messageRequest: MessageRequest = {
|
||||
id: message.id ?? '',
|
||||
messages: messages
|
||||
.slice(1, messages.length)
|
||||
.reverse()
|
||||
.map((e) => {
|
||||
return {
|
||||
content: e.content,
|
||||
role: e.role,
|
||||
} as ChatCompletionMessage
|
||||
}),
|
||||
threadId: message.threadId ?? '',
|
||||
}
|
||||
if (message.role === ChatCompletionRole.Assistant) {
|
||||
deleteAMessage(message.id ?? '')
|
||||
}
|
||||
events.emit(EventName.OnNewMessageRequest, messageRequest)
|
||||
}}
|
||||
/>
|
||||
<div className="flex overflow-hidden rounded-md border border-border bg-background/20">
|
||||
{message.status === MessageStatus.Pending && (
|
||||
<div
|
||||
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
|
||||
onClick={() => stopInference()}
|
||||
>
|
||||
<StopCircle size={14} />
|
||||
</div>
|
||||
)}
|
||||
<ClipboardCopy
|
||||
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
|
||||
size={20}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(message.content ?? '')
|
||||
toaster({
|
||||
title: 'Copied to clipboard',
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Trash2Icon
|
||||
className="mx-1 cursor-pointer rounded-sm bg-gray-800 px-[3px]"
|
||||
size={20}
|
||||
onClick={async () => {
|
||||
deleteAMessage(message.id ?? '')
|
||||
if (thread)
|
||||
await pluginManager
|
||||
.get<ConversationalPlugin>(PluginType.Conversational)
|
||||
?.saveConversation({
|
||||
...thread,
|
||||
messages: messages.filter((e) => e.id !== message.id),
|
||||
})
|
||||
}}
|
||||
/>
|
||||
{message.status !== MessageStatus.Pending &&
|
||||
message.id === messages[0]?.id && (
|
||||
<div
|
||||
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
|
||||
onClick={() => {
|
||||
const messageRequest: MessageRequest = {
|
||||
id: message.id ?? '',
|
||||
messages: messages
|
||||
.slice(1, messages.length)
|
||||
.reverse()
|
||||
.map((e) => {
|
||||
return {
|
||||
content: e.content,
|
||||
role: e.role,
|
||||
} as ChatCompletionMessage
|
||||
}),
|
||||
threadId: message.threadId ?? '',
|
||||
}
|
||||
if (message.role === ChatCompletionRole.Assistant) {
|
||||
deleteAMessage(message.id ?? '')
|
||||
}
|
||||
events.emit(EventName.OnNewMessageRequest, messageRequest)
|
||||
}}
|
||||
>
|
||||
<RefreshCcw size={14} />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className="cursor-pointer border-r border-border px-2 py-2 hover:bg-background/80"
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(message.content ?? '')
|
||||
toaster({
|
||||
title: 'Copied to clipboard',
|
||||
})
|
||||
}}
|
||||
>
|
||||
<ClipboardCopy size={14} />
|
||||
</div>
|
||||
<div
|
||||
className="cursor-pointer px-2 py-2 hover:bg-background/80"
|
||||
onClick={async () => {
|
||||
deleteAMessage(message.id ?? '')
|
||||
if (thread)
|
||||
await pluginManager
|
||||
.get<ConversationalPlugin>(PluginType.Conversational)
|
||||
?.saveConversation({
|
||||
...thread,
|
||||
messages: messages.filter((e) => e.id !== message.id),
|
||||
})
|
||||
}}
|
||||
>
|
||||
<Trash2Icon size={14} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ import { ChatCompletionRole, MessageStatus, ThreadMessage } from '@janhq/core'
|
||||
|
||||
import hljs from 'highlight.js'
|
||||
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { Marked } from 'marked'
|
||||
|
||||
import { markedHighlight } from 'marked-highlight'
|
||||
@ -21,6 +22,8 @@ import { displayDate } from '@/utils/datetime'
|
||||
|
||||
import MessageToolbar from '../MessageToolbar'
|
||||
|
||||
import { getCurrentChatMessagesAtom } from '@/helpers/atoms/ChatMessage.atom'
|
||||
|
||||
const marked = new Marked(
|
||||
markedHighlight({
|
||||
langPrefix: 'hljs',
|
||||
@ -55,6 +58,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
|
||||
|
||||
const [lastTimestamp, setLastTimestamp] = useState<number | undefined>()
|
||||
const [tokenSpeed, setTokenSpeed] = useState(0)
|
||||
const messages = useAtomValue(getCurrentChatMessagesAtom)
|
||||
|
||||
useEffect(() => {
|
||||
if (props.status === MessageStatus.Ready || !experimentalFeatureEnabed) {
|
||||
@ -73,22 +77,29 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
|
||||
|
||||
setTokenSpeed(averageTokenSpeed)
|
||||
setTokenCount(totalTokenCount)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [props.content])
|
||||
|
||||
return (
|
||||
<div className="group mx-auto rounded-xl px-4 lg:w-3/4">
|
||||
<div className="group relative mx-auto rounded-xl px-4 lg:w-3/4">
|
||||
<div
|
||||
className={twMerge(
|
||||
'mb-1 flex items-center justify-start gap-2',
|
||||
'mb-2 flex items-center justify-start gap-x-2',
|
||||
!isUser && 'mt-2'
|
||||
)}
|
||||
>
|
||||
{!isUser && !isSystem && <LogoMark width={20} />}
|
||||
<div className="text-sm font-extrabold capitalize">{props.role}</div>
|
||||
<p className="text-xs font-medium">{displayDate(props.createdAt)}</p>
|
||||
|
||||
{experimentalFeatureEnabed && (
|
||||
<div className="hidden cursor-pointer group-hover:flex">
|
||||
<div
|
||||
className={twMerge(
|
||||
'absolute right-0 cursor-pointer transition-all',
|
||||
messages[0].id === props.id
|
||||
? 'absolute -bottom-10 left-4'
|
||||
: 'hidden group-hover:flex'
|
||||
)}
|
||||
>
|
||||
<MessageToolbar message={props} />
|
||||
</div>
|
||||
)}
|
||||
@ -113,7 +124,7 @@ const SimpleTextMessage: React.FC<ThreadMessage> = (props) => {
|
||||
</div>
|
||||
{experimentalFeatureEnabed &&
|
||||
(props.status === MessageStatus.Pending || tokenSpeed > 0) && (
|
||||
<p className="mt-1 text-xs font-medium text-white">
|
||||
<p className="mt-2 text-xs font-medium text-foreground">
|
||||
Token Speed: {Number(tokenSpeed).toFixed(2)}/s
|
||||
</p>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user