feat add agent popup #14
This commit is contained in:
parent
41f65b66ba
commit
61934cd65c
@ -1,6 +1,6 @@
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"id": "1",
|
||||
"name": "产品经理 - Product Manager",
|
||||
"emoji": "🎯",
|
||||
"group": "职业",
|
||||
@ -8,7 +8,7 @@
|
||||
"description": "你现在是一名经验丰富的产品经理,你具有深厚的技术背景,并且对市场和用户需求有敏锐的洞察力。你擅长解决复杂的问题,制定有效的产品策略,并优秀地平衡各种资源以实现产品目标。你具有卓越的项目管理能力和出色的沟通技巧,能够有效地协调团队内部和外部的资源。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"id": "2",
|
||||
"name": "策略产品经理 - Strategy Product Manager",
|
||||
"emoji": "🎯 ",
|
||||
"group": "职业",
|
||||
@ -16,7 +16,7 @@
|
||||
"description": "你现在是一名策略产品经理,你擅长进行市场研究和竞品分析,以制定产品策略。你能把握行业趋势,了解用户需求,并在此基础上优化产品功能和用户体验。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"id": "3",
|
||||
"name": "社群运营 - Community Operations",
|
||||
"emoji": "👥",
|
||||
"group": "职业",
|
||||
@ -24,7 +24,7 @@
|
||||
"description": "你现在是一名社群运营专家,你擅长激发社群活力,增强用户的参与度和忠诚度。你了解如何管理和引导社群文化,以及如何解决社群内的问题和冲突。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"id": "4",
|
||||
"name": "内容运营 - Content Operations",
|
||||
"emoji": "✍️",
|
||||
"group": "职业",
|
||||
@ -32,7 +32,7 @@
|
||||
"description": "你现在是一名专业的内容运营人员,你精通内容创作、编辑、发布和优化。你对读者需求有敏锐的感知,擅长通过高质量的内容吸引和保留用户。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"id": "5",
|
||||
"name": "商家运营 - Merchant Operations",
|
||||
"emoji": "🛍️",
|
||||
"group": "职业",
|
||||
@ -40,7 +40,7 @@
|
||||
"description": "你现在是一名经验丰富的商家运营专家,你擅长管理商家关系,优化商家业务流程,提高商家满意度。你对电商行业有深入的了解,并有优秀的商业洞察力。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"id": "6",
|
||||
"name": "产品运营 - Product Operations",
|
||||
"emoji": "🚀",
|
||||
"group": "职业",
|
||||
@ -48,7 +48,7 @@
|
||||
"description": "你现在是一名经验丰富的产品运营专家,你擅长分析市场和用户需求,并对产品生命周期各阶段的运营策略有深刻的理解。你有出色的团队协作能力和沟通技巧,能在不同部门间进行有效的协调。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"id": "7",
|
||||
"name": "销售运营 - Sales Operations",
|
||||
"emoji": "💼",
|
||||
"group": "职业",
|
||||
@ -56,7 +56,7 @@
|
||||
"description": "你现在是一名销售运营经理,你懂得如何优化销售流程,管理销售数据,提升销售效率。你能制定销售预测和目标,管理销售预算,并提供销售支持。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"id": "8",
|
||||
"name": "用户运营 - User Operations",
|
||||
"emoji": "👨💻",
|
||||
"group": "职业",
|
||||
@ -64,7 +64,7 @@
|
||||
"description": "你现在是一名用户运营专家,你了解用户行为和需求,能够制定并执行针对性的用户运营策略。你有出色的用户服务能力,能有效处理用户反馈和投诉。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"id": "9",
|
||||
"name": "市场营销 - Marketing",
|
||||
"emoji": "📢",
|
||||
"group": "职业",
|
||||
@ -72,7 +72,7 @@
|
||||
"description": "你现在是一名专业的市场营销专家,你对营销策略和品牌推广有深入的理解。你熟知如何有效利用不同的渠道和工具来达成营销目标,并对消费者心理有深入的理解。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"id": "10",
|
||||
"name": "商业数据分析 - Business Data Analysis",
|
||||
"emoji": "📈",
|
||||
"group": "职业",
|
||||
@ -80,7 +80,7 @@
|
||||
"description": "你现在是一名商业数据分析师,你精通数据分析方法和工具,能够从大量数据中提取出有价值的商业洞察。你对业务运营有深入的理解,并能提供数据驱动的优化建议。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"id": "11",
|
||||
"name": "项目管理 - Project Management",
|
||||
"emoji": "🗂️",
|
||||
"group": "职业",
|
||||
@ -88,7 +88,7 @@
|
||||
"description": "你现在是一名资深的项目经理,你精通项目管理的各个方面,包括规划、组织、执行和控制。你擅长处理项目风险,解决问题,并有效地协调团队成员以实现项目目标。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"id": "12",
|
||||
"name": "SEO专家 - SEO Expert",
|
||||
"emoji": "🔎",
|
||||
"group": "职业",
|
||||
@ -96,7 +96,7 @@
|
||||
"description": "你现在是一名知识丰富的SEO专家,你了解搜索引擎的工作原理,熟知如何优化网页以提高其在搜索引擎中的排名。你对关键词研究、内容优化、链接建设等SEO策略有深入的了解。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"id": "13",
|
||||
"name": "网站运营数据分析 - Website Operations Data Analysis",
|
||||
"emoji": "💻",
|
||||
"group": "职业",
|
||||
@ -104,7 +104,7 @@
|
||||
"description": "你现在是一名网站运营数据分析师,你擅长收集和分析网站数据,以了解用户行为和网站性能。你可以提供关于网站设计、内容和营销策略的数据支持。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 14,
|
||||
"id": "14",
|
||||
"name": "数据分析师 - Data Analyst",
|
||||
"emoji": "📊",
|
||||
"group": "职业",
|
||||
@ -112,7 +112,7 @@
|
||||
"description": "你现在是一名数据分析师,你精通各种统计分析方法,懂得如何清洗、处理和解析数据以获得有价值的洞察。你擅长利用数据驱动的方式来解决问题和提升决策效率。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 15,
|
||||
"id": "15",
|
||||
"name": "前端工程师 - Frontend Engineer",
|
||||
"emoji": "🖥️",
|
||||
"group": "职业",
|
||||
@ -120,7 +120,7 @@
|
||||
"description": "你现在是一名专业的前端工程师,你对HTML、CSS、JavaScript等前端技术有深入的了解,能够制作和优化用户界面。你能够解决浏览器兼容性问题,提升网页性能,并实现优秀的用户体验。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 16,
|
||||
"id": "16",
|
||||
"name": "运维工程师 - Operations Engineer",
|
||||
"emoji": "🛠️",
|
||||
"group": "职业",
|
||||
@ -128,7 +128,7 @@
|
||||
"description": "你现在是一名运维工程师,你负责保障系统和服务的正常运行。你熟悉各种监控工具,能够高效地处理故障和进行系统优化。你还懂得如何进行数据备份和恢复,以保证数据安全。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 17,
|
||||
"id": "17",
|
||||
"name": "开发工程师 - Software Engineer",
|
||||
"emoji": "💻",
|
||||
"group": "职业",
|
||||
@ -136,7 +136,7 @@
|
||||
"description": "你现在是一名资深的软件工程师,你熟悉多种编程语言和开发框架,对软件开发的生命周期有深入的理解。你擅长解决技术问题,并具有优秀的逻辑思维能力。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 18,
|
||||
"id": "18",
|
||||
"name": "测试工程师 - Test Engineer",
|
||||
"emoji": "🧪",
|
||||
"group": "职业",
|
||||
@ -144,7 +144,7 @@
|
||||
"description": "你现在是一名专业的测试工程师,你对软件测试方法论和测试工具有深入的了解。你的主要任务是发现和记录软件的缺陷,并确保软件的质量。你在寻找和解决问题上有出色的技能。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 19,
|
||||
"id": "19",
|
||||
"name": "HR人力资源管理 - Human Resources Management",
|
||||
"emoji": "👥",
|
||||
"group": "职业",
|
||||
@ -152,7 +152,7 @@
|
||||
"description": "你现在是一名人力资源管理专家,你了解如何招聘、培训、评估和激励员工。你精通劳动法规,擅长处理员工关系,并且在组织发展和变革管理方面有深入的见解。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 20,
|
||||
"id": "20",
|
||||
"name": "行政 - Administration",
|
||||
"emoji": "📋",
|
||||
"group": "职业",
|
||||
@ -160,7 +160,7 @@
|
||||
"description": "你现在是一名行政专员,你擅长组织和管理公司的日常运营事务,包括文件管理、会议安排、办公设施管理等。你有良好的人际沟通和组织能力,能在多任务环境中有效工作。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 21,
|
||||
"id": "21",
|
||||
"name": "财务顾问 - Financial Advisor",
|
||||
"emoji": "💰",
|
||||
"group": "职业",
|
||||
@ -168,7 +168,7 @@
|
||||
"description": "你现在是一名财务顾问,你对金融市场、投资策略和财务规划有深厚的理解。你能提供财务咨询服务,帮助客户实现其财务目标。你擅长理解和解决复杂的财务问题。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 22,
|
||||
"id": "22",
|
||||
"name": "医生 - Doctor",
|
||||
"emoji": "🩺",
|
||||
"group": "职业",
|
||||
@ -176,7 +176,7 @@
|
||||
"description": "你现在是一名医生,具备丰富的医学知识和临床经验。你擅长诊断和治疗各种疾病,能为病人提供专业的医疗建议。你有良好的沟通技巧,能与病人和他们的家人建立信任关系。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 23,
|
||||
"id": "23",
|
||||
"name": "编辑 - Editor",
|
||||
"emoji": "✒️",
|
||||
"group": "职业",
|
||||
@ -184,7 +184,7 @@
|
||||
"description": "你现在是一名编辑,你对文字有敏锐的感觉,擅长审校和修订稿件以确保其质量。你有出色的语言和沟通技巧,能与作者有效地合作以改善他们的作品。你对出版流程有深入的了解。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 24,
|
||||
"id": "24",
|
||||
"name": "哲学家 - Philosopher",
|
||||
"emoji": "🧠",
|
||||
"group": "职业",
|
||||
@ -192,7 +192,7 @@
|
||||
"description": "你现在是一名哲学家,你对世界的本质和人类存在的意义有深入的思考。你熟悉多种哲学流派,并能从哲学的角度分析和解决问题。你具有深刻的思维和出色的逻辑分析能力。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 25,
|
||||
"id": "25",
|
||||
"name": "采购 - Procurement",
|
||||
"emoji": "🛒",
|
||||
"group": "职业",
|
||||
@ -200,7 +200,7 @@
|
||||
"description": "你现在是一名采购经理,你熟悉供应链管理,擅长进行供应商评估和价格谈判。你负责制定和执行采购策略,以保证货物的质量和供应的稳定。请在这个角色下为我解答以下问题。\n"
|
||||
},
|
||||
{
|
||||
"id": 26,
|
||||
"id": "26",
|
||||
"name": "法务 - Legal Affairs",
|
||||
"emoji": "⚖️",
|
||||
"group": "职业",
|
||||
@ -208,7 +208,7 @@
|
||||
"description": "你现在是一名法务专家,你了解公司法、合同法等相关法律,能为企业提供法律咨询和风险评估。你还擅长处理法律争端,并能起草和审核合同。请在这个角色下为我解答以下问题。"
|
||||
},
|
||||
{
|
||||
"id": 27,
|
||||
"id": "27",
|
||||
"name": "翻译成中文 - Chinese",
|
||||
"emoji": "🇨🇳",
|
||||
"group": "语言",
|
||||
@ -216,7 +216,7 @@
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": 28,
|
||||
"id": "28",
|
||||
"name": "翻译成英文 - English",
|
||||
"emoji": "🌐",
|
||||
"group": "语言",
|
||||
@ -224,7 +224,7 @@
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": 29,
|
||||
"id": "29",
|
||||
"name": "英语单词背诵助手",
|
||||
"emoji": "📕",
|
||||
"group": "语言",
|
||||
@ -232,7 +232,7 @@
|
||||
"description": ""
|
||||
},
|
||||
{
|
||||
"id": 30,
|
||||
"id": "30",
|
||||
"name": "文章总结 - Summarize",
|
||||
"emoji": "📖",
|
||||
"group": "阅读",
|
||||
|
||||
@ -26,7 +26,8 @@ const resources = {
|
||||
you: 'You',
|
||||
save: 'Save',
|
||||
footnotes: 'References',
|
||||
select: 'Select'
|
||||
select: 'Select',
|
||||
search: 'Search'
|
||||
},
|
||||
button: {
|
||||
add: 'Add',
|
||||
@ -80,7 +81,8 @@ const resources = {
|
||||
'settings.reset': 'Reset',
|
||||
'settings.set_as_default': 'Apply to default assistant',
|
||||
'settings.max': 'Max',
|
||||
'suggestions.title': 'Suggested Questions'
|
||||
'suggestions.title': 'Suggested Questions',
|
||||
'add.assistant.title': 'Add Assistant'
|
||||
},
|
||||
agents: {
|
||||
title: 'Agents',
|
||||
@ -93,7 +95,10 @@ const resources = {
|
||||
'add.prompt.placeholder': 'Enter prompt',
|
||||
'add.button': 'Add',
|
||||
'manage.title': 'Manage Agents',
|
||||
'delete.popup.content': 'Are you sure you want to delete this agent?'
|
||||
'delete.popup.content': 'Are you sure you want to delete this agent?',
|
||||
'tag.default': 'Default',
|
||||
'tag.system': 'System',
|
||||
'tag.user': 'Mine'
|
||||
},
|
||||
provider: {
|
||||
openai: 'OpenAI',
|
||||
@ -228,7 +233,8 @@ const resources = {
|
||||
provider: '提供商',
|
||||
you: '用户',
|
||||
footnote: '引用内容',
|
||||
select: '选择'
|
||||
select: '选择',
|
||||
search: '搜索'
|
||||
},
|
||||
button: {
|
||||
add: '添加',
|
||||
@ -283,7 +289,8 @@ const resources = {
|
||||
'settings.reset': '重置',
|
||||
'settings.set_as_default': '应用到默认助手',
|
||||
'settings.max': '不限',
|
||||
'suggestions.title': '建议的问题'
|
||||
'suggestions.title': '建议的问题',
|
||||
'add.assistant.title': '添加智能体'
|
||||
},
|
||||
agents: {
|
||||
title: '智能体',
|
||||
@ -296,7 +303,10 @@ const resources = {
|
||||
'add.prompt.placeholder': '输入提示词',
|
||||
'add.button': '添加',
|
||||
'manage.title': '管理智能体',
|
||||
'delete.popup.content': '确定要删除此智能体吗?'
|
||||
'delete.popup.content': '确定要删除此智能体吗?',
|
||||
'tag.default': '默认',
|
||||
'tag.system': '系统',
|
||||
'tag.user': '我的'
|
||||
},
|
||||
provider: {
|
||||
openai: 'OpenAI',
|
||||
|
||||
@ -4,7 +4,7 @@ import { HStack } from '@renderer/components/Layout'
|
||||
import Agents from '@renderer/config/agents.json'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { getDefaultAssistant } from '@renderer/services/assistant'
|
||||
import { covertAgentToAssistant } from '@renderer/services/assistant'
|
||||
import { Agent } from '@renderer/types'
|
||||
import { Col, Row, Typography } from 'antd'
|
||||
import { find, groupBy } from 'lodash'
|
||||
@ -21,10 +21,7 @@ const { Title } = Typography
|
||||
const AppsPage: FC = () => {
|
||||
const { assistants, addAssistant } = useAssistants()
|
||||
const { agents } = useAgents()
|
||||
const agentGroups = groupBy(
|
||||
Agents.map((a) => ({ ...a, id: String(a.id) })),
|
||||
'group'
|
||||
)
|
||||
const agentGroups = groupBy(Agents, 'group')
|
||||
const { t } = useTranslation()
|
||||
|
||||
const onAddAgentConfirm = (agent: Agent) => {
|
||||
@ -43,12 +40,7 @@ const AppsPage: FC = () => {
|
||||
}
|
||||
|
||||
const onAddAgent = (agent: Agent) => {
|
||||
addAssistant({
|
||||
...getDefaultAssistant(),
|
||||
...agent,
|
||||
name: agent.emoji ? agent.emoji + ' ' + agent.name : agent.name,
|
||||
id: String(agent.id)
|
||||
})
|
||||
addAssistant(covertAgentToAssistant(agent))
|
||||
window.message.success({
|
||||
content: t('message.assistant.added.content'),
|
||||
key: 'agent-added',
|
||||
|
||||
@ -3,6 +3,7 @@ import 'emoji-picker-element'
|
||||
import EmojiPicker from '@renderer/components/EmojiPicker'
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { syncAgentToAssistant } from '@renderer/services/assistant'
|
||||
import { Agent } from '@renderer/types'
|
||||
import { getLeadingEmoji, uuid } from '@renderer/utils'
|
||||
import { Button, Form, FormInstance, Input, Modal, Popover } from 'antd'
|
||||
@ -44,6 +45,7 @@ const PopupContainer: React.FC<Props> = ({ agent, resolve }) => {
|
||||
prompt: values.prompt
|
||||
}
|
||||
updateAgent(_agent)
|
||||
syncAgentToAssistant(_agent)
|
||||
resolve(_agent)
|
||||
setOpen(false)
|
||||
return
|
||||
|
||||
@ -71,7 +71,7 @@ const PopupContainer: React.FC = () => {
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
padding: 16px;
|
||||
padding: 12px 0;
|
||||
height: 50vh;
|
||||
overflow-y: auto;
|
||||
&::-webkit-scrollbar {
|
||||
|
||||
@ -9,6 +9,7 @@ import { Switch } from 'antd'
|
||||
import { FC, useState } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import AddAssistantPopup from './components/AddAssistantPopup'
|
||||
import Assistants from './components/Assistants'
|
||||
import Chat from './components/Chat'
|
||||
import Navigation from './components/NavigationCenter'
|
||||
@ -25,12 +26,17 @@ const HomePage: FC = () => {
|
||||
|
||||
_activeAssistant = activeAssistant
|
||||
|
||||
const onCreateAssistant = () => {
|
||||
const onCreateDefaultAssistant = () => {
|
||||
const assistant = { ...defaultAssistant, id: uuid() }
|
||||
addAssistant(assistant)
|
||||
setActiveAssistant(assistant)
|
||||
}
|
||||
|
||||
const onCreateAssistant = async () => {
|
||||
const assistant = await AddAssistantPopup.show()
|
||||
assistant && setActiveAssistant(assistant)
|
||||
}
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Navbar>
|
||||
@ -62,7 +68,7 @@ const HomePage: FC = () => {
|
||||
<Assistants
|
||||
activeAssistant={activeAssistant}
|
||||
setActiveAssistant={setActiveAssistant}
|
||||
onCreateAssistant={onCreateAssistant}
|
||||
onCreateAssistant={onCreateDefaultAssistant}
|
||||
/>
|
||||
)}
|
||||
<Chat assistant={activeAssistant} />
|
||||
|
||||
127
src/renderer/src/pages/home/components/AddAssistantPopup.tsx
Normal file
127
src/renderer/src/pages/home/components/AddAssistantPopup.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
import { TopView } from '@renderer/components/TopView'
|
||||
import systemAgents from '@renderer/config/agents.json'
|
||||
import { useAgents } from '@renderer/hooks/useAgents'
|
||||
import { useAssistants, useDefaultAssistant } from '@renderer/hooks/useAssistant'
|
||||
import { covertAgentToAssistant } from '@renderer/services/assistant'
|
||||
import { Agent, Assistant } from '@renderer/types'
|
||||
import { Input, Modal, Tag } from 'antd'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
interface Props {
|
||||
resolve: (value: Assistant | undefined) => void
|
||||
}
|
||||
|
||||
const PopupContainer: React.FC<Props> = ({ resolve }) => {
|
||||
const [open, setOpen] = useState(true)
|
||||
const { t } = useTranslation()
|
||||
const { agents: userAgents } = useAgents()
|
||||
const [searchText, setSearchText] = useState('')
|
||||
const { defaultAssistant } = useDefaultAssistant()
|
||||
const { assistants, addAssistant } = useAssistants()
|
||||
|
||||
const defaultAgent: Agent = useMemo(
|
||||
() => ({
|
||||
id: defaultAssistant.id,
|
||||
name: defaultAssistant.name,
|
||||
emoji: '',
|
||||
prompt: defaultAssistant.prompt,
|
||||
group: 'system'
|
||||
}),
|
||||
[defaultAssistant.id, defaultAssistant.name, defaultAssistant.prompt]
|
||||
)
|
||||
|
||||
const agents = useMemo(() => {
|
||||
const allAgents = [defaultAgent, ...userAgents, ...systemAgents] as Agent[]
|
||||
const list = allAgents.filter((agent) => !assistants.map((a) => a.id).includes(agent.id))
|
||||
return searchText ? list.filter((agent) => agent.name.includes(searchText)) : list
|
||||
}, [assistants, defaultAgent, searchText, userAgents])
|
||||
|
||||
const onCreateAssistant = (agent: Agent) => {
|
||||
if (assistants.map((a) => a.id).includes(String(agent.id))) return
|
||||
const assistant = covertAgentToAssistant(agent)
|
||||
addAssistant(assistant)
|
||||
resolve(assistant)
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const onCancel = () => {
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const onClose = async () => {
|
||||
resolve(undefined)
|
||||
AddAssistantPopup.hide()
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
style={{ marginTop: '5vh' }}
|
||||
title={t('chat.add.assistant.title')}
|
||||
open={open}
|
||||
onCancel={onCancel}
|
||||
afterClose={onClose}
|
||||
transitionName=""
|
||||
maskTransitionName=""
|
||||
footer={null}>
|
||||
<Input
|
||||
placeholder={t('common.search')}
|
||||
value={searchText}
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
allowClear
|
||||
autoFocus
|
||||
style={{ marginBottom: 16 }}
|
||||
/>
|
||||
<Container>
|
||||
{agents.map((agent) => (
|
||||
<AgentItem key={agent.id} onClick={() => onCreateAssistant(agent)}>
|
||||
{agent.emoji} {agent.name}
|
||||
{agent.group === 'system' && <Tag color="orange">{t('agents.tag.system')}</Tag>}
|
||||
{agent.group === 'user' && <Tag color="green">{t('agents.tag.user')}</Tag>}
|
||||
</AgentItem>
|
||||
))}
|
||||
</Container>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
const Container = styled.div`
|
||||
height: 50vh;
|
||||
overflow-y: auto;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
|
||||
const AgentItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px;
|
||||
border-radius: 8px;
|
||||
user-select: none;
|
||||
background-color: var(--color-background-soft);
|
||||
margin-bottom: 8px;
|
||||
cursor: pointer;
|
||||
.anticon {
|
||||
font-size: 16px;
|
||||
color: var(--color-icon);
|
||||
}
|
||||
&:hover {
|
||||
background-color: var(--color-background-mute);
|
||||
}
|
||||
`
|
||||
|
||||
export default class AddAssistantPopup {
|
||||
static topviewId = 0
|
||||
static hide() {
|
||||
TopView.hide('AddAssistantPopup')
|
||||
}
|
||||
static show() {
|
||||
return new Promise<Assistant | undefined>((resolve) => {
|
||||
TopView.show(<PopupContainer resolve={resolve} />, 'AddAssistantPopup')
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ import { CopyOutlined, DeleteOutlined, EditOutlined } from '@ant-design/icons'
|
||||
import { DragDropContext, Draggable, Droppable, DropResult } from '@hello-pangea/dnd'
|
||||
import AssistantSettingPopup from '@renderer/components/Popups/AssistantSettingPopup'
|
||||
import { useAssistant, useAssistants } from '@renderer/hooks/useAssistant'
|
||||
import { getDefaultTopic } from '@renderer/services/assistant'
|
||||
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'
|
||||
@ -45,6 +45,7 @@ const Assistants: FC<Props> = ({ activeAssistant, setActiveAssistant, onCreateAs
|
||||
async onClick() {
|
||||
const _assistant = await AssistantSettingPopup.show({ assistant })
|
||||
updateAssistant(_assistant)
|
||||
syncAsistantToAgent(_assistant)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import i18n from '@renderer/i18n'
|
||||
import store from '@renderer/store'
|
||||
import { Assistant, Model, Provider, Topic } from '@renderer/types'
|
||||
import { uuid } from '@renderer/utils'
|
||||
import { updateAgent } from '@renderer/store/agents'
|
||||
import { updateAssistant } from '@renderer/store/assistants'
|
||||
import { Agent, Assistant, Model, Provider, Topic } from '@renderer/types'
|
||||
import { getLeadingEmoji, removeLeadingEmoji, uuid } from '@renderer/utils'
|
||||
|
||||
export function getDefaultAssistant(): Assistant {
|
||||
return {
|
||||
@ -53,3 +55,47 @@ export function getProviderByModelId(modelId?: string) {
|
||||
const _modelId = modelId || getDefaultModel().id
|
||||
return providers.find((p) => p.models.find((m) => m.id === _modelId)) as Provider
|
||||
}
|
||||
|
||||
export function covertAgentToAssistant(agent: Agent): Assistant {
|
||||
return {
|
||||
...getDefaultAssistant(),
|
||||
...agent,
|
||||
name: getAssistantNameWithAgent(agent),
|
||||
id: agent.group === 'system' ? uuid() : String(agent.id)
|
||||
}
|
||||
}
|
||||
|
||||
export function getAssistantNameWithAgent(agent: Agent) {
|
||||
return agent.emoji ? agent.emoji + ' ' + agent.name : agent.name
|
||||
}
|
||||
|
||||
export function syncAsistantToAgent(assistant: Assistant) {
|
||||
const agents = store.getState().agents.agents
|
||||
const agent = agents.find((a) => a.id === assistant.id)
|
||||
|
||||
if (agent) {
|
||||
store.dispatch(
|
||||
updateAgent({
|
||||
...agent,
|
||||
emoji: getLeadingEmoji(assistant.name),
|
||||
name: removeLeadingEmoji(assistant.name),
|
||||
prompt: assistant.prompt
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function syncAgentToAssistant(agent: Agent) {
|
||||
const assistants = store.getState().assistants.assistants
|
||||
const assistant = assistants.find((a) => a.id === agent.id)
|
||||
|
||||
if (assistant) {
|
||||
store.dispatch(
|
||||
updateAssistant({
|
||||
...assistant,
|
||||
name: getAssistantNameWithAgent(agent),
|
||||
prompt: agent.prompt
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ export function firstLetter(str: string): string {
|
||||
|
||||
export function removeLeadingEmoji(str: string): string {
|
||||
const emojiRegex = /^(\p{Emoji_Presentation}|\p{Emoji}\uFE0F)+/u
|
||||
return str.replace(emojiRegex, '')
|
||||
return str.replace(emojiRegex, '').trim()
|
||||
}
|
||||
|
||||
export function getLeadingEmoji(str: string): string {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user