feat: 先进智能体功能上线

- 基于 agent-runtime 打造,默认 ReAct agent
- 支持 agent 能力对接,已对接工作流、插件、知识库等 tool 能力
- 全新 agent 编排界面,支持可视化便捷配置 agent
- 全新 agent 聊天界面,支持快捷操作、额外知识库选择等
This commit is contained in:
2026-05-28 11:29:18 +08:00
parent 11e595b088
commit 1c205c3720
39 changed files with 3546 additions and 217 deletions

View File

@@ -1,8 +1,9 @@
<script lang="ts" setup>
import type {
DropdownMenuProps,
EasyFlowDropdownMenuItem as IDropdownMenuItem,
} from './interface';
import type {DropdownMenuProps, EasyFlowDropdownMenuItem as IDropdownMenuItem,} from './interface';
import {computed, ref} from 'vue';
import {Search} from '@easyflow-core/icons';
import {
DropdownMenu,
@@ -11,12 +12,29 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
Input,
} from '../../ui';
interface Props extends DropdownMenuProps {}
defineOptions({ name: 'DropdownMenu' });
const props = withDefaults(defineProps<Props>(), {});
const props = withDefaults(defineProps<Props>(), {
align: 'start',
searchEmptyText: '无匹配标签',
searchPlaceholder: '搜索标签',
});
const searchKeyword = ref('');
const filteredMenus = computed(() => {
const keyword = searchKeyword.value.trim().toLocaleLowerCase();
if (!props.searchable || !keyword) {
return props.menus;
}
return props.menus.filter((menu) =>
menu.label.toLocaleLowerCase().includes(keyword),
);
});
function handleItemClick(menu: IDropdownMenuItem) {
if (menu.disabled) {
@@ -27,22 +45,50 @@ function handleItemClick(menu: IDropdownMenuItem) {
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger class="flex h-full items-center gap-1">
<DropdownMenuTrigger
:aria-label="triggerLabel"
class="flex h-full items-center gap-1"
>
<slot></slot>
</DropdownMenuTrigger>
<DropdownMenuContent align="start">
<DropdownMenuContent :align="align" :class="contentClass">
<div v-if="searchable" class="sticky top-0 z-10 bg-popover p-1">
<div class="relative">
<Search
class="pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-[hsl(var(--text-muted))]"
/>
<Input
v-model="searchKeyword"
:placeholder="searchPlaceholder"
class="h-8 rounded-md border-[hsl(var(--line-subtle))] bg-[hsl(var(--surface-subtle))] py-1 pl-8 pr-2 text-xs"
@keydown.stop
/>
</div>
</div>
<DropdownMenuGroup>
<template v-for="menu in menus" :key="menu.value">
<template v-for="menu in filteredMenus" :key="menu.value">
<DropdownMenuItem
:disabled="menu.disabled"
:class="{
'bg-[hsl(var(--nav-item-active))] text-[hsl(var(--nav-item-active-foreground))] font-medium':
menu.active,
}"
class="data-[state=checked]:bg-accent data-[state=checked]:text-accent-foreground text-foreground/80 mb-1 cursor-pointer"
@click="handleItemClick(menu)"
>
<component :is="menu.icon" v-if="menu.icon" class="mr-2 size-4" />
{{ menu.label }}
<span class="min-w-0 flex-1 truncate">
{{ menu.label }}
</span>
</DropdownMenuItem>
<DropdownMenuSeparator v-if="menu.separator" class="bg-border" />
</template>
<div
v-if="filteredMenus.length === 0"
class="px-3 py-5 text-center text-xs text-[hsl(var(--text-muted))]"
>
{{ searchEmptyText }}
</div>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>

View File

@@ -1,6 +1,10 @@
import type { Component } from 'vue';
import type {Component} from 'vue';
interface EasyFlowDropdownMenuItem {
/**
* @zh_CN 是否为当前选中项
*/
active?: boolean;
disabled?: boolean;
/**
* @zh_CN 点击事件处理
@@ -26,7 +30,31 @@ interface EasyFlowDropdownMenuItem {
}
interface DropdownMenuProps {
/**
* @zh_CN 菜单对齐方向
*/
align?: 'center' | 'end' | 'start';
/**
* @zh_CN 菜单浮层样式
*/
contentClass?: any;
menus: EasyFlowDropdownMenuItem[];
/**
* @zh_CN 搜索无结果文案
*/
searchEmptyText?: string;
/**
* @zh_CN 搜索占位文案
*/
searchPlaceholder?: string;
/**
* @zh_CN 是否显示菜单搜索框
*/
searchable?: boolean;
/**
* @zh_CN 触发按钮的无障碍标签
*/
triggerLabel?: string;
}
export type { DropdownMenuProps, EasyFlowDropdownMenuItem };