Skip to content

Commit

Permalink
fix(janhq#591): prevent duplicate message id issue (janhq#595)
Browse files Browse the repository at this point in the history
Signed-off-by: James <[email protected]>
Co-authored-by: James <[email protected]>
namchuai and James authored Nov 14, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 52b96e6 commit 1fc9c4e
Showing 15 changed files with 53 additions and 53 deletions.
6 changes: 4 additions & 2 deletions plugins/inference-plugin/package.json
Original file line number Diff line number Diff line change
@@ -22,7 +22,8 @@
"postinstall": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:linux-cpu && npm run downloadnitro:linux-cuda && npm run downloadnitro:mac-arm64 && npm run downloadnitro:mac-x64 && rimraf dist/nitro/* && cpx \"nitro/**\" \"dist/nitro\"",
"postinstall:dev": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:mac-arm64 && npm run downloadnitro:mac-x64 && rimraf dist/nitro/* && cpx \"nitro/**\" \"dist/nitro\"",
"postinstall:windows": "rimraf *.tgz --glob && npm run build && npm run downloadnitro:win-cpu && npm run downloadnitro:win-cuda && rimraf dist/nitro/* && cpx \"nitro/**\" \"dist/nitro\"",
"build:publish": "npm pack && cpx *.tgz ../../electron/core/pre-install"
"build:publish": "npm pack && cpx *.tgz ../../electron/core/pre-install",
"build:debug": "rimraf *.tgz --glob && npm run build && npm pack && cpx *.tgz ../../electron/core/pre-install"
},
"exports": {
".": "./dist/index.js",
@@ -40,7 +41,8 @@
"kill-port": "^2.0.1",
"rxjs": "^7.8.1",
"tcp-port-used": "^1.0.2",
"ts-loader": "^9.5.0"
"ts-loader": "^9.5.0",
"ulid": "^2.3.0"
},
"engines": {
"node": ">=18.0.0"
3 changes: 0 additions & 3 deletions plugins/inference-plugin/src/helpers/message.ts

This file was deleted.

6 changes: 3 additions & 3 deletions plugins/inference-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ import {
} from "@janhq/core";
import { InferencePlugin } from "@janhq/core/lib/plugins";
import { requestInference } from "./helpers/sse";
import { generateMessageId } from "./helpers/message";
import { ulid } from "ulid";

/**
* A class that implements the InferencePlugin interface from the @janhq/core package.
@@ -112,13 +112,13 @@ export default class JanInferencePlugin implements InferencePlugin {
content: data.message,
},
];
const recentMessages = await (data.history ?? prompts);
const recentMessages = data.history ?? prompts;
const message = {
...data,
message: "",
user: "assistant",
createdAt: new Date().toISOString(),
_id: generateMessageId(),
_id: ulid(),
};
events.emit(EventName.OnNewMessageResponse, message);

3 changes: 2 additions & 1 deletion plugins/model-plugin/package.json
Original file line number Diff line number Diff line change
@@ -15,7 +15,8 @@
"scripts": {
"build": "tsc -b . && webpack --config webpack.config.js",
"postinstall": "rimraf *.tgz --glob && npm run build",
"build:publish": "npm pack && cpx *.tgz ../../electron/core/pre-install"
"build:publish": "npm pack && cpx *.tgz ../../electron/core/pre-install",
"build:debug": "rimraf *.tgz --glob && npm run build && npm pack && cpx *.tgz ../../electron/core/pre-install"
},
"devDependencies": {
"cpx": "^1.5.0",
1 change: 1 addition & 0 deletions web/containers/Providers/EventHandler.tsx
Original file line number Diff line number Diff line change
@@ -24,6 +24,7 @@ import {
import { downloadingModelsAtom } from '@/helpers/atoms/Model.atom'
import { MessageStatus, toChatMessage } from '@/models/ChatMessage'
import { pluginManager } from '@/plugin'
import { ChatMessage, Conversation } from '@/types/chatMessage'

let currentConversation: Conversation | undefined = undefined

2 changes: 1 addition & 1 deletion web/helpers/atoms/ChatMessage.atom.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@ import { atom } from 'jotai'

import { getActiveConvoIdAtom } from './Conversation.atom'

import { MessageStatus } from '@/models/ChatMessage'
import { ChatMessage, MessageStatus } from '@/models/ChatMessage'

/**
* Stores all chat messages for all conversations
1 change: 1 addition & 0 deletions web/helpers/atoms/Conversation.atom.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Conversation, ConversationState } from '@/types/chatMessage'
import { atom } from 'jotai'

// import { MainViewState, setMainViewStateAtom } from './MainView.atom'
1 change: 1 addition & 0 deletions web/hooks/useCreateConversation.ts
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import {
addNewConversationStateAtom,
} from '@/helpers/atoms/Conversation.atom'
import { pluginManager } from '@/plugin'
import { Conversation } from '@/types/chatMessage'

export const useCreateConversation = () => {
const [userConversations, setUserConversations] = useAtom(
1 change: 1 addition & 0 deletions web/hooks/useGetInputState.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import { useActiveModel } from './useActiveModel'
import { useGetDownloadedModels } from './useGetDownloadedModels'

import { currentConversationAtom } from '@/helpers/atoms/Conversation.atom'
import { Conversation } from '@/types/chatMessage'

export default function useGetInputState() {
const [inputState, setInputState] = useState<InputType>('loading')
1 change: 1 addition & 0 deletions web/hooks/useGetUserConversations.ts
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import {
} from '@/helpers/atoms/Conversation.atom'
import { toChatMessage } from '@/models/ChatMessage'
import { pluginManager } from '@/plugin/PluginManager'
import { ChatMessage, ConversationState } from '@/types/chatMessage'

const useGetUserConversations = () => {
const setConversationStates = useSetAtom(conversationStatesAtom)
45 changes: 22 additions & 23 deletions web/hooks/useSendChatMessage.ts
Original file line number Diff line number Diff line change
@@ -12,9 +12,7 @@ import { Message } from '@janhq/core/lib/types'
import { useAtom, useAtomValue, useSetAtom } from 'jotai'

import { currentPromptAtom } from '@/containers/Providers/Jotai'

import { generateMessageId } from '@/utils/message'

import { ulid } from 'ulid'
import {
addNewMessageAtom,
getCurrentChatMessagesAtom,
@@ -24,9 +22,10 @@ import {
updateConversationAtom,
updateConversationWaitingForResponseAtom,
} from '@/helpers/atoms/Conversation.atom'
import { toChatMessage } from '@/models/ChatMessage'
import { MessageSenderType, toChatMessage } from '@/models/ChatMessage'

import { pluginManager } from '@/plugin/PluginManager'
import { ChatMessage, Conversation } from '@/types/chatMessage'

export default function useSendChatMessage() {
const currentConvo = useAtomValue(currentConversationAtom)
@@ -73,16 +72,13 @@ export default function useSendChatMessage() {
...updatedConv,
name: updatedConv.name ?? '',
message: updatedConv.lastMessage ?? '',
messages: currentMessages.map<Message>((e: ChatMessage) => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
_id: e.id,
message: e.text,
user: e.senderUid,
updatedAt: new Date(e.createdAt).toISOString(),
createdAt: new Date(e.createdAt).toISOString(),
}
}),
messages: currentMessages.map<Message>((e: ChatMessage) => ({
_id: e.id,
message: e.text,
user: e.senderUid,
updatedAt: new Date(e.createdAt).toISOString(),
createdAt: new Date(e.createdAt).toISOString(),
})),
})
}
}, 1000)
@@ -98,32 +94,35 @@ export default function useSendChatMessage() {

const prompt = currentPrompt.trim()
const messageHistory: MessageHistory[] = currentMessages
.map((msg) => {
return {
role: msg.senderUid === 'user' ? 'user' : 'assistant',
content: msg.text ?? '',
}
})
.map((msg) => ({
role: msg.senderUid,
content: msg.text ?? '',
}))
.reverse()
.concat([
{
role: 'user',
role: MessageSenderType.User,
content: prompt,
} as MessageHistory,
])
const newMessage: NewMessageRequest = {
// eslint-disable-next-line @typescript-eslint/naming-convention
_id: generateMessageId(),
_id: ulid(),
conversationId: convoId,
message: prompt,
user: 'user',
user: MessageSenderType.User,
createdAt: new Date().toISOString(),
history: messageHistory,
}

const newChatMessage = toChatMessage(newMessage)
addNewMessage(newChatMessage)

// delay randomly from 50 - 100ms
// to prevent duplicate message id
const delay = Math.floor(Math.random() * 50) + 50
await new Promise((resolve) => setTimeout(resolve, delay))

events.emit(EventName.OnNewMessageRequest, newMessage)
if (!currentConvo?.summary && currentConvo) {
const updatedConv: Conversation = {
1 change: 1 addition & 0 deletions web/package.json
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@
"tailwind-merge": "^2.0.0",
"tailwindcss": "3.3.5",
"typescript": "5.2.2",
"ulid": "^2.3.0",
"uuid": "^9.0.1",
"zod": "^3.22.4"
},
29 changes: 14 additions & 15 deletions web/screens/Chat/ChatItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import React, { forwardRef } from 'react'

import SimpleTextMessage from '../SimpleTextMessage'
import { ChatMessage } from '@/types/chatMessage'

type Props = {
message: ChatMessage
}

type Ref = HTMLDivElement

const ChatItem = forwardRef<Ref, Props>(({ message }, ref) => {
return (
<div ref={ref} className="py-4 even:bg-secondary dark:even:bg-secondary/20">
<SimpleTextMessage
status={message.status}
key={message.id}
avatarUrl={message.senderAvatarUrl}
senderName={message.senderName}
createdAt={message.createdAt}
senderType={message.messageSenderType}
text={message.text}
/>
</div>
)
})
const ChatItem = forwardRef<Ref, Props>(({ message }, ref) => (
<div ref={ref} className="py-4 even:bg-secondary dark:even:bg-secondary/20">
<SimpleTextMessage
status={message.status}
key={message.id}
avatarUrl={message.senderAvatarUrl}
senderName={message.senderName}
createdAt={message.createdAt}
senderType={message.messageSenderType}
text={message.text}
/>
</div>
))

export default ChatItem
2 changes: 1 addition & 1 deletion web/types/chatMessage.d.ts
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ enum MessageType {
Error = 'Error',
}

enum MessageSenderType {
export enum MessageSenderType {
Ai = 'assistant',
User = 'user',
}
4 changes: 0 additions & 4 deletions web/utils/message.ts
Original file line number Diff line number Diff line change
@@ -25,7 +25,3 @@ export function mergeAndRemoveDuplicates(

return result.reverse()
}

export const generateMessageId = () => {
return `m-${Date.now()}`
}

0 comments on commit 1fc9c4e

Please sign in to comment.