fix: assistant with last used and fix metadata (#5955)
* fix: assistant with last used and fix metadata * chore: revert instruction and desc * chore: fix current assistant state * chore: updae metadata message assistant * chore: update test case
This commit is contained in:
parent
160d158152
commit
63cb4fbf3b
@ -18,4 +18,5 @@ export const localStorageKey = {
|
|||||||
toolAvailability: 'tool-availability',
|
toolAvailability: 'tool-availability',
|
||||||
mcpGlobalPermissions: 'mcp-global-permissions',
|
mcpGlobalPermissions: 'mcp-global-permissions',
|
||||||
lastUsedModel: 'last-used-model',
|
lastUsedModel: 'last-used-model',
|
||||||
|
lastUsedAssistant: 'last-used-assistant',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,8 @@ vi.mock('../useAssistant', () => ({
|
|||||||
})),
|
})),
|
||||||
{
|
{
|
||||||
getState: vi.fn(() => ({
|
getState: vi.fn(() => ({
|
||||||
currentAssistant: { id: 'test-assistant', name: 'Test Assistant' }
|
currentAssistant: { id: 'test-assistant', name: 'Test Assistant' },
|
||||||
|
assistants: [{ id: 'test-assistant', name: 'Test Assistant' }]
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@ -11,7 +11,8 @@ vi.mock('../usePrompt', () => ({
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('../useAppState', () => ({
|
vi.mock('../useAppState', () => ({
|
||||||
useAppState: vi.fn(() => ({
|
useAppState: Object.assign(
|
||||||
|
vi.fn(() => ({
|
||||||
tools: [],
|
tools: [],
|
||||||
updateTokenSpeed: vi.fn(),
|
updateTokenSpeed: vi.fn(),
|
||||||
resetTokenSpeed: vi.fn(),
|
resetTokenSpeed: vi.fn(),
|
||||||
@ -20,10 +21,21 @@ vi.mock('../useAppState', () => ({
|
|||||||
updateLoadingModel: vi.fn(),
|
updateLoadingModel: vi.fn(),
|
||||||
setAbortController: vi.fn(),
|
setAbortController: vi.fn(),
|
||||||
})),
|
})),
|
||||||
|
{
|
||||||
|
getState: vi.fn(() => ({
|
||||||
|
tokenSpeed: { tokensPerSecond: 10 },
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
vi.mock('../useAssistant', () => ({
|
vi.mock('../useAssistant', () => ({
|
||||||
useAssistant: vi.fn(() => ({
|
useAssistant: vi.fn(() => ({
|
||||||
|
assistants: [{
|
||||||
|
id: 'test-assistant',
|
||||||
|
instructions: 'test instructions',
|
||||||
|
parameters: { stream: true },
|
||||||
|
}],
|
||||||
currentAssistant: {
|
currentAssistant: {
|
||||||
id: 'test-assistant',
|
id: 'test-assistant',
|
||||||
instructions: 'test instructions',
|
instructions: 'test instructions',
|
||||||
@ -88,6 +100,12 @@ vi.mock('../useModelContextApproval', () => ({
|
|||||||
})),
|
})),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
vi.mock('../useModelLoad', () => ({
|
||||||
|
useModelLoad: vi.fn(() => ({
|
||||||
|
setModelLoadError: vi.fn(),
|
||||||
|
})),
|
||||||
|
}))
|
||||||
|
|
||||||
vi.mock('@tanstack/react-router', () => ({
|
vi.mock('@tanstack/react-router', () => ({
|
||||||
useRouter: vi.fn(() => ({
|
useRouter: vi.fn(() => ({
|
||||||
navigate: vi.fn(),
|
navigate: vi.fn(),
|
||||||
@ -96,6 +114,7 @@ vi.mock('@tanstack/react-router', () => ({
|
|||||||
|
|
||||||
vi.mock('@/lib/completion', () => ({
|
vi.mock('@/lib/completion', () => ({
|
||||||
emptyThreadContent: { thread_id: 'test-thread', content: '' },
|
emptyThreadContent: { thread_id: 'test-thread', content: '' },
|
||||||
|
extractToolCall: vi.fn(),
|
||||||
newUserThreadContent: vi.fn(() => ({ thread_id: 'test-thread', content: 'user message' })),
|
newUserThreadContent: vi.fn(() => ({ thread_id: 'test-thread', content: 'user message' })),
|
||||||
newAssistantThreadContent: vi.fn(() => ({ thread_id: 'test-thread', content: 'assistant message' })),
|
newAssistantThreadContent: vi.fn(() => ({ thread_id: 'test-thread', content: 'assistant message' })),
|
||||||
sendCompletion: vi.fn(),
|
sendCompletion: vi.fn(),
|
||||||
|
|||||||
@ -35,6 +35,12 @@ export const useAppState = create<AppState>()((set) => ({
|
|||||||
tokenSpeed: undefined,
|
tokenSpeed: undefined,
|
||||||
currentToolCall: undefined,
|
currentToolCall: undefined,
|
||||||
updateStreamingContent: (content: ThreadMessage | undefined) => {
|
updateStreamingContent: (content: ThreadMessage | undefined) => {
|
||||||
|
const assistants = useAssistant.getState().assistants
|
||||||
|
const currentAssistant = useAssistant.getState().currentAssistant
|
||||||
|
|
||||||
|
const selectedAssistant =
|
||||||
|
assistants.find((a) => a.id === currentAssistant.id) || assistants[0]
|
||||||
|
|
||||||
set(() => ({
|
set(() => ({
|
||||||
streamingContent: content
|
streamingContent: content
|
||||||
? {
|
? {
|
||||||
@ -42,7 +48,7 @@ export const useAppState = create<AppState>()((set) => ({
|
|||||||
created_at: content.created_at || Date.now(),
|
created_at: content.created_at || Date.now(),
|
||||||
metadata: {
|
metadata: {
|
||||||
...content.metadata,
|
...content.metadata,
|
||||||
assistant: useAssistant.getState().currentAssistant,
|
assistant: selectedAssistant,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { createAssistant, deleteAssistant } from '@/services/assistants'
|
import { createAssistant, deleteAssistant } from '@/services/assistants'
|
||||||
import { Assistant as CoreAssistant } from '@janhq/core'
|
import { Assistant as CoreAssistant } from '@janhq/core'
|
||||||
import { create } from 'zustand'
|
import { create } from 'zustand'
|
||||||
|
import { localStorageKey } from '@/constants/localStorage'
|
||||||
|
|
||||||
interface AssistantState {
|
interface AssistantState {
|
||||||
assistants: Assistant[]
|
assistants: Assistant[]
|
||||||
@ -8,8 +9,29 @@ interface AssistantState {
|
|||||||
addAssistant: (assistant: Assistant) => void
|
addAssistant: (assistant: Assistant) => void
|
||||||
updateAssistant: (assistant: Assistant) => void
|
updateAssistant: (assistant: Assistant) => void
|
||||||
deleteAssistant: (id: string) => void
|
deleteAssistant: (id: string) => void
|
||||||
setCurrentAssistant: (assistant: Assistant) => void
|
setCurrentAssistant: (assistant: Assistant, saveToStorage?: boolean) => void
|
||||||
setAssistants: (assistants: Assistant[]) => void
|
setAssistants: (assistants: Assistant[]) => void
|
||||||
|
getLastUsedAssistant: () => string | null
|
||||||
|
setLastUsedAssistant: (assistantId: string) => void
|
||||||
|
initializeWithLastUsed: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions for localStorage
|
||||||
|
const getLastUsedAssistantId = (): string | null => {
|
||||||
|
try {
|
||||||
|
return localStorage.getItem(localStorageKey.lastUsedAssistant)
|
||||||
|
} catch (error) {
|
||||||
|
console.debug('Failed to get last used assistant from localStorage:', error)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setLastUsedAssistantId = (assistantId: string) => {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(localStorageKey.lastUsedAssistant, assistantId)
|
||||||
|
} catch (error) {
|
||||||
|
console.debug('Failed to set last used assistant in localStorage:', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const defaultAssistant: Assistant = {
|
export const defaultAssistant: Assistant = {
|
||||||
@ -51,17 +73,52 @@ export const useAssistant = create<AssistantState>()((set, get) => ({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
deleteAssistant: (id) => {
|
deleteAssistant: (id) => {
|
||||||
|
const state = get()
|
||||||
deleteAssistant(
|
deleteAssistant(
|
||||||
get().assistants.find((e) => e.id === id) as unknown as CoreAssistant
|
state.assistants.find((e) => e.id === id) as unknown as CoreAssistant
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
console.error('Failed to delete assistant:', error)
|
console.error('Failed to delete assistant:', error)
|
||||||
})
|
})
|
||||||
set({ assistants: get().assistants.filter((a) => a.id !== id) })
|
|
||||||
|
// Check if we're deleting the current assistant
|
||||||
|
const wasCurrentAssistant = state.currentAssistant.id === id
|
||||||
|
|
||||||
|
set({ assistants: state.assistants.filter((a) => a.id !== id) })
|
||||||
|
|
||||||
|
// If the deleted assistant was current, fallback to default and update localStorage
|
||||||
|
if (wasCurrentAssistant) {
|
||||||
|
set({ currentAssistant: defaultAssistant })
|
||||||
|
setLastUsedAssistantId(defaultAssistant.id)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setCurrentAssistant: (assistant) => {
|
setCurrentAssistant: (assistant, saveToStorage = true) => {
|
||||||
set({ currentAssistant: assistant })
|
set({ currentAssistant: assistant })
|
||||||
|
if (saveToStorage) {
|
||||||
|
setLastUsedAssistantId(assistant.id)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setAssistants: (assistants) => {
|
setAssistants: (assistants) => {
|
||||||
set({ assistants })
|
set({ assistants })
|
||||||
},
|
},
|
||||||
|
getLastUsedAssistant: () => {
|
||||||
|
return getLastUsedAssistantId()
|
||||||
|
},
|
||||||
|
setLastUsedAssistant: (assistantId) => {
|
||||||
|
setLastUsedAssistantId(assistantId)
|
||||||
|
},
|
||||||
|
initializeWithLastUsed: () => {
|
||||||
|
const lastUsedId = getLastUsedAssistantId()
|
||||||
|
if (lastUsedId) {
|
||||||
|
const lastUsedAssistant = get().assistants.find(
|
||||||
|
(a) => a.id === lastUsedId
|
||||||
|
)
|
||||||
|
if (lastUsedAssistant) {
|
||||||
|
set({ currentAssistant: lastUsedAssistant })
|
||||||
|
} else {
|
||||||
|
// Fallback to default if last used assistant was deleted
|
||||||
|
set({ currentAssistant: defaultAssistant })
|
||||||
|
setLastUsedAssistantId(defaultAssistant.id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}))
|
}))
|
||||||
|
|||||||
@ -45,7 +45,7 @@ export const useChat = () => {
|
|||||||
updateLoadingModel,
|
updateLoadingModel,
|
||||||
setAbortController,
|
setAbortController,
|
||||||
} = useAppState()
|
} = useAppState()
|
||||||
const { currentAssistant } = useAssistant()
|
const { assistants, currentAssistant } = useAssistant()
|
||||||
const { updateProvider } = useModelProvider()
|
const { updateProvider } = useModelProvider()
|
||||||
|
|
||||||
const { approvedTools, showApprovalModal, allowAllMCPPermissions } =
|
const { approvedTools, showApprovalModal, allowAllMCPPermissions } =
|
||||||
@ -74,6 +74,9 @@ export const useChat = () => {
|
|||||||
return provider?.provider || selectedProvider
|
return provider?.provider || selectedProvider
|
||||||
}, [provider, selectedProvider])
|
}, [provider, selectedProvider])
|
||||||
|
|
||||||
|
const selectedAssistant =
|
||||||
|
assistants.find((a) => a.id === currentAssistant.id) || assistants[0]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function setTools() {
|
function setTools() {
|
||||||
getTools().then((data: MCPTool[]) => {
|
getTools().then((data: MCPTool[]) => {
|
||||||
@ -92,6 +95,7 @@ export const useChat = () => {
|
|||||||
|
|
||||||
const getCurrentThread = useCallback(async () => {
|
const getCurrentThread = useCallback(async () => {
|
||||||
let currentThread = retrieveThread()
|
let currentThread = retrieveThread()
|
||||||
|
|
||||||
if (!currentThread) {
|
if (!currentThread) {
|
||||||
currentThread = await createThread(
|
currentThread = await createThread(
|
||||||
{
|
{
|
||||||
@ -99,7 +103,7 @@ export const useChat = () => {
|
|||||||
provider: selectedProvider,
|
provider: selectedProvider,
|
||||||
},
|
},
|
||||||
prompt,
|
prompt,
|
||||||
currentAssistant
|
selectedAssistant
|
||||||
)
|
)
|
||||||
router.navigate({
|
router.navigate({
|
||||||
to: route.threadsDetail,
|
to: route.threadsDetail,
|
||||||
@ -114,7 +118,7 @@ export const useChat = () => {
|
|||||||
router,
|
router,
|
||||||
selectedModel?.id,
|
selectedModel?.id,
|
||||||
selectedProvider,
|
selectedProvider,
|
||||||
currentAssistant,
|
selectedAssistant,
|
||||||
])
|
])
|
||||||
|
|
||||||
const restartModel = useCallback(
|
const restartModel = useCallback(
|
||||||
@ -402,6 +406,7 @@ export const useChat = () => {
|
|||||||
accumulatedText,
|
accumulatedText,
|
||||||
{
|
{
|
||||||
tokenSpeed: useAppState.getState().tokenSpeed,
|
tokenSpeed: useAppState.getState().tokenSpeed,
|
||||||
|
assistant: currentAssistant,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -28,19 +28,18 @@ export const useMessages = create<MessageState>()((set, get) => ({
|
|||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
addMessage: (message) => {
|
addMessage: (message) => {
|
||||||
|
const assistants = useAssistant.getState().assistants
|
||||||
const currentAssistant = useAssistant.getState().currentAssistant
|
const currentAssistant = useAssistant.getState().currentAssistant
|
||||||
|
|
||||||
|
const selectedAssistant =
|
||||||
|
assistants.find((a) => a.id === currentAssistant.id) || assistants[0]
|
||||||
|
|
||||||
const newMessage = {
|
const newMessage = {
|
||||||
...message,
|
...message,
|
||||||
created_at: message.created_at || Date.now(),
|
created_at: message.created_at || Date.now(),
|
||||||
metadata: {
|
metadata: {
|
||||||
...message.metadata,
|
...message.metadata,
|
||||||
assistant: {
|
assistant: selectedAssistant,
|
||||||
id: currentAssistant?.id || '',
|
|
||||||
name: currentAssistant?.name || '',
|
|
||||||
avatar: currentAssistant?.avatar || '',
|
|
||||||
instructions: currentAssistant?.instructions || '',
|
|
||||||
parameters: currentAssistant?.parameters || '',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
createMessage(newMessage).then((createdMessage) => {
|
createMessage(newMessage).then((createdMessage) => {
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export function DataProvider() {
|
|||||||
const { setMessages } = useMessages()
|
const { setMessages } = useMessages()
|
||||||
const { checkForUpdate } = useAppUpdater()
|
const { checkForUpdate } = useAppUpdater()
|
||||||
const { setServers } = useMCPServers()
|
const { setServers } = useMCPServers()
|
||||||
const { setAssistants } = useAssistant()
|
const { setAssistants, initializeWithLastUsed } = useAssistant()
|
||||||
const { setThreads } = useThreads()
|
const { setThreads } = useThreads()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
@ -37,6 +37,7 @@ export function DataProvider() {
|
|||||||
// Only update assistants if we have valid data
|
// Only update assistants if we have valid data
|
||||||
if (data && Array.isArray(data) && data.length > 0) {
|
if (data && Array.isArray(data) && data.length > 0) {
|
||||||
setAssistants(data as unknown as Assistant[])
|
setAssistants(data as unknown as Assistant[])
|
||||||
|
initializeWithLastUsed()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user