diff --git a/src/renderer/src/hooks/useAgents.ts b/src/renderer/src/hooks/useAgents.ts index ddaa40ac..fb33550e 100644 --- a/src/renderer/src/hooks/useAgents.ts +++ b/src/renderer/src/hooks/useAgents.ts @@ -1,12 +1,12 @@ import { useAppDispatch, useAppSelector } from '@renderer/store' import { - addConversation as _addConversation, - removeConversation as _removeConversation, + addTopic as _addTopic, + removeTopic as _removeTopic, addAgent, removeAgent, updateAgent } from '@renderer/store/agents' -import { Agent, Conversation } from '@renderer/types' +import { Agent, Topic } from '@renderer/types' import localforage from 'localforage' export default function useAgents() { @@ -20,7 +20,7 @@ export default function useAgents() { dispatch(removeAgent({ id })) const agent = agents.find((a) => a.id === id) if (agent) { - agent.conversations.forEach((id) => localforage.removeItem(`conversation:${id}`)) + agent.topics.forEach((id) => localforage.removeItem(`topic:${id}`)) } }, updateAgent: (agent: Agent) => dispatch(updateAgent(agent)) @@ -33,11 +33,11 @@ export function useAgent(id: string) { return { agent, - addConversation: (conversation: Conversation) => { - dispatch(_addConversation({ agentId: agent?.id!, conversation })) + addTopic: (topic: Topic) => { + dispatch(_addTopic({ agentId: agent?.id!, topic })) }, - removeConversation: (conversation: Conversation) => { - dispatch(_removeConversation({ agentId: agent?.id!, conversation })) + removeTopic: (topic: Topic) => { + dispatch(_removeTopic({ agentId: agent?.id!, topic })) } } } diff --git a/src/renderer/src/pages/home/components/Chat/Chat.tsx b/src/renderer/src/pages/home/components/Chat/Chat.tsx index 412a344b..0774ba7b 100644 --- a/src/renderer/src/pages/home/components/Chat/Chat.tsx +++ b/src/renderer/src/pages/home/components/Chat/Chat.tsx @@ -1,5 +1,5 @@ import { Agent } from '@renderer/types' -import { FC } from 'react' +import { FC, useState } from 'react' import styled from 'styled-components' import Inputbar from './Inputbar' import Conversations from './Conversations' @@ -13,6 +13,7 @@ interface Props { const Chat: FC = (props) => { const { agent } = useAgent(props.agent.id) + const [activeTopic, setActiveTopic] = useState(agent.topics[0]) if (!agent) { return null @@ -21,10 +22,10 @@ const Chat: FC = (props) => { return ( - - + + - + ) } diff --git a/src/renderer/src/pages/home/components/Chat/Conversations.tsx b/src/renderer/src/pages/home/components/Chat/Conversations.tsx index 15a4b46c..be482271 100644 --- a/src/renderer/src/pages/home/components/Chat/Conversations.tsx +++ b/src/renderer/src/pages/home/components/Chat/Conversations.tsx @@ -1,6 +1,6 @@ import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' import { openaiProvider } from '@renderer/services/provider' -import { Agent, Conversation, Message } from '@renderer/types' +import { Agent, Message, Topic } from '@renderer/types' import { runAsyncFunction, uuid } from '@renderer/utils' import localforage from 'localforage' import { FC, useCallback, useEffect, useState } from 'react' @@ -11,28 +11,29 @@ import hljs from 'highlight.js' interface Props { agent: Agent + topic: Topic } -const Conversations: FC = ({ agent }) => { +const Conversations: FC = ({ agent, topic }) => { const [messages, setMessages] = useState([]) const [lastMessage, setLastMessage] = useState(null) - const { id: conversationId } = agent.conversations[0] + const { id: topicId } = topic const onSendMessage = useCallback( (message: Message) => { const _messages = [...messages, message] setMessages(_messages) - const conversation = { - id: conversationId, + const topic = { + id: topicId, name: 'Default Topic', messages: _messages } - localforage.setItem(`conversation:${conversationId}`, conversation) + localforage.setItem(`topic:${topicId}`, topic) }, - [conversationId, messages] + [topicId, messages] ) const fetchChatCompletion = useCallback( @@ -48,7 +49,7 @@ const Conversations: FC = ({ agent }) => { role: 'agent', content: '', agentId: agent.id, - conversationId, + topicId, createdAt: 'now' } @@ -65,7 +66,7 @@ const Conversations: FC = ({ agent }) => { return _message }, - [agent.id, conversationId] + [agent.id, topicId] ) useEffect(() => { @@ -84,15 +85,15 @@ const Conversations: FC = ({ agent }) => { useEffect(() => { runAsyncFunction(async () => { - const conversation = await localforage.getItem(`conversation:${conversationId}`) - setMessages(conversation ? conversation.messages : []) + const topic = await localforage.getItem(`topic:${topicId}`) + setMessages(topic ? topic.messages : []) }) - }, [conversationId]) + }, [topicId]) useEffect(() => hljs.highlightAll()) return ( - + {lastMessage && } {reverse([...messages]).map((message) => ( diff --git a/src/renderer/src/pages/home/components/Chat/Inputbar.tsx b/src/renderer/src/pages/home/components/Chat/Inputbar.tsx index 3ce494df..a7400399 100644 --- a/src/renderer/src/pages/home/components/Chat/Inputbar.tsx +++ b/src/renderer/src/pages/home/components/Chat/Inputbar.tsx @@ -1,5 +1,5 @@ import { EVENT_NAMES, EventEmitter } from '@renderer/services/event' -import { Agent, Conversation, Message } from '@renderer/types' +import { Agent, Message, Topic } from '@renderer/types' import { uuid } from '@renderer/utils' import { FC, useState } from 'react' import styled from 'styled-components' @@ -10,23 +10,24 @@ import { useAgent } from '@renderer/hooks/useAgents' interface Props { agent: Agent + setActiveTopic: (topic: Topic) => void } -const Inputbar: FC = ({ agent }) => { +const Inputbar: FC = ({ agent, setActiveTopic }) => { const [text, setText] = useState('') const { setShowRightSidebar } = useShowRightSidebar() - const { addConversation } = useAgent(agent.id) + const { addTopic } = useAgent(agent.id) const handleKeyDown = (event: React.KeyboardEvent) => { if (event.key === 'Enter') { - const conversationId = agent.conversations[0] ? agent.conversations[0] : uuid() + const topicId = agent.topics[0] ? agent.topics[0] : uuid() const message: Message = { id: uuid(), role: 'user', content: text, agentId: agent.id, - conversationId, + topicId, createdAt: 'now' } @@ -38,12 +39,13 @@ const Inputbar: FC = ({ agent }) => { } const addNewConversation = () => { - const conversation: Conversation = { + const topic: Topic = { id: uuid(), name: 'Default Topic', messages: [] } - addConversation(conversation) + addTopic(topic) + setActiveTopic(topic) } return ( diff --git a/src/renderer/src/pages/home/components/Chat/TopicList.tsx b/src/renderer/src/pages/home/components/Chat/TopicList.tsx index 23cf2471..2f0257e9 100644 --- a/src/renderer/src/pages/home/components/Chat/TopicList.tsx +++ b/src/renderer/src/pages/home/components/Chat/TopicList.tsx @@ -1,19 +1,16 @@ import { useShowRightSidebar } from '@renderer/hooks/useStore' -import { Agent } from '@renderer/types' -import { FC, useEffect, useState } from 'react' +import { Agent, Topic } from '@renderer/types' +import { FC } from 'react' import styled from 'styled-components' interface Props { agent: Agent + activeTopic: Topic + setActiveTopic: (topic: Topic) => void } -const TopicList: FC = ({ agent }) => { +const TopicList: FC = ({ agent, activeTopic, setActiveTopic }) => { const { showRightSidebar } = useShowRightSidebar() - const [activeTopic, setActiveTopic] = useState(agent.conversations[0]) - - useEffect(() => { - setActiveTopic(agent.conversations[0]) - }, [agent.conversations, agent.id]) if (!showRightSidebar) { return null @@ -21,7 +18,7 @@ const TopicList: FC = ({ agent }) => { return ( - {agent.conversations.map((topic) => ( + {agent.topics.map((topic) => ( ) => { state.agents = state.agents.map((c) => (c.id === action.payload.id ? action.payload : c)) }, - addConversation: (state, action: PayloadAction<{ agentId: string; conversation: Conversation }>) => { + addTopic: (state, action: PayloadAction<{ agentId: string; topic: Topic }>) => { console.debug(action.payload) state.agents = state.agents.map((agent) => agent.id === action.payload.agentId ? { ...agent, - conversations: uniqBy([action.payload.conversation, ...agent.conversations], 'id') + topics: uniqBy([action.payload.topic, ...agent.topics], 'id') } : agent ) }, - removeConversation: (state, action: PayloadAction<{ agentId: string; conversation: Conversation }>) => { + removeTopic: (state, action: PayloadAction<{ agentId: string; topic: Topic }>) => { state.agents = state.agents.map((agent) => agent.id === action.payload.agentId ? { ...agent, - conversations: agent.conversations.filter(({ id }) => id !== action.payload.conversation.id) + topics: agent.topics.filter(({ id }) => id !== action.payload.topic.id) } : agent ) @@ -48,6 +48,6 @@ const agentsSlice = createSlice({ } }) -export const { addAgent, removeAgent, updateAgent, addConversation, removeConversation } = agentsSlice.actions +export const { addAgent, removeAgent, updateAgent, addTopic, removeTopic } = agentsSlice.actions export default agentsSlice.reducer diff --git a/src/renderer/src/types/index.ts b/src/renderer/src/types/index.ts index 15d9c457..d362cd79 100644 --- a/src/renderer/src/types/index.ts +++ b/src/renderer/src/types/index.ts @@ -2,7 +2,7 @@ export type Agent = { id: string name: string description: string - conversations: Conversation[] + topics: Topic[] } export type Message = { @@ -10,11 +10,11 @@ export type Message = { role: 'user' | 'agent' content: string agentId: string - conversationId: string + topicId: string createdAt: string } -export type Conversation = { +export type Topic = { id: string name: string messages: Message[]