feat: add input toolbar
This commit is contained in:
parent
9313452490
commit
64a93e5c4b
@ -28,6 +28,7 @@
|
|||||||
"@fontsource/inter": "^5.0.18",
|
"@fontsource/inter": "^5.0.18",
|
||||||
"@reduxjs/toolkit": "^2.2.5",
|
"@reduxjs/toolkit": "^2.2.5",
|
||||||
"antd": "^5.18.3",
|
"antd": "^5.18.3",
|
||||||
|
"dayjs": "^1.11.11",
|
||||||
"electron-updater": "^6.1.7",
|
"electron-updater": "^6.1.7",
|
||||||
"electron-window-state": "^5.0.3",
|
"electron-window-state": "^5.0.3",
|
||||||
"emittery": "^1.0.3",
|
"emittery": "^1.0.3",
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
@import 'https://at.alicdn.com/t/c/font_4563475_yuh5d3ftmm.css';
|
@import 'https://at.alicdn.com/t/c/font_4563475_hrx8c92awui.css';
|
||||||
@import './markdown.scss';
|
@import './markdown.scss';
|
||||||
:root {
|
:root {
|
||||||
--color-white: #ffffff;
|
--color-white: #ffffff;
|
||||||
@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
--navbar-height: 40px;
|
--navbar-height: 40px;
|
||||||
--sidebar-width: 70px;
|
--sidebar-width: 70px;
|
||||||
--conversations-width: 240px;
|
--agents-width: 240px;
|
||||||
--settings-width: 280px;
|
--settings-width: 280px;
|
||||||
--status-bar-height: 40px;
|
--status-bar-height: 40px;
|
||||||
|
--input-bar-height: 120px;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
.markdown {
|
.markdown {
|
||||||
width: 100%;
|
|
||||||
max-width: 800px;
|
|
||||||
color: #fff;
|
color: #fff;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
@ -79,6 +77,14 @@
|
|||||||
background-color: #555;
|
background-color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 3px 5px;
|
padding: 3px 5px;
|
||||||
@ -92,5 +98,6 @@
|
|||||||
Liberation Mono,
|
Liberation Mono,
|
||||||
monospace;
|
monospace;
|
||||||
font-size: 80%;
|
font-size: 80%;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@ const NavbarContainer = styled.div`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const NavbarLeftContainer = styled.div`
|
const NavbarLeftContainer = styled.div`
|
||||||
min-width: var(--conversations-width);
|
min-width: var(--agents-width);
|
||||||
border-right: 1px solid #ffffff20;
|
border-right: 1px solid #ffffff20;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@ -24,7 +24,7 @@ const Container = styled.div`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const StatusbarLeft = styled.div`
|
const StatusbarLeft = styled.div`
|
||||||
min-width: var(--sidebar-width) + var(--conversations-width);
|
min-width: var(--sidebar-width) + var(--agents-width);
|
||||||
`
|
`
|
||||||
|
|
||||||
const StatusbarCenter = styled.div`
|
const StatusbarCenter = styled.div`
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
updateAgent
|
updateAgent
|
||||||
} from '@renderer/store/agents'
|
} from '@renderer/store/agents'
|
||||||
import { Agent } from '@renderer/types'
|
import { Agent } from '@renderer/types'
|
||||||
|
import localforage from 'localforage'
|
||||||
|
|
||||||
export default function useAgents() {
|
export default function useAgents() {
|
||||||
const { agents } = useAppSelector((state) => state.agents)
|
const { agents } = useAppSelector((state) => state.agents)
|
||||||
@ -15,7 +16,13 @@ export default function useAgents() {
|
|||||||
return {
|
return {
|
||||||
agents,
|
agents,
|
||||||
addAgent: (agent: Agent) => dispatch(addAgent(agent)),
|
addAgent: (agent: Agent) => dispatch(addAgent(agent)),
|
||||||
removeAgent: (id: string) => dispatch(removeAgent({ id })),
|
removeAgent: (id: string) => {
|
||||||
|
dispatch(removeAgent({ id }))
|
||||||
|
const agent = agents.find((a) => a.id === id)
|
||||||
|
if (agent) {
|
||||||
|
agent.conversations.forEach((id) => localforage.removeItem(`conversation:${id}`))
|
||||||
|
}
|
||||||
|
},
|
||||||
updateAgent: (agent: Agent) => dispatch(updateAgent(agent)),
|
updateAgent: (agent: Agent) => dispatch(updateAgent(agent)),
|
||||||
addConversation: (agentId: string, conversationId: string) => {
|
addConversation: (agentId: string, conversationId: string) => {
|
||||||
dispatch(addConversationToAgent({ agentId, conversationId }))
|
dispatch(addConversationToAgent({ agentId, conversationId }))
|
||||||
|
|||||||
@ -5,36 +5,24 @@ import styled from 'styled-components'
|
|||||||
import Chat from './components/Chat'
|
import Chat from './components/Chat'
|
||||||
import Agents from './components/Agents'
|
import Agents from './components/Agents'
|
||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { Agent } from '@renderer/types'
|
import { getDefaultAgent } from '@renderer/services/agent'
|
||||||
import { last } from 'lodash'
|
|
||||||
|
|
||||||
const HomePage: FC = () => {
|
const HomePage: FC = () => {
|
||||||
const { agents, addAgent } = useAgents()
|
const { agents, addAgent } = useAgents()
|
||||||
const [activeAgent, setActiveAgent] = useState(agents[0])
|
const [activeAgent, setActiveAgent] = useState(agents[0])
|
||||||
|
|
||||||
const onCreateConversation = () => {
|
const onCreateAgent = () => {
|
||||||
const _agent = {
|
const _agent = getDefaultAgent()
|
||||||
id: uuid(),
|
_agent.id = uuid()
|
||||||
name: 'New conversation',
|
|
||||||
avatar: 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp&f=y',
|
|
||||||
lastMessage: 'message',
|
|
||||||
lastMessageAt: 'now',
|
|
||||||
conversations: []
|
|
||||||
}
|
|
||||||
addAgent(_agent)
|
addAgent(_agent)
|
||||||
setActiveAgent(_agent)
|
setActiveAgent(_agent)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onRemoveAgent = (agent: Agent) => {
|
|
||||||
const _agent = last(agents.filter((a) => a.id !== agent.id))
|
|
||||||
_agent && setActiveAgent(_agent)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Navbar>
|
<Navbar>
|
||||||
<NavbarLeft style={{ justifyContent: 'flex-end', borderRight: 'none' }}>
|
<NavbarLeft style={{ justifyContent: 'flex-end', borderRight: 'none' }}>
|
||||||
<NewButton onClick={onCreateConversation}>
|
<NewButton onClick={onCreateAgent}>
|
||||||
<i className="iconfont icon-a-addchat"></i>
|
<i className="iconfont icon-a-addchat"></i>
|
||||||
</NewButton>
|
</NewButton>
|
||||||
</NavbarLeft>
|
</NavbarLeft>
|
||||||
@ -46,7 +34,7 @@ const HomePage: FC = () => {
|
|||||||
</NavbarRight>
|
</NavbarRight>
|
||||||
</Navbar>
|
</Navbar>
|
||||||
<ContentContainer>
|
<ContentContainer>
|
||||||
<Agents activeAgent={activeAgent} onActive={setActiveAgent} onRemove={onRemoveAgent} />
|
<Agents activeAgent={activeAgent} onActive={setActiveAgent} />
|
||||||
<Chat agent={activeAgent} />
|
<Chat agent={activeAgent} />
|
||||||
</ContentContainer>
|
</ContentContainer>
|
||||||
</Container>
|
</Container>
|
||||||
|
|||||||
@ -4,20 +4,23 @@ import useAgents from '@renderer/hooks/useAgents'
|
|||||||
import { Agent } from '@renderer/types'
|
import { Agent } from '@renderer/types'
|
||||||
import { Dropdown, MenuProps } from 'antd'
|
import { Dropdown, MenuProps } from 'antd'
|
||||||
import { EllipsisOutlined } from '@ant-design/icons'
|
import { EllipsisOutlined } from '@ant-design/icons'
|
||||||
|
import { last } from 'lodash'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
activeAgent: Agent
|
activeAgent: Agent
|
||||||
onActive: (agent: Agent) => void
|
onActive: (agent: Agent) => void
|
||||||
onRemove: (agent: Agent) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Agents: FC<Props> = ({ activeAgent, onActive, onRemove }) => {
|
const Agents: FC<Props> = ({ activeAgent, onActive }) => {
|
||||||
const { agents, removeAgent } = useAgents()
|
const { agents, removeAgent } = useAgents()
|
||||||
const targetAgent = useRef<Agent | null>(null)
|
const targetAgent = useRef<Agent | null>(null)
|
||||||
|
|
||||||
const onDelete = (agent: Agent) => {
|
const onDelete = (agent: Agent) => {
|
||||||
removeAgent(agent.id)
|
removeAgent(agent.id)
|
||||||
onRemove(agent)
|
setTimeout(() => {
|
||||||
|
const _agent = last(agents.filter((a) => a.id !== agent.id))
|
||||||
|
_agent && onActive(_agent)
|
||||||
|
}, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const items: MenuProps['items'] = [
|
const items: MenuProps['items'] = [
|
||||||
@ -36,14 +39,17 @@ const Agents: FC<Props> = ({ activeAgent, onActive, onRemove }) => {
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
console.debug('activeAgent', activeAgent)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
{agents.map((agent) => (
|
{agents.map((agent) => (
|
||||||
<AgentItem
|
<AgentItem
|
||||||
|
data-id={agent.id}
|
||||||
key={agent.id}
|
key={agent.id}
|
||||||
onClick={() => onActive(agent)}
|
onClick={() => onActive(agent)}
|
||||||
className={agent.id === activeAgent?.id ? 'active' : ''}>
|
className={agent.id === activeAgent?.id ? 'active' : ''}>
|
||||||
<Dropdown menu={{ items }} trigger={['click']} placement="bottom">
|
<Dropdown menu={{ items }} trigger={['click']} placement="bottom" arrow>
|
||||||
<EllipsisOutlined
|
<EllipsisOutlined
|
||||||
style={{ position: 'absolute', right: 12, top: 12 }}
|
style={{ position: 'absolute', right: 12, top: 12 }}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
@ -53,8 +59,7 @@ const Agents: FC<Props> = ({ activeAgent, onActive, onRemove }) => {
|
|||||||
/>
|
/>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<AgentName>{agent.name}</AgentName>
|
<AgentName>{agent.name}</AgentName>
|
||||||
<AgentLastMessage>{agent.lastMessage}</AgentLastMessage>
|
<AgentLastMessage>{agent.description}</AgentLastMessage>
|
||||||
<AgentTime>{agent.lastMessageAt}</AgentTime>
|
|
||||||
</AgentItem>
|
</AgentItem>
|
||||||
))}
|
))}
|
||||||
</Container>
|
</Container>
|
||||||
@ -64,8 +69,8 @@ const Agents: FC<Props> = ({ activeAgent, onActive, onRemove }) => {
|
|||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: var(--conversations-width);
|
min-width: var(--agents-width);
|
||||||
max-width: var(--conversations-width);
|
max-width: var(--agents-width);
|
||||||
border-right: 0.5px solid #ffffff20;
|
border-right: 0.5px solid #ffffff20;
|
||||||
height: calc(100vh - var(--navbar-height));
|
height: calc(100vh - var(--navbar-height));
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
@ -95,11 +100,6 @@ const AgentItem = styled.div`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const AgentTime = styled.div`
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--color-text-2);
|
|
||||||
`
|
|
||||||
|
|
||||||
const AgentName = styled.div`
|
const AgentName = styled.div`
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text-1);
|
color: var(--color-text-1);
|
||||||
|
|||||||
@ -43,6 +43,7 @@ const Conversations: FC<Props> = ({ agent, conversationId }) => {
|
|||||||
|
|
||||||
const _message: Message = {
|
const _message: Message = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
|
role: 'agent',
|
||||||
content: '',
|
content: '',
|
||||||
agentId: agent.id,
|
agentId: agent.id,
|
||||||
conversationId,
|
conversationId,
|
||||||
@ -82,7 +83,6 @@ const Conversations: FC<Props> = ({ agent, conversationId }) => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
runAsyncFunction(async () => {
|
runAsyncFunction(async () => {
|
||||||
const conversation = await localforage.getItem<Conversation>(`conversation:${conversationId}`)
|
const conversation = await localforage.getItem<Conversation>(`conversation:${conversationId}`)
|
||||||
console.debug('conversation', conversation)
|
|
||||||
setMessages(conversation ? conversation.messages : [])
|
setMessages(conversation ? conversation.messages : [])
|
||||||
})
|
})
|
||||||
}, [conversationId])
|
}, [conversationId])
|
||||||
@ -102,6 +102,7 @@ const Container = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
|
max-height: calc(100vh - var(--input-bar-height) - var(--navbar-height));
|
||||||
&::-webkit-scrollbar {
|
&::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,8 @@ import { Agent, Message } from '@renderer/types'
|
|||||||
import { uuid } from '@renderer/utils'
|
import { uuid } from '@renderer/utils'
|
||||||
import { FC, useState } from 'react'
|
import { FC, useState } from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
|
import { MoreOutlined } from '@ant-design/icons'
|
||||||
|
import { Tooltip } from 'antd'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
agent: Agent
|
agent: Agent
|
||||||
@ -17,6 +19,7 @@ const Inputbar: FC<Props> = ({ agent }) => {
|
|||||||
|
|
||||||
const message: Message = {
|
const message: Message = {
|
||||||
id: uuid(),
|
id: uuid(),
|
||||||
|
role: 'user',
|
||||||
content: text,
|
content: text,
|
||||||
agentId: agent.id,
|
agentId: agent.id,
|
||||||
conversationId,
|
conversationId,
|
||||||
@ -31,28 +34,100 @@ const Inputbar: FC<Props> = ({ agent }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<Container>
|
||||||
|
<Toolbar>
|
||||||
|
<ToolbarMenu>
|
||||||
|
<Tooltip placement="top" title=" New Chat " arrow>
|
||||||
|
<ToolbarItem>
|
||||||
|
<i className="iconfont icon-a-new-chat"></i>
|
||||||
|
</ToolbarItem>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip placement="top" title=" Topics " arrow>
|
||||||
|
<ToolbarItem>
|
||||||
|
<i className="iconfont icon-textedit_text_topic"></i>
|
||||||
|
</ToolbarItem>
|
||||||
|
</Tooltip>
|
||||||
|
</ToolbarMenu>
|
||||||
|
<ToolbarMenu>
|
||||||
|
<Tooltip placement="top" title=" Settings " arrow>
|
||||||
|
<ToolbarItem style={{ marginRight: 0 }}>
|
||||||
|
<MoreOutlined />
|
||||||
|
</ToolbarItem>
|
||||||
|
</Tooltip>
|
||||||
|
</ToolbarMenu>
|
||||||
|
</Toolbar>
|
||||||
<Textarea
|
<Textarea
|
||||||
value={text}
|
value={text}
|
||||||
onChange={(e) => setText(e.target.value)}
|
onChange={(e) => setText(e.target.value)}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Type a message..."
|
placeholder="Type a message..."
|
||||||
autoFocus
|
autoFocus
|
||||||
|
contextMenu="true"
|
||||||
/>
|
/>
|
||||||
|
</Container>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Textarea = styled.textarea`
|
const Container = styled.div`
|
||||||
padding: 15px;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 120px;
|
height: var(--input-bar-height);
|
||||||
min-height: 120px;
|
border-top: 0.5px solid #ffffff20;
|
||||||
|
padding: 5px 15px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const Textarea = styled.textarea`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
resize: none;
|
resize: none;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
color: var(--color-text);
|
color: var(--color-text);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-top: 0.5px solid #ffffff20;
|
`
|
||||||
|
|
||||||
|
const Toolbar = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
margin: 0 -5px;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ToolbarMenu = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
`
|
||||||
|
|
||||||
|
const ToolbarItem = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
cursor: pointer;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
font-size: 18px;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
margin-right: 6px;
|
||||||
|
color: var(--color-icon);
|
||||||
|
.iconfont {
|
||||||
|
font-size: 18px;
|
||||||
|
transition: all 0.2s ease-in-out;
|
||||||
|
}
|
||||||
|
.icon-textedit_text_topic {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-background-soft);
|
||||||
|
.iconfont {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export default Inputbar
|
export default Inputbar
|
||||||
|
|||||||
@ -65,7 +65,7 @@ const ContentContainer = styled.div`
|
|||||||
const SettingMenus = styled.ul`
|
const SettingMenus = styled.ul`
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
min-width: var(--conversations-width);
|
min-width: var(--agents-width);
|
||||||
border-right: 1px solid #ffffff20;
|
border-right: 1px solid #ffffff20;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
`
|
`
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
export function getDefaultAgent() {
|
export function getDefaultAgent() {
|
||||||
return {
|
return {
|
||||||
id: 'default',
|
id: 'default',
|
||||||
name: 'Chat Assistant',
|
name: 'Default Agent',
|
||||||
avatar: '',
|
description: "Hello, I'm Default Agent.",
|
||||||
lastMessage: 'I am your personal intelligent assistant Cherry, how can I help you now?',
|
|
||||||
lastMessageAt: 'now',
|
|
||||||
conversations: []
|
conversations: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,23 +24,23 @@ const agentsSlice = createSlice({
|
|||||||
state.agents = state.agents.map((c) => (c.id === action.payload.id ? action.payload : c))
|
state.agents = state.agents.map((c) => (c.id === action.payload.id ? action.payload : c))
|
||||||
},
|
},
|
||||||
addConversationToAgent: (state, action: PayloadAction<{ agentId: string; conversationId: string }>) => {
|
addConversationToAgent: (state, action: PayloadAction<{ agentId: string; conversationId: string }>) => {
|
||||||
state.agents = state.agents.map((c) =>
|
state.agents = state.agents.map((agent) =>
|
||||||
c.id === action.payload.agentId
|
agent.id === action.payload.agentId
|
||||||
? {
|
? {
|
||||||
...c,
|
...agent,
|
||||||
conversations: [...c.conversations, action.payload.conversationId]
|
conversations: [...new Set([...agent.conversations, action.payload.conversationId])]
|
||||||
}
|
}
|
||||||
: c
|
: agent
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
removeConversationFromAgent: (state, action: PayloadAction<{ agentId: string; conversationId: string }>) => {
|
removeConversationFromAgent: (state, action: PayloadAction<{ agentId: string; conversationId: string }>) => {
|
||||||
state.agents = state.agents.map((c) =>
|
state.agents = state.agents.map((agent) =>
|
||||||
c.id === action.payload.agentId
|
agent.id === action.payload.agentId
|
||||||
? {
|
? {
|
||||||
...c,
|
...agent,
|
||||||
conversations: c.conversations.filter((id) => id !== action.payload.conversationId)
|
conversations: agent.conversations.filter((id) => id !== action.payload.conversationId)
|
||||||
}
|
}
|
||||||
: c
|
: agent
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
export type Agent = {
|
export type Agent = {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
avatar: string
|
description: string
|
||||||
lastMessage: string
|
|
||||||
lastMessageAt: string
|
|
||||||
conversations: string[]
|
conversations: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Message = {
|
export type Message = {
|
||||||
id: string
|
id: string
|
||||||
|
role: 'user' | 'agent'
|
||||||
content: string
|
content: string
|
||||||
agentId: string
|
agentId: string
|
||||||
conversationId: string
|
conversationId: string
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user