feat: merge assistant and topics

This commit is contained in:
kangfenmao 2024-09-03 10:21:48 +08:00
parent 44e518ef03
commit ace0cb7823
21 changed files with 200 additions and 246 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -2,9 +2,10 @@ import { TranslationOutlined } from '@ant-design/icons'
import { isMac } from '@renderer/config/constant'
import { AppLogo, isLocalAi } from '@renderer/config/env'
import useAvatar from '@renderer/hooks/useAvatar'
import { useRuntime } from '@renderer/hooks/useStore'
import { useRuntime, useShowAssistants } from '@renderer/hooks/useStore'
import { Avatar } from 'antd'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import { Link, useLocation } from 'react-router-dom'
import styled from 'styled-components'
@ -16,11 +17,26 @@ const Sidebar: FC = () => {
const { pathname } = useLocation()
const avatar = useAvatar()
const { minappShow } = useRuntime()
const { toggleShowAssistants } = useShowAssistants()
const { generating } = useRuntime()
const { t } = useTranslation()
const isRoute = (path: string): string => (pathname === path ? 'active' : '')
const onEditUser = () => {
UserPopup.show()
const onEditUser = () => UserPopup.show()
const to = (path: string) => {
if (generating) {
window.message.warning({ content: t('message.switch.disabled'), key: 'switch-assistant' })
return '/'
}
return path
}
const onToggleShowAssistants = () => {
if (pathname === '/') {
toggleShowAssistants()
}
}
return (
@ -28,22 +44,22 @@ const Sidebar: FC = () => {
<AvatarImg src={avatar || AppLogo} draggable={false} className="nodrag" onClick={onEditUser} />
<MainMenus>
<Menus>
<StyledLink to="/">
<StyledLink to={to('/')} onClick={onToggleShowAssistants}>
<Icon className={isRoute('/')}>
<i className="iconfont icon-chat"></i>
</Icon>
</StyledLink>
<StyledLink to="/agents">
<StyledLink to={to('/agents')}>
<Icon className={isRoute('/agents')}>
<i className="iconfont icon-business-smart-assistant"></i>
</Icon>
</StyledLink>
<StyledLink to="/translate">
<StyledLink to={to('/translate')}>
<Icon className={isRoute('/translate')}>
<TranslationOutlined />
</Icon>
</StyledLink>
<StyledLink to="/apps">
<StyledLink to={to('/apps')}>
<Icon className={isRoute('/apps')}>
<i className="iconfont icon-appstore"></i>
</Icon>
@ -51,7 +67,7 @@ const Sidebar: FC = () => {
</Menus>
</MainMenus>
<Menus>
<StyledLink to={isLocalAi ? '/settings/assistant' : '/settings/provider'}>
<StyledLink to={to(isLocalAi ? '/settings/assistant' : '/settings/provider')}>
<Icon className={pathname.startsWith('/settings') ? 'active' : ''}>
<i className="iconfont icon-setting"></i>
</Icon>

View File

@ -255,46 +255,60 @@ export const SYSTEM_MODELS: Record<string, SystemModel[]> = {
}
],
zhipu: [
{
id: 'glm-4-0520',
provider: 'zhipu',
name: 'GLM-4-0520',
group: 'GLM',
enabled: true
},
{
id: 'glm-4',
provider: 'zhipu',
name: 'GLM-4',
group: 'GLM',
group: 'GLM-4',
enabled: false
},
{
id: 'glm-4-airx',
id: 'glm-4-plus',
provider: 'zhipu',
name: 'GLM-4-AirX',
group: 'GLM',
name: 'GLM-4-Plus',
group: 'GLM-4',
enabled: false
},
{
id: 'glm-4-air',
provider: 'zhipu',
name: 'GLM-4-Air',
group: 'GLM',
group: 'GLM-4',
enabled: true
},
{
id: 'glm-4-airx',
provider: 'zhipu',
name: 'GLM-4-AirX',
group: 'GLM-4',
enabled: false
},
{
id: 'glm-4-flash',
provider: 'zhipu',
name: 'GLM-4-Flash',
group: 'GLM-4',
enabled: false
},
{
id: 'glm-4v',
provider: 'zhipu',
name: 'GLM-4V',
group: 'GLM',
name: 'GLM 4V',
group: 'GLM-4v',
enabled: false
},
{
id: 'glm-4v-plus',
provider: 'zhipu',
name: 'GLM-4V-Plus',
group: 'GLM-4v',
enabled: false
},
{
id: 'glm-4-alltools',
provider: 'zhipu',
name: 'GLM-4-AllTools',
group: 'GLM',
group: 'GLM-4-AllTools',
enabled: false
}
],

View File

@ -2,7 +2,7 @@ import BaicuanAppLogo from '@renderer/assets/images/apps/baixiaoying.webp'
import KimiAppLogo from '@renderer/assets/images/apps/kimi.jpg'
import YuewenAppLogo from '@renderer/assets/images/apps/yuewen.png'
import BaichuanModelLogo from '@renderer/assets/images/models/baichuan.png'
import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.jpeg'
import ChatGLMModelLogo from '@renderer/assets/images/models/chatglm.png'
import ChatGPTModelLogo from '@renderer/assets/images/models/chatgpt.jpeg'
import ClaudeModelLogo from '@renderer/assets/images/models/claude.png'
import DeepSeekModelLogo from '@renderer/assets/images/models/deepseek.png'

View File

@ -1,17 +1,5 @@
import { useAppDispatch, useAppSelector } from '@renderer/store'
import { setShowRightSidebar, toggleRightSidebar, toggleShowAssistants } from '@renderer/store/settings'
export function useShowRightSidebar() {
const showRightSidebar = useAppSelector((state) => state.settings.showRightSidebar)
const dispatch = useAppDispatch()
return {
rightSidebarShown: showRightSidebar,
toggleRightSidebar: () => dispatch(toggleRightSidebar()),
showRightSidebar: () => dispatch(setShowRightSidebar(true)),
hideRightSidebar: () => dispatch(setShowRightSidebar(false))
}
}
import { toggleShowAssistants } from '@renderer/store/settings'
export function useShowAssistants() {
const showAssistants = useAppSelector((state) => state.settings.showAssistants)

View File

@ -2,9 +2,12 @@ import { Assistant, Topic } from '@renderer/types'
import { find } from 'lodash'
import { useEffect, useState } from 'react'
import { useAssistant } from './useAssistant'
let _activeTopic: Topic
export function useActiveTopic(assistant: Assistant) {
export function useActiveTopic(_assistant: Assistant) {
const { assistant } = useAssistant(_assistant.id)
const [activeTopic, setActiveTopic] = useState(_activeTopic || assistant?.topics[0])
useEffect(() => {

View File

@ -29,7 +29,8 @@ const resources = {
select: 'Select',
search: 'Search',
default: 'Default',
warning: 'Warning'
warning: 'Warning',
back: 'Back'
},
button: {
add: 'Add',
@ -67,7 +68,6 @@ const resources = {
'topics.delete.all.title': 'Delete all topics',
'topics.delete.all.content': 'Are you sure you want to delete all topics?',
'input.new_topic': 'New Topic',
'input.topics': ' Topics ',
'input.clear': 'Clear',
'input.expand': 'Expand',
'input.collapse': 'Collapse',
@ -267,7 +267,8 @@ const resources = {
select: '选择',
search: '搜索',
default: '默认',
warning: '警告'
warning: '警告',
back: '返回'
},
button: {
add: '添加',
@ -305,7 +306,6 @@ const resources = {
'topics.delete.all.title': '删除所有话题',
'topics.delete.all.content': '确定要删除所有话题吗?',
'input.new_topic': '新话题',
'input.topics': ' 话题 ',
'input.clear': '清除',
'input.expand': '展开',
'input.collapse': '收起',

View File

@ -1,11 +1,13 @@
import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { ArrowRightOutlined, CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { ArrowLeftOutlined } from '@ant-design/icons'
import DragableList from '@renderer/components/DragableList'
import { HStack } from '@renderer/components/Layout'
import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingPopup'
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
import { getDefaultTopic, syncAsistantToAgent } from '@renderer/services/assistant'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
import { useAppSelector } from '@renderer/store'
import { Assistant } from '@renderer/types'
import { Assistant, Topic } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { Dropdown } from 'antd'
import { ItemType } from 'antd/es/menu/interface'
@ -14,13 +16,27 @@ import { FC, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import Topics from './Topics'
interface Props {
activeAssistant: Assistant
setActiveAssistant: (assistant: Assistant) => void
activeTopic: Topic
setActiveTopic: (topic: Topic) => void
showTopics: boolean
setShowTopics: (showTopics: boolean) => void
onCreateAssistant: () => void
}
const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAssistant }) => {
const Assistants: FC<Props> = ({
activeAssistant,
setActiveAssistant,
activeTopic,
setActiveTopic,
showTopics,
setShowTopics,
onCreateAssistant
}) => {
const { assistants, removeAssistant, addAssistant, updateAssistants } = useAssistants()
const generating = useAppSelector((state) => state.runtime.generating)
const { updateAssistant } = useAssistant(activeAssistant.id)
@ -80,10 +96,23 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
}
EventEmitter.emit(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR)
setActiveAssistant(assistant)
setShowTopics(true)
},
[generating, setActiveAssistant, t]
[generating, setActiveAssistant, setShowTopics, t]
)
if (showTopics) {
return (
<Container>
<NavigtaionHeader onClick={() => setShowTopics(false)}>
<ArrowLeftOutlined />
{t('common.back')}
</NavigtaionHeader>
<Topics assistant={activeAssistant} activeTopic={activeTopic} setActiveTopic={setActiveTopic} />
</Container>
)
}
return (
<Container>
<DragableList list={assistants} onUpdate={updateAssistants}>
@ -93,6 +122,9 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
onClick={() => onSwitchAssistant(assistant)}
className={assistant.id === activeAssistant?.id ? 'active' : ''}>
<AssistantName className="name">{assistant.name || t('chat.default.name')}</AssistantName>
<HStack alignItems="center">
<ArrowRightOutlined />
</HStack>
</AssistantItem>
</Dropdown>
)}
@ -108,26 +140,31 @@ const Container = styled.div`
max-width: var(--assistants-width);
border-right: 0.5px solid var(--color-border);
height: calc(100vh - var(--navbar-height));
padding: 10px;
overflow-y: auto;
padding: 10px 0;
`
const AssistantItem = styled.div`
display: flex;
flex-direction: column;
flex-direction: row;
justify-content: space-between;
padding: 7px 10px;
position: relative;
border-radius: 4px;
margin: 0 10px;
cursor: pointer;
font-family: Ubuntu;
.anticon {
display: none;
color: var(--color-text-3);
}
&:hover {
background-color: var(--color-background-soft);
.count {
display: none;
}
.anticon {
display: block;
color: var(--color-text-1);
}
}
&.active {
@ -139,6 +176,19 @@ const AssistantItem = styled.div`
}
`
const NavigtaionHeader = styled.div`
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 10px;
padding: 0 5px;
cursor: pointer;
color: var(--color-text-3);
margin: 10px;
margin-top: 0;
`
const AssistantName = styled.div`
color: var(--color-text);
display: -webkit-box;

View File

@ -1,29 +1,35 @@
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useActiveTopic } from '@renderer/hooks/useTopic'
import { Assistant } from '@renderer/types'
import { Assistant, Topic } from '@renderer/types'
import { Flex } from 'antd'
import { FC } from 'react'
import { FC, useState } from 'react'
import styled from 'styled-components'
import Inputbar from './Inputbar/Inputbar'
import Messages from './Messages/Messages'
import RightSidebar from './RightSidebar'
import Settings from './Settings'
interface Props {
assistant: Assistant
activeTopic: Topic
setActiveTopic: (topic: Topic) => void
}
const Chat: FC<Props> = (props) => {
const { assistant } = useAssistant(props.assistant.id)
const { activeTopic, setActiveTopic } = useActiveTopic(assistant)
const [showSetting, setShowSetting] = useState(false)
return (
<Container id="chat">
<Main vertical flex={1} justify="space-between">
<Messages assistant={assistant} topic={activeTopic} />
<Inputbar assistant={assistant} setActiveTopic={setActiveTopic} />
<Messages assistant={assistant} topic={props.activeTopic} />
<Inputbar
assistant={assistant}
setActiveTopic={props.setActiveTopic}
showSetting={showSetting}
setShowSetting={setShowSetting}
/>
</Main>
<RightSidebar assistant={assistant} activeTopic={activeTopic} setActiveTopic={setActiveTopic} />
{showSetting && <Settings assistant={assistant} />}
</Container>
)
}

View File

@ -1,42 +0,0 @@
import { NavbarCenter } from '@renderer/components/app/Navbar'
import { isMac } from '@renderer/config/constant'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { useShowAssistants } from '@renderer/hooks/useStore'
import { Assistant } from '@renderer/types'
import { removeLeadingEmoji } from '@renderer/utils'
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import SelectModelButton from './components/SelectModelButton'
import { NewButton } from './HomePage'
interface Props {
activeAssistant: Assistant
}
const HomeHeader: FC<Props> = ({ activeAssistant }) => {
const { assistant } = useAssistant(activeAssistant.id)
const { t } = useTranslation()
const { showAssistants, toggleShowAssistants } = useShowAssistants()
return (
<NavbarCenter style={{ paddingLeft: isMac ? 16 : 8 }}>
{!showAssistants && (
<NewButton onClick={toggleShowAssistants} style={{ marginRight: isMac ? 8 : 25 }}>
<i className="iconfont icon-showsidebarhoriz" />
</NewButton>
)}
<AssistantName>{removeLeadingEmoji(assistant?.name) || t('chat.default.name')}</AssistantName>
<SelectModelButton assistant={assistant} />
</NavbarCenter>
)
}
const AssistantName = styled.span`
margin-left: 5px;
margin-right: 10px;
font-family: Ubuntu;
`
export default HomeHeader

View File

@ -1,30 +1,37 @@
import { Navbar, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
import { Navbar, NavbarCenter, NavbarLeft, NavbarRight } from '@renderer/components/app/Navbar'
import { isMac, isWindows } from '@renderer/config/constant'
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
import { useShowAssistants, useShowRightSidebar } from '@renderer/hooks/useStore'
import { useShowAssistants } from '@renderer/hooks/useStore'
import { useActiveTopic } from '@renderer/hooks/useTopic'
import { useTheme } from '@renderer/providers/ThemeProvider'
import { Assistant } from '@renderer/types'
import { Assistant, Topic } from '@renderer/types'
import { uuid } from '@renderer/utils'
import { Switch } from 'antd'
import { FC, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import AddAssistantPopup from '../../components/Popups/AddAssistantPopup'
import Assistants from './Assistants'
import Chat from './Chat'
import Navigation from './Header'
import SelectModelButton from './components/SelectModelButton'
let _activeAssistant: Assistant
let _showTopics = false
const HomePage: FC = () => {
const { assistants, addAssistant } = useAssistants()
const [activeAssistant, setActiveAssistant] = useState(_activeAssistant || assistants[0])
const { rightSidebarShown, toggleRightSidebar } = useShowRightSidebar()
const { showAssistants, toggleShowAssistants } = useShowAssistants()
const { showAssistants } = useShowAssistants()
const { defaultAssistant } = useDefaultAssistant()
const { theme, toggleTheme } = useTheme()
const [showTopics, setShowTopics] = useState(_showTopics)
const { t } = useTranslation()
const { activeTopic, setActiveTopic } = useActiveTopic(activeAssistant)
_activeAssistant = activeAssistant
_showTopics = showTopics
const onCreateDefaultAssistant = () => {
const assistant = { ...defaultAssistant, id: uuid() }
@ -37,20 +44,25 @@ const HomePage: FC = () => {
assistant && setActiveAssistant(assistant)
}
const onSetActiveTopic = (topic: Topic) => {
setActiveTopic(topic)
setShowTopics(true)
}
return (
<Container>
<Navbar>
{showAssistants && (
<NavbarLeft style={{ justifyContent: 'space-between', borderRight: 'none', padding: '0 8px' }}>
<NewButton onClick={toggleShowAssistants} style={{ marginLeft: isMac ? 8 : 0 }}>
<i className="iconfont icon-hidesidebarhoriz" />
</NewButton>
<NavbarLeft style={{ justifyContent: 'flex-end', borderRight: 'none', padding: '0 8px' }}>
<NewButton onClick={onCreateAssistant}>
<i className="iconfont icon-a-addchat"></i>
</NewButton>
</NavbarLeft>
)}
<Navigation activeAssistant={activeAssistant} />
<NavbarCenter style={{ paddingLeft: isMac ? 16 : 8 }}>
<AssistantName>{activeAssistant?.name || t('chat.default.name')}</AssistantName>
<SelectModelButton assistant={activeAssistant} />
</NavbarCenter>
<NavbarRight style={{ justifyContent: 'flex-end', paddingRight: isWindows ? 140 : 12 }}>
<ThemeSwitch
checkedChildren={<i className="iconfont icon-theme icon-dark1" />}
@ -58,9 +70,6 @@ const HomePage: FC = () => {
checked={theme === 'dark'}
onChange={toggleTheme}
/>
<NewButton onClick={toggleRightSidebar}>
<i className={`iconfont ${rightSidebarShown ? 'icon-showsidebarhoriz' : 'icon-hidesidebarhoriz'}`} />
</NewButton>
</NavbarRight>
</Navbar>
<ContentContainer>
@ -68,10 +77,14 @@ const HomePage: FC = () => {
<Assistants
activeAssistant={activeAssistant}
setActiveAssistant={setActiveAssistant}
activeTopic={activeTopic}
setActiveTopic={setActiveTopic}
showTopics={showTopics}
setShowTopics={setShowTopics}
onCreateAssistant={onCreateDefaultAssistant}
/>
)}
<Chat assistant={activeAssistant} />
<Chat assistant={activeAssistant} activeTopic={activeTopic} setActiveTopic={onSetActiveTopic} />
</ContentContainer>
</Container>
)
@ -90,6 +103,12 @@ const ContentContainer = styled.div`
background-color: var(--color-background);
`
const AssistantName = styled.span`
margin-left: 5px;
margin-right: 10px;
font-family: Ubuntu;
`
export const NewButton = styled.div`
-webkit-app-region: none;
border-radius: 4px;

View File

@ -3,7 +3,6 @@ import {
ControlOutlined,
FullscreenExitOutlined,
FullscreenOutlined,
HistoryOutlined,
PauseCircleOutlined,
PlusCircleOutlined,
QuestionCircleOutlined
@ -32,11 +31,13 @@ import SendMessageButton from './SendMessageButton'
interface Props {
assistant: Assistant
setActiveTopic: (topic: Topic) => void
showSetting: boolean
setShowSetting: (show: boolean) => void
}
let _text = ''
const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
const Inputbar: FC<Props> = ({ assistant, setActiveTopic, showSetting, setShowSetting }) => {
const [text, setText] = useState(_text)
const [inputFocus, setInputFocus] = useState(false)
const { addTopic } = useAssistant(assistant.id)
@ -194,6 +195,7 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
variant="borderless"
rows={1}
ref={textareaRef}
style={{ fontSize }}
styles={{ textarea: TextareaStyle }}
onFocus={() => setInputFocus(true)}
onBlur={() => setInputFocus(false)}
@ -219,13 +221,8 @@ const Inputbar: FC<Props> = ({ assistant, setActiveTopic }) => {
</ToolbarButton>
</Popconfirm>
</Tooltip>
<Tooltip placement="top" title={t('chat.input.topics')} arrow>
<ToolbarButton type="text" onClick={() => EventEmitter.emit(EVENT_NAMES.SHOW_TOPIC_SIDEBAR)}>
<HistoryOutlined />
</ToolbarButton>
</Tooltip>
<Tooltip placement="top" title={t('chat.input.settings')} arrow>
<ToolbarButton type="text" onClick={() => EventEmitter.emit(EVENT_NAMES.SHOW_CHAT_SETTINGS)}>
<Tooltip placement="top" title={t('chat.input.settings')} arrow className={showSetting ? 'active' : ''}>
<ToolbarButton type="text" onClick={() => setShowSetting(!showSetting)}>
<ControlOutlined />
</ToolbarButton>
</Tooltip>

View File

@ -162,7 +162,7 @@ const MessageItem: FC<Props> = ({ message, index, showMenu, onDeleteMessage }) =
</ActionButton>
</Tooltip>
{canRegenerate && (
<SelectModelDropdown model={model} onSelect={onRegenerate} placement="topRight">
<SelectModelDropdown model={model} onSelect={onRegenerate} placement="topLeft">
<Tooltip title={t('common.regenerate')} mouseEnterDelay={0.8}>
<ActionButton>
<SyncOutlined />

View File

@ -1,96 +0,0 @@
import { BarsOutlined, SettingOutlined } from '@ant-design/icons'
import { useShowRightSidebar } from '@renderer/hooks/useStore'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/event'
import { Assistant, Topic } from '@renderer/types'
import { Segmented } from 'antd'
import { FC, useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import styled from 'styled-components'
import SettingsTab from './SettingsTab'
import TopicsTab from './TopicsTab'
interface Props {
assistant: Assistant
activeTopic: Topic
setActiveTopic: (topic: Topic) => void
}
const RightSidebar: FC<Props> = (props) => {
const [tab, setTab] = useState<'topic' | 'settings'>('topic')
const { rightSidebarShown, showRightSidebar, hideRightSidebar } = useShowRightSidebar()
const { t } = useTranslation()
const isTopicTab = tab === 'topic'
const isSettingsTab = tab === 'settings'
useEffect(() => {
const unsubscribes = [
EventEmitter.on(EVENT_NAMES.SHOW_TOPIC_SIDEBAR, (): any => {
if (rightSidebarShown && isTopicTab) {
return hideRightSidebar()
}
if (rightSidebarShown) {
return setTab('topic')
}
showRightSidebar()
setTab('topic')
}),
EventEmitter.on(EVENT_NAMES.SHOW_CHAT_SETTINGS, (): any => {
if (rightSidebarShown && isSettingsTab) {
return hideRightSidebar()
}
if (rightSidebarShown) {
return setTab('settings')
}
showRightSidebar()
setTab('settings')
}),
EventEmitter.on(EVENT_NAMES.SWITCH_TOPIC_SIDEBAR, () => setTab('topic'))
]
return () => unsubscribes.forEach((unsub) => unsub())
}, [hideRightSidebar, isSettingsTab, isTopicTab, rightSidebarShown, showRightSidebar])
if (!rightSidebarShown) {
return null
}
return (
<Container>
<Segmented
value={tab}
style={{ borderRadius: 0, padding: '10px', gap: 5, borderBottom: '0.5px solid var(--color-border)' }}
options={[
{ label: t('common.topics'), value: 'topic', icon: <BarsOutlined /> },
{ label: t('settings.title'), value: 'settings', icon: <SettingOutlined /> }
]}
block
onChange={(value) => setTab(value as 'topic' | 'settings')}
/>
<TabContent>
{tab === 'topic' && <TopicsTab {...props} />}
{tab === 'settings' && <SettingsTab assistant={props.assistant} />}
</TabContent>
</Container>
)
}
const Container = styled.div`
display: flex;
flex-direction: column;
width: var(--topic-list-width);
height: calc(100vh - var(--navbar-height));
border-left: 0.5px solid var(--color-border);
.collapsed {
width: 0;
border-left: none;
}
`
const TabContent = styled.div`
display: flex;
flex: 1;
flex-direction: column;
overflow-y: auto;
`
export default RightSidebar

View File

@ -234,7 +234,13 @@ const Container = styled.div`
display: flex;
flex: 1;
flex-direction: column;
width: var(--topic-list-width);
max-width: var(--topic-list-width);
height: calc(100vh - var(--navbar-height));
border-left: 0.5px solid var(--color-border);
padding: 0 15px;
padding-bottom: 20px;
overflow-y: auto;
`
const Label = styled.p`

View File

@ -18,7 +18,7 @@ interface Props {
setActiveTopic: (topic: Topic) => void
}
const TopicsTab: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic }) => {
const Topics: FC<Props> = ({ assistant: _assistant, activeTopic, setActiveTopic }) => {
const { assistant, removeTopic, updateTopic, updateTopics } = useAssistant(_assistant.id)
const { t } = useTranslation()
const generating = useAppSelector((state) => state.runtime.generating)
@ -136,11 +136,12 @@ const Container = styled.div`
display: flex;
flex: 1;
flex-direction: column;
padding: 10px 10px;
overflow-y: scroll;
`
const TopicListItem = styled.div`
padding: 7px 10px;
margin: 0 10px;
cursor: pointer;
border-radius: 4px;
white-space: nowrap;
@ -155,4 +156,4 @@ const TopicListItem = styled.div`
}
`
export default TopicsTab
export default Topics

View File

@ -1,5 +1,4 @@
import { PlusOutlined } from '@ant-design/icons'
import { DeleteOutlined, EditOutlined } from '@ant-design/icons'
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
import { getProviderLogo } from '@renderer/config/provider'
import { useAllProviders, useProviders } from '@renderer/hooks/useProvider'

View File

@ -2,8 +2,6 @@ import { Divider } from 'antd'
import Link from 'antd/es/typography/Link'
import styled from 'styled-components'
import SettingsPage from './SettingsPage'
export const SettingContainer = styled.div`
display: flex;
flex-direction: column;
@ -69,5 +67,3 @@ export const SettingHelpLink = styled(Link)`
font-size: 11px;
padding: 0 5px;
`
export default SettingsPage

View File

@ -54,12 +54,7 @@ export default class ProviderSDK {
const userMessages = takeRight(messages, contextCount + 1).map((message) => {
return {
role: message.role,
content: message.images
? [
{ type: 'text', text: message.content },
...message.images!.map((image) => ({ type: 'image_url', image_url: image }))
]
: message.content
content: message.content
}
})
@ -132,10 +127,22 @@ export default class ProviderSDK {
return
}
const _userMessages = takeRight(messages, contextCount + 1).map((message) => {
return {
role: message.role,
content: message.images
? [
{ type: 'text', text: message.content },
...message.images!.map((image) => ({ type: 'image_url', image_url: image }))
]
: message.content
}
})
// @ts-ignore key is not typed
const stream = await this.openaiSdk.chat.completions.create({
model: model.id,
messages: [systemMessage, ...userMessages].filter(Boolean) as ChatCompletionMessageParam[],
messages: [systemMessage, ..._userMessages].filter(Boolean) as ChatCompletionMessageParam[],
stream: true,
temperature: assistant?.settings?.temperature,
max_tokens: maxTokens,

View File

@ -9,7 +9,6 @@ export enum ThemeMode {
}
export interface SettingsState {
showRightSidebar: boolean
showAssistants: boolean
sendMessageShortcut: SendMessageShortcut
language: string
@ -23,7 +22,6 @@ export interface SettingsState {
}
const initialState: SettingsState = {
showRightSidebar: true,
showAssistants: true,
sendMessageShortcut: 'Enter',
language: navigator.language,
@ -40,12 +38,6 @@ const settingsSlice = createSlice({
name: 'settings',
initialState,
reducers: {
toggleRightSidebar: (state) => {
state.showRightSidebar = !state.showRightSidebar
},
setShowRightSidebar: (state, action: PayloadAction<boolean>) => {
state.showRightSidebar = action.payload
},
toggleShowAssistants: (state) => {
state.showAssistants = !state.showAssistants
},
@ -80,8 +72,6 @@ const settingsSlice = createSlice({
})
export const {
setShowRightSidebar,
toggleRightSidebar,
toggleShowAssistants,
setSendMessageShortcut,
setLanguage,