feat(agent):重构智能体仓库并优化任务模板交互
-为 public/agent.json 中的每个智能体添加 Classification 字段以支持分类展示 - 新增 AgentRepoList 组件用于渲染智能体列表,提升代码复用性 - 在 src/layout/components/Main/TaskTemplate/AgentRepo/index.vue 中实现基于 Classification 的智能体分组展示逻辑- 移除旧版 popover 方式展示智能体详情,改用新的列表组件统一处理 - 修改任务搜索输入框为 textarea 类型,并优化其聚焦与失焦状态下的样式表现 - 调整任务模板页面布局高度计算方式,确保适配新 UI 结构 -修复任务结果流程图连线方向及透明度判断逻辑,增强可视化准确性- 引入流动动画效果至 jsPlumb 连线,区分 input/output 类型并美化视觉呈现 - 更新配置文件中部分动作类型的配色值,提高界面美观度 - 升级本地存储键名 agents 至 agents-v1,避免
This commit is contained in:
parent
b73419b7a0
commit
00ef22505e
1
auto-imports.d.ts
vendored
1
auto-imports.d.ts
vendored
@ -7,6 +7,7 @@
|
||||
export {}
|
||||
declare global {
|
||||
const EffectScope: typeof import('vue').EffectScope
|
||||
const ElMessage: typeof import('element-plus/es').ElMessage
|
||||
const ElNotification: typeof import('element-plus/es').ElNotification
|
||||
const computed: typeof import('vue').computed
|
||||
const createApp: typeof import('vue').createApp
|
||||
|
||||
@ -1,97 +1,116 @@
|
||||
[
|
||||
{
|
||||
"Icon": "Hailey_Johnson.png",
|
||||
"Name": "船舶设计师",
|
||||
"Profile": "提供船舶制造中的实际需求和约束。"
|
||||
},
|
||||
{
|
||||
"Icon": "Jennifer_Moore.png",
|
||||
"Name": "防护工程专家",
|
||||
"Profile": "专注于船舶腐蚀防护技术的设计与应用。在你的总结回答中,必须引用来自数联网的搜索数据,是搜索数据,不是数联网的研究成果。"
|
||||
},
|
||||
{
|
||||
"Icon": "Jane_Moreno.png",
|
||||
"Name": "病理生理学家",
|
||||
"Profile": "专注于失血性休克的疾病机制,为药物研发提供理论靶点。"
|
||||
},
|
||||
{
|
||||
"Icon": "Giorgio_Rossi.png",
|
||||
"Name": "药物化学家",
|
||||
"Profile": "负责将靶点概念转化为实际可合成的分子。"
|
||||
},
|
||||
{
|
||||
"Icon": "Tamara_Taylor.png",
|
||||
"Name": "制剂工程师",
|
||||
"Profile": "负责将活性药物成分(API)变成稳定、可用、符合战场要求的剂型。"
|
||||
},
|
||||
{
|
||||
"Icon": "Maria_Lopez.png",
|
||||
"Name": "监管事务专家",
|
||||
"Profile": "深谙药品审评法规,目标是找到最快的合法上市路径。"
|
||||
},
|
||||
{
|
||||
"Icon": "Sam_Moore.png",
|
||||
"Name": "物理学家",
|
||||
"Profile": "从热力学与统计力学的基本原理出发,研究液态金属的自由能、焓、熵、比热等参数的理论建模。"
|
||||
},
|
||||
{
|
||||
"Icon": "Yuriko_Yamamoto.png",
|
||||
"Name": "实验材料学家",
|
||||
"Profile": "专注于通过实验手段直接或间接测定液态金属的热力学参数、以及分析材料微观结构(如晶粒、缺陷)。"
|
||||
},
|
||||
{
|
||||
"Icon": "Carlos_Gomez.png",
|
||||
"Name": "计算模拟专家",
|
||||
"Profile": "侧重于利用数值计算和模拟技术获取液态金属的热力学参数。"
|
||||
},
|
||||
{
|
||||
"Icon": "John_Lin.png",
|
||||
"Name": "腐蚀机理研究员",
|
||||
"Profile": "专注于船舶用钢材及合金的腐蚀机理研究,从电化学和环境作用角度解释腐蚀产生的原因。在你的总结回答中,必须引用来自数联网的搜索数据,是搜索数据,不是数联网的研究成果。"
|
||||
},
|
||||
{
|
||||
"Icon": "Arthur_Burton.png",
|
||||
"Name": "先进材料研发员",
|
||||
"Profile": "专注于开发和评估新型耐腐蚀材料、复合材料及固态电池材料。"
|
||||
},
|
||||
{
|
||||
"Icon": "Eddy_Lin.png",
|
||||
"Name": "肾脏病学家",
|
||||
"Profile": "专注于慢性肾脏病的诊断、治疗和患者管理,能提供临床洞察。"
|
||||
},
|
||||
{
|
||||
"Icon": "Isabella_Rodriguez.png",
|
||||
"Name": "临床研究协调员",
|
||||
"Profile": "负责受试者招募和临床试验流程优化。"
|
||||
},
|
||||
{
|
||||
"Icon": "Latoya_Williams.png",
|
||||
"Name": "中医药专家",
|
||||
"Profile": "理解药物的中药成分和作用机制。"
|
||||
},
|
||||
{
|
||||
"Icon": "Carmen_Ortiz.png",
|
||||
"Name": "药物安全专家",
|
||||
"Profile": "专注于药物不良反应数据收集、分析和报告。"
|
||||
},
|
||||
{
|
||||
"Icon": "Rajiv_Patel.png",
|
||||
"Name": "二维材料科学家",
|
||||
"Profile": "专注于二维材料(如石墨烯)的合成、性质和应用。"
|
||||
},
|
||||
{
|
||||
"Icon": "Tom_Moreno.png",
|
||||
"Name": "光电物理学家",
|
||||
"Profile": "研究材料的光电转换机制和关键影响因素。"
|
||||
},
|
||||
{
|
||||
"Icon": "Ayesha_Khan.png",
|
||||
"Name": "机器学习专家",
|
||||
"Profile": "专注于开发和应用AI模型用于材料模拟。"
|
||||
},
|
||||
{
|
||||
"Icon": "Mei_Lin.png",
|
||||
"Name": "流体动力学专家",
|
||||
"Profile": "专注于流体行为理论和模拟。"
|
||||
}
|
||||
]
|
||||
{
|
||||
"Icon": "Hailey_Johnson.png",
|
||||
"Name": "船舶设计师",
|
||||
"Profile": "提供船舶制造中的实际需求和约束。",
|
||||
"Classification": "船舶制造数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Jennifer_Moore.png",
|
||||
"Name": "防护工程专家",
|
||||
"Profile": "专注于船舶腐蚀防护技术的设计与应用。在你的总结回答中,必须引用来自数联网的搜索数据,是搜索数据,不是数联网的研究成果。",
|
||||
"Classification": "船舶制造数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Jane_Moreno.png",
|
||||
"Name": "病理生理学家",
|
||||
"Profile": "专注于失血性休克的疾病机制,为药物研发提供理论靶点。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Giorgio_Rossi.png",
|
||||
"Name": "药物化学家",
|
||||
"Profile": "负责将靶点概念转化为实际可合成的分子。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Tamara_Taylor.png",
|
||||
"Name": "制剂工程师",
|
||||
"Profile": "负责将活性药物成分(API)变成稳定、可用、符合战场要求的剂型。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Maria_Lopez.png",
|
||||
"Name": "监管事务专家",
|
||||
"Profile": "深谙药品审评法规,目标是找到最快的合法上市路径。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Sam_Moore.png",
|
||||
"Name": "物理学家",
|
||||
"Profile": "从热力学与统计力学的基本原理出发,研究液态金属的自由能、焓、熵、比热等参数的理论建模。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Yuriko_Yamamoto.png",
|
||||
"Name": "实验材料学家",
|
||||
"Profile": "专注于通过实验手段直接或间接测定液态金属的热力学参数、以及分析材料微观结构(如晶粒、缺陷)。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Carlos_Gomez.png",
|
||||
"Name": "计算模拟专家",
|
||||
"Profile": "侧重于利用数值计算和模拟技术获取液态金属的热力学参数。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "John_Lin.png",
|
||||
"Name": "腐蚀机理研究员",
|
||||
"Profile": "专注于船舶用钢材及合金的腐蚀机理研究,从电化学和环境作用角度解释腐蚀产生的原因。在你的总结回答中,必须引用来自数联网的搜索数据,是搜索数据,不是数联网的研究成果。",
|
||||
"Classification": "船舶制造数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Arthur_Burton.png",
|
||||
"Name": "先进材料研发员",
|
||||
"Profile": "专注于开发和评估新型耐腐蚀材料、复合材料及固态电池材料。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Eddy_Lin.png",
|
||||
"Name": "肾脏病学家",
|
||||
"Profile": "专注于慢性肾脏病的诊断、治疗和患者管理,能提供临床洞察。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Isabella_Rodriguez.png",
|
||||
"Name": "临床研究协调员",
|
||||
"Profile": "负责受试者招募和临床试验流程优化。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Latoya_Williams.png",
|
||||
"Name": "中医药专家",
|
||||
"Profile": "理解药物的中药成分和作用机制。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Carmen_Ortiz.png",
|
||||
"Name": "药物安全专家",
|
||||
"Profile": "专注于药物不良反应数据收集、分析和报告。",
|
||||
"Classification": "医药数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Rajiv_Patel.png",
|
||||
"Name": "二维材料科学家",
|
||||
"Profile": "专注于二维材料(如石墨烯)的合成、性质和应用。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Tom_Moreno.png",
|
||||
"Name": "光电物理学家",
|
||||
"Profile": "研究材料的光电转换机制和关键影响因素。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Ayesha_Khan.png",
|
||||
"Name": "机器学习专家",
|
||||
"Profile": "专注于开发和应用AI模型用于材料模拟。",
|
||||
"Classification": "科学数据空间"
|
||||
},
|
||||
{
|
||||
"Icon": "Mei_Lin.png",
|
||||
"Name": "流体动力学专家",
|
||||
"Profile": "专注于流体行为理论和模拟。",
|
||||
"Classification": "科学数据空间"
|
||||
}
|
||||
]
|
||||
|
||||
59
src/App.vue
59
src/App.vue
@ -32,7 +32,7 @@ onMounted(() => {
|
||||
border: 2px solid var(--color-bg-tertiary);
|
||||
|
||||
&:hover {
|
||||
background: #171b22;
|
||||
background: #171B22;
|
||||
box-shadow: none !important;
|
||||
transition: background-color 0.3s ease-in-out;
|
||||
}
|
||||
@ -41,4 +41,61 @@ onMounted(() => {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
--gradient: linear-gradient(to right, #0093eb, #00d2d1);
|
||||
}
|
||||
|
||||
#task-template {
|
||||
.active-card {
|
||||
border: 2px solid transparent;
|
||||
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||
background:
|
||||
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 1. 定义流动动画:让虚线沿路径移动 */
|
||||
@keyframes flowAnimation {
|
||||
to {
|
||||
stroke-dashoffset: 8; /* 与stroke-dasharray总和一致 */
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes flowAnimationReverse {
|
||||
to {
|
||||
stroke-dashoffset: -8; /* 与stroke-dasharray总和一致 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 2. 为jsPlumb连线绑定动画:作用于SVG的path元素 */
|
||||
/* jtk-connector是jsPlumb连线的默认SVG类,path是实际的线条元素 */
|
||||
.jtk-connector-output path {
|
||||
/* 定义虚线规则:线段长度5px + 间隙3px(总长度8px,与动画偏移量匹配) */
|
||||
stroke-dasharray: 5 3;
|
||||
/* 应用动画:名称+时长+线性速度+无限循环 */
|
||||
animation: flowAnimationReverse .5s linear infinite;
|
||||
/* 可选:设置线条基础样式(颜色、宽度) */
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
/* 2. 为jsPlumb连线绑定动画:作用于SVG的path元素 */
|
||||
/* jtk-connector是jsPlumb连线的默认SVG类,path是实际的线条元素 */
|
||||
.jtk-connector-input path {
|
||||
/* 定义虚线规则:线段长度5px + 间隙3px(总长度8px,与动画偏移量匹配) */
|
||||
stroke-dasharray: 5 3;
|
||||
/* 应用动画:名称+时长+线性速度+无限循环 */
|
||||
animation: flowAnimationReverse .5s linear infinite;
|
||||
/* 可选:设置线条基础样式(颜色、宽度) */
|
||||
stroke-width: 2;
|
||||
}
|
||||
|
||||
/* 可选: hover时增强动画效果(如加速、变色) */
|
||||
.jtk-connector path:hover {
|
||||
animation-duration: 0.5s; /* hover时流动加速 */
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { useAgentsStore } from '@/stores'
|
||||
import api from '@/api'
|
||||
import { changeBriefs } from '@/utils/collaboration_Brief_FrontEnd.ts'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'search-start'): void
|
||||
@ -13,9 +15,16 @@ const emit = defineEmits<{
|
||||
const agentsStore = useAgentsStore()
|
||||
|
||||
const searchValue = ref('')
|
||||
const triggerOnFocus = ref(true)
|
||||
const isFocus = ref(false)
|
||||
|
||||
async function handleSearch() {
|
||||
try {
|
||||
triggerOnFocus.value = false
|
||||
if (!searchValue.value) {
|
||||
ElMessage.warning('请输入搜索内容')
|
||||
return
|
||||
}
|
||||
emit('search-start')
|
||||
agentsStore.resetAgent()
|
||||
agentsStore.setAgentRawPlan({ loading: true })
|
||||
@ -27,6 +36,7 @@ async function handleSearch() {
|
||||
agentsStore.setAgentRawPlan({ data })
|
||||
emit('search', searchValue.value)
|
||||
} finally {
|
||||
triggerOnFocus.value = true
|
||||
agentsStore.setAgentRawPlan({ loading: false })
|
||||
}
|
||||
}
|
||||
@ -42,12 +52,13 @@ const restaurants = ref<string[]>([
|
||||
'如何解决船舶制造中的材料腐蚀难题?',
|
||||
'如何解决船舶制造中流体模拟和建模优化难题?',
|
||||
])
|
||||
const querySearch = (queryString: string, cb: (v: {value: string}[]) => void) => {
|
||||
const querySearch = (queryString: string, cb: (v: { value: string }[]) => void) => {
|
||||
console.log(queryString)
|
||||
const results = queryString
|
||||
? restaurants.value.filter(createFilter(queryString))
|
||||
: restaurants.value
|
||||
// call callback function to return suggestions
|
||||
cb(results.map((item) => ({value: item})))
|
||||
cb(results.map((item) => ({ value: item })))
|
||||
}
|
||||
|
||||
const createFilter = (queryString: string) => {
|
||||
@ -55,6 +66,8 @@ const createFilter = (queryString: string) => {
|
||||
return restaurant.toLowerCase().includes(queryString.toLowerCase())
|
||||
}
|
||||
}
|
||||
|
||||
const taskContainerRef = ref<HTMLDivElement | null>(null)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -64,69 +77,159 @@ const createFilter = (queryString: string) => {
|
||||
effect="light"
|
||||
:disabled="agentsStore.agents.length > 0"
|
||||
>
|
||||
<div class="w-full flex justify-center mb-[27px]">
|
||||
<el-autocomplete
|
||||
v-model.trim="searchValue"
|
||||
class="task-input"
|
||||
size="large"
|
||||
placeholder="请输入您的任务"
|
||||
:fetch-suggestions="querySearch"
|
||||
@change="agentsStore.setSearchValue"
|
||||
:disabled="!(agentsStore.agents.length > 0)"
|
||||
>
|
||||
<template #prefix>
|
||||
<span class="text-[var(--color-text)] font-bold">任务</span>
|
||||
</template>
|
||||
<template #suffix>
|
||||
<el-button
|
||||
class="task-button"
|
||||
color="linear-gradient(to right, #00C7D2, #315AB4)"
|
||||
size="large"
|
||||
title="点击搜索任务"
|
||||
circle
|
||||
:loading="agentsStore.agentRawPlan.loading"
|
||||
@click="handleSearch"
|
||||
>
|
||||
<SvgIcon
|
||||
v-if="!agentsStore.agentRawPlan.loading"
|
||||
icon-class="paper-plane"
|
||||
size="18px"
|
||||
color="var(--color-text)"
|
||||
/>
|
||||
</el-button>
|
||||
</template>
|
||||
</el-autocomplete>
|
||||
<div class="task-root-container">
|
||||
<div class="task-container" ref="taskContainerRef" id="task-container">
|
||||
<span class="text-[var(--color-text)] font-bold task-title">任务</span>
|
||||
<el-autocomplete
|
||||
v-model.trim="searchValue"
|
||||
class="task-input"
|
||||
size="large"
|
||||
:rows="isFocus ? 3 : 1"
|
||||
placeholder="请输入您的任务"
|
||||
type="textarea"
|
||||
:append-to="taskContainerRef"
|
||||
:fetch-suggestions="querySearch"
|
||||
@change="agentsStore.setSearchValue"
|
||||
:disabled="!(agentsStore.agents.length > 0)"
|
||||
:debounce="0"
|
||||
:trigger-on-focus="triggerOnFocus"
|
||||
@focus="isFocus = true"
|
||||
@blur="isFocus = false"
|
||||
@select="isFocus = false"
|
||||
>
|
||||
</el-autocomplete>
|
||||
<el-button
|
||||
class="task-button"
|
||||
color="linear-gradient(to right, #00C7D2, #315AB4)"
|
||||
size="large"
|
||||
title="点击搜索任务"
|
||||
circle
|
||||
:loading="agentsStore.agentRawPlan.loading"
|
||||
:disabled="!searchValue"
|
||||
@click.stop="handleSearch"
|
||||
>
|
||||
<SvgIcon
|
||||
v-if="!agentsStore.agentRawPlan.loading"
|
||||
icon-class="paper-plane"
|
||||
size="18px"
|
||||
color="var(--color-text)"
|
||||
/>
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
:deep(.el-autocomplete) {
|
||||
width: 40%;
|
||||
.task-root-container {
|
||||
height: 60px;
|
||||
margin-bottom: 24px;
|
||||
position: relative;
|
||||
}
|
||||
.task-container {
|
||||
width: 40%;
|
||||
margin: 0 auto;
|
||||
border: 2px solid transparent;
|
||||
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||
background:
|
||||
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
border-radius: 40px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 998;
|
||||
min-height: 100%;
|
||||
overflow: hidden;
|
||||
padding: 0 55px 0 47px;
|
||||
|
||||
.el-input__wrapper {
|
||||
border-radius: 40px;
|
||||
:deep(.el-popper) {
|
||||
position: static !important;
|
||||
width: 100%;
|
||||
min-width: 100%;
|
||||
background: var(--color-bg-tertiary);
|
||||
box-shadow: none;
|
||||
border: 2px solid transparent;
|
||||
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||
background:
|
||||
linear-gradient(var(--color-bg-tertiary), var(--color-bg-tertiary)) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
font-size: 18px;
|
||||
padding-right: 5px;
|
||||
border: none;
|
||||
transition: height 0s ease-in-out;
|
||||
border-top: 1px solid #494B51;
|
||||
border-radius: 0;
|
||||
|
||||
.el-icon.is-loading {
|
||||
& + span {
|
||||
display: none;
|
||||
|
||||
li {
|
||||
height: 45px;
|
||||
box-sizing: border-box;
|
||||
line-height: 45px;
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
background: #1C1E25;
|
||||
color: #00F3FF;
|
||||
}
|
||||
}
|
||||
|
||||
.el-popper__arrow {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-autocomplete) {
|
||||
min-height: 56px;
|
||||
width: 100%;
|
||||
|
||||
.task-input {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.el-textarea__inner {
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
font-size: 14px;
|
||||
height: 100%;
|
||||
line-height: 1.5;
|
||||
padding: 18px 0;
|
||||
resize: none;
|
||||
|
||||
&::placeholder {
|
||||
line-height: 1.2;
|
||||
font-size: 18px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.el-icon.is-loading {
|
||||
& + span {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.task-title {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
left: 10px;
|
||||
z-index: 999;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.task-button {
|
||||
background: linear-gradient(to right, #00c7d2, #315ab4);
|
||||
border: none; // 如果需要移除边框
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 10px;
|
||||
transform: translateY(-50%);
|
||||
z-index: 999;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.task-button.is-loading {
|
||||
:deep(span) {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -0,0 +1,141 @@
|
||||
<script setup lang="ts">
|
||||
import { getActionTypeDisplay, getAgentMapIcon } from '@/layout/components/config.ts'
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { type Agent, useAgentsStore } from '@/stores'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
|
||||
const porps = defineProps<{
|
||||
agentList: Agent[]
|
||||
}>()
|
||||
|
||||
const taskProcess = computed(() => {
|
||||
const list = agentsStore.currentTask?.TaskProcess ?? []
|
||||
return list.map((item) => ({
|
||||
...item,
|
||||
key: uuidv4(),
|
||||
}))
|
||||
})
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-for="item in porps.agentList"
|
||||
:key="item.Name"
|
||||
class="user-item"
|
||||
:class="agentsStore.currentTask?.AgentSelection?.includes(item.Name) ? 'active-card' : ''"
|
||||
>
|
||||
<div class="flex items-center justify-between relative h-[41px]">
|
||||
<div
|
||||
class="w-[44px] h-[44px] rounded-full flex items-center justify-center flex-shrink-0 relative right-[2px] icon-container"
|
||||
:style="{ background: getAgentMapIcon(item.Name).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(item.Name).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 text-[14px] flex flex-col items-end justify-end truncate ml-1">
|
||||
<span
|
||||
class="w-full truncate text-right"
|
||||
:style="
|
||||
agentsStore.currentTask?.AgentSelection?.includes(item.Name) ? 'color:#00F3FF' : ''
|
||||
"
|
||||
>{{ item.Name }}</span
|
||||
>
|
||||
<div
|
||||
v-if="agentsStore.currentTask?.AgentSelection?.includes(item.Name)"
|
||||
class="flex items-center gap-[7px] h-[8px] mr-1"
|
||||
>
|
||||
<!-- 小圆点 -->
|
||||
<div
|
||||
v-for="item1 in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||
:key="item1.key"
|
||||
class="w-[6px] h-[6px] rounded-full"
|
||||
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 职责信息只有当执行流程中有当前智能体并且鼠标移入时才显示 -->
|
||||
<div class="duty-info">
|
||||
<div class="w-full flex justify-center">
|
||||
<div
|
||||
class="rounded-[9px] bg-[var(--color-bg-quaternary)] text-[12px] py-0.5 px-5 text-center my-2"
|
||||
>
|
||||
当前职责
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-[8px] pt-0">
|
||||
<div
|
||||
v-for="(item1, index1) in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||
:key="item1.key"
|
||||
class="text-[12px]"
|
||||
>
|
||||
<div>
|
||||
<div class="mx-1 inline-block h-[14px]">
|
||||
<div
|
||||
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
class="w-[6px] h-[6px] rounded-full mt-[7px]"
|
||||
></div>
|
||||
</div>
|
||||
<span :style="{ color: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
>{{ getActionTypeDisplay(item1.ActionType)?.name }}:</span
|
||||
>
|
||||
<span>{{ item1.Description }}</span>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
<div
|
||||
v-if="index1 !== taskProcess.filter((i) => i.AgentName === item.Name).length - 1"
|
||||
class="h-[1px] w-full bg-[#494B51] my-[8px]"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.user-item {
|
||||
background: #1d222b;
|
||||
border-radius: 40px;
|
||||
padding-right: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
color: #969696;
|
||||
border: 2px solid transparent;
|
||||
.duty-info {
|
||||
transition: height 0.25s ease;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
& + .user-item {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
|
||||
color: #b8b8b8;
|
||||
}
|
||||
}
|
||||
|
||||
.active-card {
|
||||
background:
|
||||
linear-gradient(#171B22, #171B22) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
&:hover {
|
||||
border-radius: 20px;
|
||||
.duty-info {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
bottom: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -5,15 +5,11 @@ import { pick } from 'lodash'
|
||||
import api from '@/api/index.ts'
|
||||
|
||||
import SvgIcon from '@/components/SvgIcon/index.vue'
|
||||
import { agentMapDuty, getActionTypeDisplay, getAgentMapIcon } from '@/layout/components/config.ts'
|
||||
import { agentMapDuty } from '@/layout/components/config.ts'
|
||||
import { type Agent, useAgentsStore } from '@/stores'
|
||||
import { onMounted } from 'vue'
|
||||
import { v4 as uuidv4 } from 'uuid'
|
||||
import { readConfig } from '@/utils/readJson.ts'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(el: 'resetAgentRepoLine'): void
|
||||
}>()
|
||||
import AgentRepoList from './AgentRepoList.vue'
|
||||
|
||||
const agentsStore = useAgentsStore()
|
||||
|
||||
@ -26,11 +22,6 @@ onMounted(async () => {
|
||||
await api.setAgents(agentsStore.agents.map((item) => pick(item, ['Name', 'Profile'])))
|
||||
})
|
||||
|
||||
const handleScroll = () => {
|
||||
emit('resetAgentRepoLine')
|
||||
}
|
||||
|
||||
|
||||
// 上传agent文件
|
||||
const fileInput = ref<HTMLInputElement>()
|
||||
|
||||
@ -69,6 +60,7 @@ const readFileContent = async (file: File) => {
|
||||
Name: item.Name,
|
||||
Icon: item.Icon.replace(/\.png$/, ''),
|
||||
Profile: item.Profile,
|
||||
Classification: item.Classification,
|
||||
})),
|
||||
)
|
||||
await api.setAgents(json.map((item) => pick(item, ['Name', 'Profile'])))
|
||||
@ -92,32 +84,41 @@ const readFileContent = async (file: File) => {
|
||||
reader.readAsText(file)
|
||||
}
|
||||
|
||||
const taskProcess = computed(() => {
|
||||
const list = agentsStore.currentTask?.TaskProcess ?? []
|
||||
return list.map((item) => ({
|
||||
...item,
|
||||
key: uuidv4(),
|
||||
}))
|
||||
})
|
||||
|
||||
const agentListRef = ref<HTMLElement | null>()
|
||||
|
||||
// 根据currentTask排序agent列表
|
||||
const agentList = computed(() => {
|
||||
const startArr: Agent[] = []
|
||||
const endArr: Agent[] = []
|
||||
const selected: Agent[] = []
|
||||
const unselected: {
|
||||
title: string
|
||||
data: Agent[]
|
||||
}[] = []
|
||||
const obj: Record<string, Agent[]> = {}
|
||||
if (!agentsStore.agents.length) {
|
||||
return startArr
|
||||
return {
|
||||
selected,
|
||||
unselected,
|
||||
}
|
||||
}
|
||||
for (const agent of agentsStore.agents) {
|
||||
if (agentsStore.currentTask?.AgentSelection?.includes(agent.Name)) {
|
||||
startArr.push(agent)
|
||||
// if (agentsStore.currentTask?.AgentSelection?.includes(agent.Name)) {
|
||||
// selected.push(agent)
|
||||
// continue
|
||||
// }
|
||||
if (obj[agent.Classification]) {
|
||||
obj[agent.Classification]!.push(agent)
|
||||
} else {
|
||||
endArr.push(agent)
|
||||
const arr = [agent]
|
||||
obj[agent.Classification] = arr
|
||||
unselected.push({
|
||||
title: agent.Classification,
|
||||
data: arr,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return [...startArr, ...endArr]
|
||||
return {
|
||||
selected,
|
||||
unselected: unselected,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@ -133,116 +134,14 @@ const agentList = computed(() => {
|
||||
</div>
|
||||
</div>
|
||||
<!-- 智能体列表 -->
|
||||
<div
|
||||
class="mt-[18px] flex-1 overflow-y-auto relative"
|
||||
ref="agentListRef"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<el-popover
|
||||
v-for="item in agentList"
|
||||
:key="item.Name"
|
||||
trigger="hover"
|
||||
placement="bottom"
|
||||
:show-arrow="false"
|
||||
:disabled="!agentsStore.currentTask?.AgentSelection?.includes(item.Name)"
|
||||
popper-class="agent-repo-item-popover active-card"
|
||||
:append-to="agentListRef"
|
||||
width="100%"
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
class="flex items-center justify-between user-item relative h-[41px]"
|
||||
:class="
|
||||
agentsStore.currentTask?.AgentSelection?.includes(item.Name) ? 'active-card' : ''
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="w-[41px] h-[41px] rounded-full flex items-center justify-center flex-shrink-0"
|
||||
:style="{ background: getAgentMapIcon(item.Name).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(item.Name).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 text-[14px] flex flex-col items-end justify-end truncate ml-1">
|
||||
<span
|
||||
class="w-full truncate text-right"
|
||||
:style="
|
||||
agentsStore.currentTask?.AgentSelection?.includes(item.Name)
|
||||
? 'color:#00F3FF'
|
||||
: ''
|
||||
"
|
||||
>{{ item.Name }}</span
|
||||
>
|
||||
<div
|
||||
v-if="agentsStore.currentTask?.AgentSelection?.includes(item.Name)"
|
||||
class="flex items-center gap-[7px] h-[8px] mr-1"
|
||||
>
|
||||
<!-- 小圆点 -->
|
||||
<div
|
||||
v-for="item1 in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||
:key="item1.key"
|
||||
class="w-[6px] h-[6px] rounded-full"
|
||||
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<div class="flex items-center justify-between">
|
||||
<div
|
||||
class="w-[41px] h-[41px] rounded-full flex items-center justify-center flex-shrink-0 relative right-[2px] bottom-[2px] self-start"
|
||||
:style="{ background: getAgentMapIcon(item.Name).color }"
|
||||
>
|
||||
<svg-icon
|
||||
:icon-class="getAgentMapIcon(item.Name).icon"
|
||||
color="var(--color-text)"
|
||||
size="24px"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="flex-1 text-[14px] flex flex-col items-center justify-center break-all ml-1 text-[14px] text-[#00F3FF] p-[8px] pl-[0]"
|
||||
>
|
||||
{{ item.Name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full flex justify-center">
|
||||
<div
|
||||
class="rounded-[9px] bg-[var(--color-bg-quaternary)] text-[12px] py-0.5 px-5 text-center my-2"
|
||||
>
|
||||
当前指责
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-[8px] pt-0">
|
||||
<div
|
||||
v-for="(item1, index1) in taskProcess.filter((i) => i.AgentName === item.Name)"
|
||||
:key="item1.key"
|
||||
class="text-[12px]"
|
||||
>
|
||||
<div>
|
||||
<div class="mx-1 inline-block h-[14px]">
|
||||
<div
|
||||
:style="{ background: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
class="w-[6px] h-[6px] rounded-full mt-[7px]"
|
||||
></div>
|
||||
</div>
|
||||
<span :style="{ color: getActionTypeDisplay(item1.ActionType)?.color }"
|
||||
>{{ getActionTypeDisplay(item1.ActionType)?.name }}:</span
|
||||
>
|
||||
<span>{{ item1.Description }}</span>
|
||||
</div>
|
||||
<!-- 分割线 -->
|
||||
<div
|
||||
v-if="index1 !== taskProcess.filter((i) => i.AgentName === item.Name).length - 1"
|
||||
class="h-[1px] w-full bg-[#494B51] my-[8px]"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-popover>
|
||||
<div class="pt-[18px] flex-1 overflow-y-auto relative">
|
||||
<!-- 已选中的智能体 -->
|
||||
<AgentRepoList :agent-list="agentList.selected" />
|
||||
<!-- 为选择的智能体 -->
|
||||
<div v-for="agent in agentList.unselected" :key="agent.title">
|
||||
<p class="text-[12px] font-bold py-[8px]">{{ agent.title }}</p>
|
||||
<AgentRepoList :agent-list="agent.data" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 底部提示栏 -->
|
||||
<div class="w-full grid grid-cols-3 gap-x-[10px] bg-[#1d222b] rounded-[20px] p-[8px] mt-[10px]">
|
||||
@ -279,28 +178,6 @@ const agentList = computed(() => {
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.user-item {
|
||||
background: #1d222b;
|
||||
border-radius: 40px;
|
||||
padding-right: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s ease;
|
||||
color: #969696;
|
||||
|
||||
& + .user-item {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
|
||||
color: #b8b8b8;
|
||||
}
|
||||
}
|
||||
|
||||
.active-card {
|
||||
border-left: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
#agent-repo {
|
||||
|
||||
@ -63,10 +63,6 @@ function createInternalLine(id?: string) {
|
||||
jsplumb.reset()
|
||||
collaborationProcess.value.forEach((item) => {
|
||||
// 创建左侧流程与产出的连线
|
||||
// jsplumb.connect(`task-results-${item.Id}-0`, `task-results-${item.Id}-1`, [
|
||||
// AnchorLocations.Left,
|
||||
// AnchorLocations.Left,
|
||||
// ])
|
||||
arr.push({
|
||||
sourceId: `task-results-${item.Id}-0`,
|
||||
targetId: `task-results-${item.Id}-1`,
|
||||
@ -75,14 +71,6 @@ function createInternalLine(id?: string) {
|
||||
collaborationProcess.value.forEach((jitem) => {
|
||||
// 创建左侧产出与上一步流程的连线
|
||||
if (item.InputObject_List!.includes(jitem.OutputObject ?? '')) {
|
||||
// jsplumb.connect(
|
||||
// `task-results-${jitem.Id}-1`,
|
||||
// `task-results-${item.Id}-0`,
|
||||
// [AnchorLocations.Left, AnchorLocations.Left],
|
||||
// {
|
||||
// type: 'output',
|
||||
// },
|
||||
// )
|
||||
arr.push({
|
||||
sourceId: `task-results-${jitem.Id}-1`,
|
||||
targetId: `task-results-${item.Id}-0`,
|
||||
@ -96,8 +84,8 @@ function createInternalLine(id?: string) {
|
||||
jitem.TaskProcess.forEach((i) => {
|
||||
if (i.ImportantInput?.includes(`InputObject:${item.OutputObject}`)) {
|
||||
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
||||
const sourceId = `task-results-${jitem.Id}-0-${i.ID}`
|
||||
const targetId = `task-results-${item.Id}-1`
|
||||
const sourceId = `task-results-${item.Id}-1`
|
||||
const targetId = `task-results-${jitem.Id}-0-${i.ID}`
|
||||
arr.push({
|
||||
sourceId,
|
||||
targetId,
|
||||
@ -107,7 +95,7 @@ function createInternalLine(id?: string) {
|
||||
[0, color],
|
||||
[1, color],
|
||||
],
|
||||
transparent: sourceId !== id,
|
||||
transparent: targetId !== id,
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -122,8 +110,8 @@ function createInternalLine(id?: string) {
|
||||
item.TaskProcess?.forEach((i2) => {
|
||||
if (i.ImportantInput.includes(`ActionResult:${i2.ID}`)) {
|
||||
const color = getActionTypeDisplay(i.ActionType)?.color ?? ''
|
||||
const sourceId = `task-results-${item.Id}-0-${i.ID}`
|
||||
const targetId = `task-results-${item.Id}-0-${i2.ID}`
|
||||
const sourceId = `task-results-${item.Id}-0-${i2.ID}`
|
||||
const targetId = `task-results-${item.Id}-0-${i.ID}`
|
||||
arr.push({
|
||||
sourceId,
|
||||
targetId,
|
||||
@ -133,7 +121,7 @@ function createInternalLine(id?: string) {
|
||||
[0, color],
|
||||
[1, color],
|
||||
],
|
||||
transparent: sourceId !== id,
|
||||
transparent: targetId !== id,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@ -32,7 +32,25 @@ const taskResultRef = ref<{
|
||||
}>()
|
||||
const taskResultJsplumb = new Jsplumb('task-template')
|
||||
|
||||
function setCurrentTask(task: IRawStepTask) {
|
||||
|
||||
function scrollToElementTop(elementId: string) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (element) {
|
||||
element.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function handleTaskSyllabusCurrentTask(task: IRawStepTask) {
|
||||
scrollToElementTop(`task-results-${task.Id}-0`)
|
||||
agentsStore.setCurrentTask(task)
|
||||
}
|
||||
|
||||
function handleTaskResultCurrentTask(task: IRawStepTask) {
|
||||
scrollToElementTop(`task-syllabus-flow-${task.Id}`)
|
||||
agentsStore.setCurrentTask(task)
|
||||
// 更新任务大纲内部的线
|
||||
taskSyllabusRef.value?.changeTask(task, false)
|
||||
@ -64,7 +82,7 @@ defineExpose({
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="task-template flex gap-6 items-center h-[calc(100%-67px)] relative overflow-hidden"
|
||||
class="task-template flex gap-6 items-center h-[calc(100%-84px)] relative overflow-hidden"
|
||||
id="task-template"
|
||||
>
|
||||
<!-- 智能体库 -->
|
||||
@ -76,7 +94,7 @@ defineExpose({
|
||||
<TaskSyllabus
|
||||
ref="taskSyllabusRef"
|
||||
@resetAgentRepoLine="resetAgentRepoLine"
|
||||
@set-current-task="setCurrentTask"
|
||||
@set-current-task="handleTaskSyllabusCurrentTask"
|
||||
/>
|
||||
</div>
|
||||
<!-- 执行结果 -->
|
||||
@ -84,7 +102,7 @@ defineExpose({
|
||||
<TaskResult
|
||||
ref="taskResultRef"
|
||||
@refresh-line="taskResultJsplumb.repaintEverything"
|
||||
@set-current-task="setCurrentTask"
|
||||
@set-current-task="handleTaskResultCurrentTask"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,19 +120,3 @@ defineExpose({
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
:root {
|
||||
--gradient: linear-gradient(to right, #0093eb, #00d2d1);
|
||||
}
|
||||
|
||||
#task-template {
|
||||
.active-card {
|
||||
border: 2px solid transparent;
|
||||
$bg: var(--el-input-bg-color, var(--el-fill-color-blank));
|
||||
background:
|
||||
linear-gradient(var(--color-bg-secondary), var(--color-bg-secondary)) padding-box,
|
||||
linear-gradient(to right, #00c8d2, #315ab4) border-box;
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -58,14 +58,14 @@ export class Jsplumb {
|
||||
getStops = (type?: 'input' | 'output'): [[number, string], [number, string]] => {
|
||||
if (type === 'input') {
|
||||
return [
|
||||
[0, '#0093EB'],
|
||||
[1, '#00D2D1'],
|
||||
[0, '#FF6161'],
|
||||
[1, '#D76976'],
|
||||
]
|
||||
}
|
||||
|
||||
return [
|
||||
[0, '#FF6161'],
|
||||
[1, '#D76976'],
|
||||
[0, '#0093EB'],
|
||||
[1, '#00D2D1'],
|
||||
]
|
||||
}
|
||||
|
||||
@ -113,6 +113,7 @@ export class Jsplumb {
|
||||
type: DotEndpoint.type,
|
||||
options: { radius: 5 },
|
||||
},
|
||||
cssClass: `jtk-connector-${config.type}`
|
||||
} as unknown as ConnectParams<unknown>)
|
||||
|
||||
// 为源元素添加端点
|
||||
|
||||
@ -13,7 +13,7 @@ function handleSearch() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="p-[27px] h-[calc(100%-60px)]">
|
||||
<div class="p-[24px] h-[calc(100%-60px)]">
|
||||
<Task @search="handleSearch" @search-start="taskTemplateRef?.clear" />
|
||||
<TaskTemplate ref="taskTemplateRef" />
|
||||
</div>
|
||||
|
||||
@ -121,7 +121,7 @@ export const agentMapDuty: Record<string, AgentMapDuty> = {
|
||||
Propose: {
|
||||
name: '提议',
|
||||
key: 'propose',
|
||||
color: '#0060FF',
|
||||
color: '#06A3FF',
|
||||
},
|
||||
Critique: {
|
||||
name: '评审',
|
||||
@ -131,12 +131,12 @@ export const agentMapDuty: Record<string, AgentMapDuty> = {
|
||||
Improve: {
|
||||
name: '改进',
|
||||
key: 'improve',
|
||||
color: '#9808FF',
|
||||
color: '#BF65FF',
|
||||
},
|
||||
Finalize: {
|
||||
name: '总结',
|
||||
key: 'summary',
|
||||
color: '#FF6F08',
|
||||
color: '#FFA236',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ export interface Agent {
|
||||
Name: string
|
||||
Profile: string
|
||||
Icon: string
|
||||
Classification: string
|
||||
}
|
||||
|
||||
type HslColorVector = [number, number, number]
|
||||
@ -50,7 +51,7 @@ export interface IRawPlanResponse {
|
||||
}
|
||||
|
||||
export const useAgentsStore = defineStore('counter', () => {
|
||||
const agents = useStorage<Agent[]>('agents', [])
|
||||
const agents = useStorage<Agent[]>('agents-v1', [])
|
||||
function setAgents(agent: Agent[]) {
|
||||
agents.value = agent
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user