Compare commits

...

2 Commits

Author SHA1 Message Date
kangfenmao
a5d6e2c5c5 0.3.1 2024-07-21 23:44:09 +08:00
kangfenmao
2993ab8dc1 fix: topic missing bug and delete assistant crash 2024-07-21 23:43:17 +08:00
7 changed files with 85 additions and 96 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "cherry-studio",
"version": "0.3.0",
"version": "0.3.1",
"description": "A powerful AI assistant for producer.",
"main": "./out/main/index.js",
"author": "kangfenmao@qq.com",

View File

@@ -1,6 +1,6 @@
import { QuestionCircleOutlined } from '@ant-design/icons'
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 { Button, Col, InputNumber, Popover, Row, Slider, Tooltip } from 'antd'
import { debounce } from 'lodash'
@@ -12,10 +12,11 @@ interface Props {
assistant: Assistant
}
const PopoverContent: FC<Props> = ({ assistant }) => {
const PopoverContent: FC<Props> = (props) => {
const { assistant } = useAssistant(props.assistant.id)
const { updateAssistant } = useAssistants()
const [temperature, setTemperature] = useState(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
const [contextCount, setConextCount] = useState(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
const [temperature, setTemperature] = useState(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
const [contextCount, setConextCount] = useState(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
const { t } = useTranslation()
const onUpdateAssistantSettings = useCallback(
@@ -64,8 +65,8 @@ const PopoverContent: FC<Props> = ({ assistant }) => {
}
useEffect(() => {
setTemperature(assistant.settings?.temperature ?? DEFAULT_TEMPERATURE)
setConextCount(assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
setTemperature(assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE)
setConextCount(assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT)
}, [assistant])
return (

View File

@@ -5,9 +5,10 @@ import { useAssistants } from '@renderer/hooks/useAssistant'
import { getDefaultTopic } from '@renderer/services/assistant'
import { Assistant } from '@renderer/types'
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 { FC, useRef } from 'react'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
@@ -19,7 +20,6 @@ interface Props {
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
const { assistants, removeAssistant, updateAssistant, addAssistant, updateAssistants } = useAssistants()
const targetAssistant = useRef<Assistant | null>(null)
const { t } = useTranslation()
@@ -29,26 +29,25 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
removeAssistant(assistant.id)
}
const items: MenuProps['items'] = [
const getMenuItems = (assistant: Assistant) =>
[
{
label: t('common.edit'),
key: 'edit',
icon: <EditOutlined />,
async onClick() {
if (targetAssistant.current) {
const _assistant = await AssistantSettingPopup.show({ assistant: targetAssistant.current })
const _assistant = await AssistantSettingPopup.show({ assistant })
updateAssistant(_assistant)
}
}
},
{
label: t('common.duplicate'),
key: 'duplicate',
icon: <CopyOutlined />,
async onClick() {
const assistant: Assistant = { ...activeAssistant, id: uuid(), topics: [getDefaultTopic()] }
addAssistant(assistant)
setActiveAssistant(assistant)
onClick: async () => {
const _assistant: Assistant = { ...assistant, id: uuid(), topics: [getDefaultTopic()] }
addAssistant(_assistant)
setActiveAssistant(_assistant)
}
},
{ type: 'divider' },
@@ -57,11 +56,9 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
key: 'delete',
icon: <DeleteOutlined />,
danger: true,
onClick: () => {
targetAssistant.current && onDelete(targetAssistant.current)
onClick: () => onDelete(assistant)
}
}
]
] as ItemType[]
const onDragEnd = (result: DropResult) => {
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}>
{(provided) => (
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
<Dropdown
key={assistant.id}
menu={{ items }}
trigger={['contextMenu']}
onOpenChange={() => (targetAssistant.current = assistant)}>
<Dropdown key={assistant.id} menu={{ items: getMenuItems(assistant) }} trigger={['contextMenu']}>
<AssistantItem
onClick={() => setActiveAssistant(assistant)}
className={assistant.id === activeAssistant?.id ? 'active' : ''}>

View File

@@ -65,7 +65,6 @@ const Messages: FC<Props> = ({ assistant, topic }) => {
useEffect(() => {
const unsubscribes = [
EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, async (msg: Message) => {
console.debug({ assistant, provider, message: msg, topic })
onSendMessage(msg)
fetchChatCompletion({ assistant, messages: [...messages, msg], topic, onResponse: setLastMessage })
}),

View File

@@ -4,7 +4,7 @@ import { useShowRightSidebar } from '@renderer/hooks/useStore'
import { fetchMessagesSummary } from '@renderer/services/api'
import { Assistant, Topic } from '@renderer/types'
import { Button, Dropdown, MenuProps, Popconfirm } from 'antd'
import { FC, useRef } from 'react'
import { FC } from 'react'
import styled from 'styled-components'
import { DeleteOutlined, EditOutlined, SignatureOutlined } from '@ant-design/icons'
import LocalStorage from '@renderer/services/storage'
@@ -21,22 +21,20 @@ interface Props {
const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
const { showRightSidebar } = useShowRightSidebar()
const { removeTopic, updateTopic, removeAllTopics, updateTopics } = useAssistant(assistant.id)
const currentTopic = useRef<Topic | null>(null)
const { t } = useTranslation()
const topicMenuItems: MenuProps['items'] = [
const getTopicMenuItems = (topic: Topic) => {
const menus: MenuProps['items'] = [
{
label: t('assistant.topics.auto_rename'),
key: 'auto-rename',
icon: <SignatureOutlined />,
async onClick() {
if (currentTopic.current) {
const messages = await LocalStorage.getTopicMessages(currentTopic.current.id)
const messages = await LocalStorage.getTopicMessages(topic.id)
if (messages.length >= 2) {
const summaryText = await fetchMessagesSummary({ messages, assistant })
if (summaryText) {
updateTopic({ ...currentTopic.current, name: summaryText })
}
updateTopic({ ...topic, name: summaryText })
}
}
}
@@ -49,31 +47,33 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
const name = await PromptPopup.show({
title: t('assistant.topics.edit.title'),
message: t('assistant.topics.edit.placeholder'),
defaultValue: currentTopic.current?.name || ''
defaultValue: topic?.name || ''
})
if (name && currentTopic.current && currentTopic.current?.name !== name) {
updateTopic({ ...currentTopic.current, name })
if (name && topic?.name !== name) {
updateTopic({ ...topic, name })
}
}
}
]
if (assistant.topics.length > 1) {
topicMenuItems.push({ type: 'divider' })
topicMenuItems.push({
menus.push({ type: 'divider' })
menus.push({
label: t('common.delete'),
danger: true,
key: 'delete',
icon: <DeleteOutlined />,
onClick() {
if (assistant.topics.length === 1) return
currentTopic.current && removeTopic(currentTopic.current)
currentTopic.current = null
removeTopic(topic)
setActiveTopic(assistant.topics[0])
}
})
}
return menus
}
const onDragEnd = (result: DropResult) => {
if (result.destination) {
const sourceIndex = result.source.index
@@ -108,11 +108,7 @@ const Topics: FC<Props> = ({ assistant, activeTopic, setActiveTopic }) => {
<Draggable key={`draggable_${topic.id}_${index}`} draggableId={topic.id} index={index}>
{(provided) => (
<div ref={provided.innerRef} {...provided.draggableProps} {...provided.dragHandleProps}>
<Dropdown
menu={{ items: topicMenuItems }}
trigger={['contextMenu']}
key={topic.id}
onOpenChange={(open) => open && (currentTopic.current = topic)}>
<Dropdown menu={{ items: getTopicMenuItems(topic) }} trigger={['contextMenu']} key={topic.id}>
<TopicListItem
className={topic.id === activeTopic?.id ? 'active' : ''}
onClick={() => setActiveTopic(topic)}>

View File

@@ -47,7 +47,7 @@ export default class ProviderSDK {
model: model.id,
messages: [systemMessage, ...userMessages].filter(Boolean) as MessageParam[],
max_tokens: 4096,
temperature: assistant.settings?.temperature
temperature: assistant?.settings?.temperature
})
.on('text', (text) => onChunk({ text: text || '' }))
.on('finalMessage', (message) =>
@@ -64,7 +64,7 @@ export default class ProviderSDK {
model: model.id,
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
stream: true,
temperature: assistant.settings?.temperature
temperature: assistant?.settings?.temperature
})
for await (const chunk of stream) {
if (window.keyv.get(EVENT_NAMES.CHAT_COMPLETION_PAUSED)) break

View File

@@ -169,10 +169,10 @@ export function getFirstCharacter(str) {
}
export const getAssistantSettings = (assistant: Assistant): AssistantSettings => {
const contextCount = assistant.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
const contextCount = assistant?.settings?.contextCount ?? DEFAULT_CONEXTCOUNT
return {
contextCount: contextCount === 20 ? 100000 : contextCount,
temperature: assistant.settings?.temperature ?? DEFAULT_TEMPERATURE
temperature: assistant?.settings?.temperature ?? DEFAULT_TEMPERATURE
}
}