fix: topic missing bug and delete assistant crash
This commit is contained in:
parent
117069e450
commit
2993ab8dc1
@ -1,6 +1,6 @@
|
|||||||
import { QuestionCircleOutlined } from '@ant-design/icons'
|
import { QuestionCircleOutlined } from '@ant-design/icons'
|
||||||
import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
import { DEFAULT_CONEXTCOUNT, DEFAULT_TEMPERATURE } from '@renderer/config/constant'
|
||||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||||
import { Assistant } from '@renderer/types'
|
import { Assistant } from '@renderer/types'
|
||||||
import { Button, Col, InputNumber, Popover, Row, Slider, Tooltip } from 'antd'
|
import { Button, Col, InputNumber, Popover, Row, Slider, Tooltip } from 'antd'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
@ -12,10 +12,11 @@ interface Props {
|
|||||||
assistant: Assistant
|
assistant: Assistant
|
||||||
}
|
}
|
||||||
|
|
||||||
const PopoverContent: FC<Props> = ({ assistant }) => {
|
const PopoverContent: FC<Props> = (props) => {
|
||||||
|
const { assistant } = useAssistant(props.assistant.id)
|
||||||
const { updateAssistant } = useAssistants()
|
const { updateAssistant } = useAssistants()
|
||||||
const [temperature, setTemperature] = useState(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||||
const [contextCount, setConextCount] = useState(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
const [contextCount, setConextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const onUpdateAssistantSettings = useCallback(
|
const onUpdateAssistantSettings = useCallback(
|
||||||
@ -64,8 +65,8 @@ const PopoverContent: FC<Props> = ({ assistant }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTemperature(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
setTemperature(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
|
||||||
setConextCount(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
setConextCount(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
|
||||||
}, [assistant])
|
}, [assistant])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -5,9 +5,10 @@ import { useAssistants } from '@renderer/hooks/useAssistant'
|
|||||||
import { getDefaultTopic } from '@renderer/services/assistant'
|
import { getDefaultTopic } from '@renderer/services/assistant'
|
||||||
import { Assistant } from '@renderer/types'
|
import { Assistant } from '@renderer/types'
|
||||||
import { droppableReorder, uuid } from '@renderer/utils'
|
import { droppableReorder, uuid } from '@renderer/utils'
|
||||||
import { Dropdown, MenuProps } from 'antd'
|
import { Dropdown } from 'antd'
|
||||||
|
import { ItemType } from 'antd/es/menu/interface'
|
||||||
import { last } from 'lodash'
|
import { last } from 'lodash'
|
||||||
import { FC, useRef } from 'react'
|
import { FC } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
|
||||||
@ -19,7 +20,6 @@ interface Props {
|
|||||||
|
|
||||||
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
|
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
|
||||||
const { assistants, removeAssistant, updateAssistant, addAssistant, updateAssistants } = useAssistants()
|
const { assistants, removeAssistant, updateAssistant, addAssistant, updateAssistants } = useAssistants()
|
||||||
const targetAssistant = useRef<Assistant | null>(null)
|
|
||||||
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
@ -29,39 +29,36 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
|||||||
removeAssistant(assistant.id)
|
removeAssistant(assistant.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
const getMenuItems = (assistant: Assistant) =>
|
||||||
{
|
[
|
||||||
label: t('common.edit'),
|
{
|
||||||
key: 'edit',
|
label: t('common.edit'),
|
||||||
icon: <EditOutlined />,
|
key: 'edit',
|
||||||
async onClick() {
|
icon: <EditOutlined />,
|
||||||
if (targetAssistant.current) {
|
async onClick() {
|
||||||
const _assistant = await AssistantSettingPopup.show({ assistant: targetAssistant.current })
|
const _assistant = await AssistantSettingPopup.show({ assistant })
|
||||||
updateAssistant(_assistant)
|
updateAssistant(_assistant)
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('common.duplicate'),
|
||||||
|
key: 'duplicate',
|
||||||
|
icon: <CopyOutlined />,
|
||||||
|
onClick: async () => {
|
||||||
|
const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic()] }
|
||||||
|
addAssistant(_assistant)
|
||||||
|
setActiveAssistant(_assistant)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'divider' },
|
||||||
|
{
|
||||||
|
label: t('common.delete'),
|
||||||
|
key: 'delete',
|
||||||
|
icon: <DeleteOutlined />,
|
||||||
|
danger: true,
|
||||||
|
onClick: () => onDelete(assistant)
|
||||||
}
|
}
|
||||||
},
|
] as ItemType[]
|
||||||
{
|
|
||||||
label: t('common.duplicate'),
|
|
||||||
key: 'duplicate',
|
|
||||||
icon: <CopyOutlined />,
|
|
||||||
async onClick() {
|
|
||||||
const assistant: Assistant = { ...activeAssistant, id: uuid(), topics: [getDefaultTopic()] }
|
|
||||||
addAssistant(assistant)
|
|
||||||
setActiveAssistant(assistant)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ type: 'divider' },
|
|
||||||
{
|
|
||||||
label: t('common.delete'),
|
|
||||||
key: 'delete',
|
|
||||||
icon: <DeleteOutlined />,
|
|
||||||
danger: true,
|
|
||||||
onClick: () => {
|
|
||||||
targetAssistant.current && onDelete(targetAssistant.current)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const onDragEnd = (result: DropResult) => {
|
const onDragEnd = (result: DropResult) => {
|
||||||
if (result.destination) {
|
if (result.destination) {
|
||||||
@ -82,11 +79,7 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
|||||||
<Draggable key={`draggable_${assistant.id}_${index}`} draggableId={assistant.id} index={index}>
|
<Draggable key={`draggable_${assistant.id}_${index}`} draggableId={assistant.id} index={index}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||||
<Dropdown
|
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
|
||||||
key={assistant.id}
|
|
||||||
menu={{ items }}
|
|
||||||
trigger={['contextMenu']}
|
|
||||||
onOpenChange={() => (targetAssistant.current = assistant)}>
|
|
||||||
<AssistantItem
|
<AssistantItem
|
||||||
onClick={() => setActiveAssistant(assistant)}
|
onClick={() => setActiveAssistant(assistant)}
|
||||||
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
|
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
|
||||||
|
|||||||
@ -65,7 +65,6 @@ const Messages: FC<Props> = ({ assistant, topic }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribes = [
|
const unsubscribes = [
|
||||||
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
|
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
|
||||||
console.debug({ assistant, provider, message: msg, topic })
|
|
||||||
onSendMessage(msg)
|
onSendMessage(msg)
|
||||||
fetchChatCompletion({ assistant, messages: [...messages, msg], topic, onResponse: setLastMessage })
|
fetchChatCompletion({ assistant, messages: [...messages, msg], topic, onResponse: setLastMessage })
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import { useShowRightSidebar } from '@renderer/hooks/useStore'
|
|||||||
import { fetchMessagesSummary } from '@renderer/services/api'
|
import { fetchMessagesSummary } from '@renderer/services/api'
|
||||||
import { Assistant, Topic } from '@renderer/types'
|
import { Assistant, Topic } from '@renderer/types'
|
||||||
import { Button, Dropdown, MenuProps, Popconfirm } from 'antd'
|
import { Button, Dropdown, MenuProps, Popconfirm } from 'antd'
|
||||||
import { FC, useRef } from 'react'
|
import { FC } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { DeleteOutlined, EditOutlined, SignatureOutlined } from '@ant-design/icons'
|
import { DeleteOutlined, EditOutlined, SignatureOutlined } from '@ant-design/icons'
|
||||||
import LocalStorage from '@renderer/services/storage'
|
import LocalStorage from '@renderer/services/storage'
|
||||||
@ -21,57 +21,57 @@ interface Props {
|
|||||||
const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
||||||
const { showRightSidebar } = useShowRightSidebar()
|
const { showRightSidebar } = useShowRightSidebar()
|
||||||
const { removeTopic, updateTopic, removeAllTopics, updateTopics } = useAssistant(assistant.id)
|
const { removeTopic, updateTopic, removeAllTopics, updateTopics } = useAssistant(assistant.id)
|
||||||
const currentTopic = useRef<Topic | null>(null)
|
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
|
||||||
const topicMenuItems: MenuProps['items'] = [
|
const getTopicMenuItems = (topic: Topic) => {
|
||||||
{
|
const menus: MenuProps['items'] = [
|
||||||
label: t('assistant.topics.auto_rename'),
|
{
|
||||||
key: 'auto-rename',
|
label: t('assistant.topics.auto_rename'),
|
||||||
icon: <SignatureOutlined />,
|
key: 'auto-rename',
|
||||||
async onClick() {
|
icon: <SignatureOutlined />,
|
||||||
if (currentTopic.current) {
|
async onClick() {
|
||||||
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
|
const messages = await LocalStorage.getTopicMessages(topic.id)
|
||||||
if (messages.length >= 2) {
|
if (messages.length >= 2) {
|
||||||
const summaryText = await fetchMessagesSummary({ messages, assistant })
|
const summaryText = await fetchMessagesSummary({ messages, assistant })
|
||||||
if (summaryText) {
|
if (summaryText) {
|
||||||
updateTopic({ ...currentTopic.current, name: summaryText })
|
updateTopic({ ...topic, name: summaryText })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
{
|
||||||
{
|
label: t('common.rename'),
|
||||||
label: t('common.rename'),
|
key: 'rename',
|
||||||
key: 'rename',
|
icon: <EditOutlined />,
|
||||||
icon: <EditOutlined />,
|
async onClick() {
|
||||||
async onClick() {
|
const name = await PromptPopup.show({
|
||||||
const name = await PromptPopup.show({
|
title: t('assistant.topics.edit.title'),
|
||||||
title: t('assistant.topics.edit.title'),
|
message: t('assistant.topics.edit.placeholder'),
|
||||||
message: t('assistant.topics.edit.placeholder'),
|
defaultValue: topic?.name || ''
|
||||||
defaultValue: currentTopic.current?.name || ''
|
})
|
||||||
})
|
if (name && topic?.name !== name) {
|
||||||
if (name && currentTopic.current && currentTopic.current?.name !== name) {
|
updateTopic({ ...topic, name })
|
||||||
updateTopic({ ...currentTopic.current, name })
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
]
|
||||||
]
|
|
||||||
|
|
||||||
if (assistant.topics.length > 1) {
|
if (assistant.topics.length > 1) {
|
||||||
topicMenuItems.push({ type: 'divider' })
|
menus.push({ type: 'divider' })
|
||||||
topicMenuItems.push({
|
menus.push({
|
||||||
label: t('common.delete'),
|
label: t('common.delete'),
|
||||||
danger: true,
|
danger: true,
|
||||||
key: 'delete',
|
key: 'delete',
|
||||||
icon: <DeleteOutlined />,
|
icon: <DeleteOutlined />,
|
||||||
onClick() {
|
onClick() {
|
||||||
if (assistant.topics.length === 1) return
|
if (assistant.topics.length === 1) return
|
||||||
currentTopic.current && removeTopic(currentTopic.current)
|
removeTopic(topic)
|
||||||
currentTopic.current = null
|
setActiveTopic(assistant.topics[0])
|
||||||
setActiveTopic(assistant.topics[0])
|
}
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
|
return menus
|
||||||
}
|
}
|
||||||
|
|
||||||
const onDragEnd = (result: DropResult) => {
|
const onDragEnd = (result: DropResult) => {
|
||||||
@ -108,11 +108,7 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
|
|||||||
<Draggable key={`draggable_${topic.id}_${index}`} draggableId={topic.id} index={index}>
|
<Draggable key={`draggable_${topic.id}_${index}`} draggableId={topic.id} index={index}>
|
||||||
{(provided) => (
|
{(provided) => (
|
||||||
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
|
||||||
<Dropdown
|
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
|
||||||
menu={{ items: topicMenuItems }}
|
|
||||||
trigger={['contextMenu']}
|
|
||||||
key={topic.id}
|
|
||||||
onOpenChange={(open) => open && (currentTopic.current = topic)}>
|
|
||||||
<TopicListItem
|
<TopicListItem
|
||||||
className={topic.id === activeTopic?.id ? 'active' : ''}
|
className={topic.id === activeTopic?.id ? 'active' : ''}
|
||||||
onClick={() => setActiveTopic(topic)}>
|
onClick={() => setActiveTopic(topic)}>
|
||||||
|
|||||||
@ -47,7 +47,7 @@ export default class ProviderSDK {
|
|||||||
model: model.id,
|
model: model.id,
|
||||||
messages: [systemMessage, ...userMessages].filter(Boolean) as MessageParam[],
|
messages: [systemMessage, ...userMessages].filter(Boolean) as MessageParam[],
|
||||||
max_tokens: 4096,
|
max_tokens: 4096,
|
||||||
temperature: assistant.settings?.temperature
|
temperature: assistant?.settings?.temperature
|
||||||
})
|
})
|
||||||
.on('text', (text) => onChunk({ text: text || '' }))
|
.on('text', (text) => onChunk({ text: text || '' }))
|
||||||
.on('finalMessage', (message) =>
|
.on('finalMessage', (message) =>
|
||||||
@ -64,7 +64,7 @@ export default class ProviderSDK {
|
|||||||
model: model.id,
|
model: model.id,
|
||||||
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
|
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
|
||||||
stream: true,
|
stream: true,
|
||||||
temperature: assistant.settings?.temperature
|
temperature: assistant?.settings?.temperature
|
||||||
})
|
})
|
||||||
for await (const chunk of stream) {
|
for await (const chunk of stream) {
|
||||||
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) break
|
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) break
|
||||||
|
|||||||
@ -169,10 +169,10 @@ export function getFirstCharacter(str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getAssistantSettings = (assistant: Assistant): AssistantSettings => {
|
export const getAssistantSettings = (assistant: Assistant): AssistantSettings => {
|
||||||
const contextCount = assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
|
const contextCount = assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
|
||||||
return {
|
return {
|
||||||
contextCount: contextCount === 20 ? 100000 : contextCount,
|
contextCount: contextCount === 20 ? 100000 : contextCount,
|
||||||
temperature: assistant.settings?.temperature ?? DEFAULT_TEMPERATURE
|
temperature: assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user