Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge bug fixes from 0.5.12 into dev #4338

Merged
merged 19 commits into from
Dec 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9603d36
Merge pull request #4302 from janhq/dev
louis-menlo Dec 19, 2024
11f4f20
fix: thread error handling
louis-menlo Dec 20, 2024
1acbb33
Merge pull request #4307 from janhq/fix/thread-error-handling
louis-menlo Dec 20, 2024
4e43f97
fix: fetch threads and messages without limiting (#4304)
louis-menlo Dec 20, 2024
af84a3a
fix: scroll bottom issue (#4308)
urmauur Dec 20, 2024
8738421
fix: overlap bottom system monitor (#4310)
urmauur Dec 20, 2024
5163e12
chore: add OpenAI gpt-4o-mini and o1 models (#4311)
louis-menlo Dec 21, 2024
abb718c
fix: width inputbox based on preference and remove tooltip image uplo…
urmauur Dec 23, 2024
2422267
fix: cleaning a thread should just clear out messages (#4316)
louis-menlo Dec 23, 2024
1f4c00d
fix: change theme settings do not work after relocated data folder (#…
louis-menlo Dec 23, 2024
365cdfa
fix: threads sorting order after updated (#4319)
louis-menlo Dec 23, 2024
9c4dcd3
fix: update thread's title edge cases (#4320)
louis-menlo Dec 23, 2024
171dad1
fix: generating message is gone after switching to another thread (#4…
louis-menlo Dec 23, 2024
df1c465
fix: app picks model automatically edge cases (#4322)
louis-menlo Dec 23, 2024
56d1ffa
fix: scroll bottom when generation text (#4323)
urmauur Dec 23, 2024
e8e5c8c
fix: disabled native resize textarea when textarea autogrowing (#4326)
urmauur Dec 23, 2024
b28cac7
fix: render performance while generating messages (#4328)
louis-menlo Dec 23, 2024
dccd9dd
chore: bump cortex 1.0.6-rc (#4330)
louis-menlo Dec 24, 2024
3cd4db0
chore: bump latest cortex stable release version (#4336)
louis-menlo Dec 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions extensions/conversational-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default class CortexConversationalExtension extends ConversationalExtensi
async listThreads(): Promise<Thread[]> {
return this.queue.add(() =>
ky
.get(`${API_URL}/v1/threads`)
.get(`${API_URL}/v1/threads?limit=-1`)
.json<ThreadList>()
.then((e) => e.data)
) as Promise<Thread[]>
Expand Down Expand Up @@ -133,7 +133,7 @@ export default class CortexConversationalExtension extends ConversationalExtensi
async listMessages(threadId: string): Promise<ThreadMessage[]> {
return this.queue.add(() =>
ky
.get(`${API_URL}/v1/threads/${threadId}/messages?order=asc`)
.get(`${API_URL}/v1/threads/${threadId}/messages?order=asc&limit=-1`)
.json<MessageList>()
.then((e) => e.data)
) as Promise<ThreadMessage[]>
Expand All @@ -147,7 +147,9 @@ export default class CortexConversationalExtension extends ConversationalExtensi
*/
async getThreadAssistant(threadId: string): Promise<ThreadAssistantInfo> {
return this.queue.add(() =>
ky.get(`${API_URL}/v1/assistants/${threadId}`).json<ThreadAssistantInfo>()
ky
.get(`${API_URL}/v1/assistants/${threadId}?limit=-1`)
.json<ThreadAssistantInfo>()
) as Promise<ThreadAssistantInfo>
}
/**
Expand Down Expand Up @@ -188,7 +190,7 @@ export default class CortexConversationalExtension extends ConversationalExtensi
* Do health check on cortex.cpp
* @returns
*/
healthz(): Promise<void> {
async healthz(): Promise<void> {
return ky
.get(`${API_URL}/healthz`, {
retry: { limit: 20, delay: () => 500, methods: ['get'] },
Expand Down
2 changes: 1 addition & 1 deletion extensions/inference-cortex-extension/bin/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.5-rc2
1.0.6
57 changes: 57 additions & 0 deletions extensions/inference-openai-extension/resources/models.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,63 @@
},
"engine": "openai"
},
{
"sources": [
{
"url": "https://openai.com"
}
],
"id": "gpt-4o-mini",
"object": "model",
"name": "OpenAI GPT 4o-mini",
"version": "1.1",
"description": "GPT-4o mini (“o” for “omni”) is a fast, affordable small model for focused tasks.",
"format": "api",
"settings": {
"vision_model": true
},
"parameters": {
"max_tokens": 16384,
"temperature": 0.7,
"top_p": 0.95,
"stream": true,
"stop": [],
"frequency_penalty": 0,
"presence_penalty": 0
},
"metadata": {
"author": "OpenAI",
"tags": ["General"]
},
"engine": "openai"
},
{
"sources": [
{
"url": "https://openai.com"
}
],
"id": "o1",
"object": "model",
"name": "OpenAI o1",
"version": "1.0",
"description": "OpenAI o1 is a new model with complex reasoning",
"format": "api",
"settings": {},
"parameters": {
"max_tokens": 100000,
"temperature": 1,
"top_p": 1,
"stream": true,
"frequency_penalty": 0,
"presence_penalty": 0
},
"metadata": {
"author": "OpenAI",
"tags": ["General"]
},
"engine": "openai"
},
{
"sources": [
{
Expand Down
2 changes: 1 addition & 1 deletion extensions/model-extension/src/cortex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class CortexAPI implements ICortexAPI {
*/
getModels(): Promise<Model[]> {
return this.queue
.add(() => ky.get(`${API_URL}/v1/models`).json<ModelList>())
.add(() => ky.get(`${API_URL}/v1/models?limit=-1`).json<ModelList>())
.then((e) =>
typeof e === 'object' ? e.data.map((e) => this.transformModel(e)) : []
)
Expand Down
6 changes: 5 additions & 1 deletion joi/src/core/TextArea/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
return (
<div className="textarea__wrapper">
<textarea
className={twMerge('textarea', className)}
className={twMerge(
'textarea',
className,
autoResize && 'resize-none'
)}
ref={autoResize ? textareaRef : ref}
{...props}
/>
Expand Down
9 changes: 3 additions & 6 deletions web/containers/ModelDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,14 @@

const handleChangeStateOpen = useCallback(
(state: boolean) => {
setOpen(state)
setModelDropdownState(state)

Check warning on line 120 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

119-120 lines are not covered with tests
},
[setModelDropdownState]
)

const isModelSupportRagAndTools = useCallback((model: Model) => {
return (

Check warning on line 126 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

126 line is not covered with tests
model?.engine === InferenceEngine.openai ||
isLocalEngine(model?.engine as InferenceEngine)
)
Expand All @@ -134,7 +134,7 @@
configuredModels
.concat(
downloadedModels.filter(
(e) => !configuredModels.some((x) => x.id === e.id)

Check warning on line 137 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

137 line is not covered with tests
)
)
.filter((e) =>
Expand All @@ -144,24 +144,24 @@
if (searchFilter === 'local') {
return isLocalEngine(e.engine)
}
if (searchFilter === 'remote') {
return !isLocalEngine(e.engine)

Check warning on line 148 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

147-148 lines are not covered with tests
}
})
.sort((a, b) => a.name.localeCompare(b.name))

Check warning on line 151 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

151 line is not covered with tests
.sort((a, b) => {
const aInDownloadedModels = downloadedModels.some(
(item) => item.id === a.id

Check warning on line 154 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

153-154 lines are not covered with tests
)
const bInDownloadedModels = downloadedModels.some(
(item) => item.id === b.id

Check warning on line 157 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

156-157 lines are not covered with tests
)
if (aInDownloadedModels && !bInDownloadedModels) {
return -1
} else if (!aInDownloadedModels && bInDownloadedModels) {
return 1

Check warning on line 162 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

159-162 lines are not covered with tests
} else {
return 0

Check warning on line 164 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

164 line is not covered with tests
}
}),
[configuredModels, searchText, searchFilter, downloadedModels]
Expand All @@ -183,10 +183,7 @@
if (!activeThread) return
const modelId = activeAssistant?.model?.id

let model = downloadedModels.find((model) => model.id === modelId)
if (!model) {
model = undefined
}
const model = downloadedModels.find((model) => model.id === modelId)
setSelectedModel(model)
}, [
recommendedModel,
Expand All @@ -198,10 +195,10 @@

const onClickModelItem = useCallback(
async (modelId: string) => {
if (!activeAssistant) return
const model = downloadedModels.find((m) => m.id === modelId)
setSelectedModel(model)
setOpen(false)

Check warning on line 201 in web/containers/ModelDropdown/index.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

198-201 lines are not covered with tests

if (activeThread) {
// Change assistand tools based on model support RAG
Expand Down Expand Up @@ -378,14 +375,14 @@
!selectedModel && 'text-[hsla(var(--text-tertiary))]'
)}
>
{selectedModel?.name || 'Select Model'}
{selectedModel?.name || 'Select a model'}
</span>
</Badge>
) : (
<Input
value={selectedModel?.name || ''}
className="cursor-pointer"
placeholder="Select Model"
placeholder="Select a model"
disabled={disabled}
readOnly
suffixIcon={
Expand Down
48 changes: 34 additions & 14 deletions web/containers/Providers/ModelHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
extractInferenceParams,
ModelExtension,
} from '@janhq/core'
import { useAtomValue, useSetAtom } from 'jotai'
import { useAtom, useAtomValue, useSetAtom } from 'jotai'
import { ulid } from 'ulidx'

import { activeModelAtom, stateModelAtom } from '@/hooks/useActiveModel'
Expand All @@ -32,6 +32,7 @@
updateMessageAtom,
tokenSpeedAtom,
deleteMessageAtom,
subscribedGeneratingMessageAtom,
} from '@/helpers/atoms/ChatMessage.atom'
import { downloadedModelsAtom } from '@/helpers/atoms/Model.atom'
import {
Expand All @@ -40,6 +41,7 @@
isGeneratingResponseAtom,
updateThreadAtom,
getActiveThreadModelParamsAtom,
activeThreadAtom,
} from '@/helpers/atoms/Thread.atom'

const maxWordForThreadTitle = 10
Expand All @@ -54,6 +56,10 @@
const activeModel = useAtomValue(activeModelAtom)
const setActiveModel = useSetAtom(activeModelAtom)
const setStateModel = useSetAtom(stateModelAtom)
const [subscribedGeneratingMessage, setSubscribedGeneratingMessage] = useAtom(

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-windows (default-windows-security)

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-macos

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-ubuntu

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-windows (mcafee)

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / coverage-check

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-ubuntu

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-macos

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-windows-pr

'setSubscribedGeneratingMessage' is assigned a value but never used

Check warning on line 59 in web/containers/Providers/ModelHandler.tsx

View workflow job for this annotation

GitHub Actions / test-on-windows (bit-defender)

'setSubscribedGeneratingMessage' is assigned a value but never used
subscribedGeneratingMessageAtom
)
const activeThread = useAtomValue(activeThreadAtom)

const updateThreadWaiting = useSetAtom(updateThreadWaitingForResponseAtom)
const threads = useAtomValue(threadsAtom)
Expand All @@ -62,11 +68,17 @@
const setIsGeneratingResponse = useSetAtom(isGeneratingResponseAtom)
const updateThread = useSetAtom(updateThreadAtom)
const messagesRef = useRef(messages)
const messageGenerationSubscriber = useRef(subscribedGeneratingMessage)
const activeModelRef = useRef(activeModel)
const activeThreadRef = useRef(activeThread)
const activeModelParams = useAtomValue(getActiveThreadModelParamsAtom)
const activeModelParamsRef = useRef(activeModelParams)
const setTokenSpeed = useSetAtom(tokenSpeedAtom)

useEffect(() => {
activeThreadRef.current = activeThread
}, [activeThread])

useEffect(() => {
threadsRef.current = threads
}, [threads])
Expand All @@ -87,6 +99,10 @@
activeModelParamsRef.current = activeModelParams
}, [activeModelParams])

useEffect(() => {
messageGenerationSubscriber.current = subscribedGeneratingMessage
}, [subscribedGeneratingMessage])

const onNewMessageResponse = useCallback(
async (message: ThreadMessage) => {
if (message.type === MessageRequestType.Thread) {
Expand Down Expand Up @@ -179,12 +195,19 @@

const updateThreadMessage = useCallback(
(message: ThreadMessage) => {
updateMessage(
message.id,
message.thread_id,
message.content,
message.status
)
if (
messageGenerationSubscriber.current &&
message.thread_id === activeThreadRef.current?.id &&
!messageGenerationSubscriber.current!.thread_id
) {
updateMessage(
message.id,
message.thread_id,
message.content,
message.status
)
}

if (message.status === MessageStatus.Pending) {
if (message.content.length) {
setIsGeneratingResponse(false)
Expand Down Expand Up @@ -244,6 +267,7 @@
const metadata = {
...thread.metadata,
...(messageContent && { lastMessage: messageContent }),
updated_at: Date.now(),
}

updateThread({
Expand Down Expand Up @@ -302,15 +326,10 @@

const generateThreadTitle = (message: ThreadMessage, thread: Thread) => {
// If this is the first ever prompt in the thread
if (
(thread.title ?? thread.metadata?.title)?.trim() !== defaultThreadTitle
) {
if ((thread.title ?? thread.metadata?.title)?.trim() !== defaultThreadTitle)
return
}

if (!activeModelRef.current) {
return
}
if (!activeModelRef.current) return

// Check model engine; we don't want to generate a title when it's not a local engine. remote model using first promp
if (!isLocalEngine(activeModelRef.current?.engine as InferenceEngine)) {
Expand All @@ -332,6 +351,7 @@
...updatedThread,
})
})
.catch(console.error)
}

// This is the first time message comes in on a new thread
Expand Down
18 changes: 18 additions & 0 deletions web/helpers/atoms/ChatMessage.atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ export const chatMessages = atom(
}
)

/**
* Store subscribed generating message thread
*/
export const subscribedGeneratingMessageAtom = atom<{
thread_id?: string
}>({})

/**
* Stores the status of the messages load for each thread
*/
Expand Down Expand Up @@ -175,6 +182,17 @@ export const updateMessageAtom = atom(
// Update thread last message
if (text.length)
set(updateThreadStateLastMessageAtom, conversationId, text)
} else {
set(addNewMessageAtom, {
id,
thread_id: conversationId,
content: text,
status,
role: ChatCompletionRole.Assistant,
created_at: Date.now() / 1000,
completed_at: Date.now() / 1000,
object: 'thread.message',
})
}
}
)
7 changes: 1 addition & 6 deletions web/helpers/atoms/Setting.atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,7 @@ export const CHAT_WIDTH = 'chatWidth'
export const themesOptionsAtom = atomWithStorage<
{ name: string; value: string }[]
>(THEME_OPTIONS, [], undefined, { getOnInit: true })
export const janThemesPathAtom = atomWithStorage<string | undefined>(
THEME_PATH,
undefined,
undefined,
{ getOnInit: true }
)

export const selectedThemeIdAtom = atomWithStorage<string>(
THEME,
'',
Expand Down
30 changes: 25 additions & 5 deletions web/helpers/atoms/Thread.atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,26 @@ export const waitingToSendMessage = atom<boolean | undefined>(undefined)
*/
export const isGeneratingResponseAtom = atom<boolean | undefined>(undefined)

/**
* Create a new thread and add it to the thread list
*/
export const createNewThreadAtom = atom(null, (get, set, newThread: Thread) => {
// create thread state for this new thread
const currentState = { ...get(threadStatesAtom) }

const threadState: ThreadState = {
hasMore: false,
waitingForResponse: false,
lastMessage: undefined,
}
currentState[newThread.id] = threadState
set(threadStatesAtom, currentState)

// add the new thread on top of the thread list to the state
const threads = get(threadsAtom)
set(threadsAtom, [newThread, ...threads])
})

/**
* Remove a thread state from the atom
*/
Expand Down Expand Up @@ -180,12 +200,12 @@ export const updateThreadAtom = atom(
)

// sort new threads based on updated at
threads.sort((thread1, thread2) => {
const aDate = new Date(thread1.updated ?? 0)
const bDate = new Date(thread2.updated ?? 0)
return bDate.getTime() - aDate.getTime()
threads.sort((a, b) => {
return ((a.metadata?.updated_at as number) ?? 0) >
((b.metadata?.updated_at as number) ?? 0)
? -1
: 1
})

set(threadsAtom, threads)
}
)
Expand Down
Loading
Loading