feat: 支持智能体可见范围管理
- 未分类智能体按可见范围绕过分类白名单 - 提供个人、部门、公开范围配置及列表状态标签
This commit is contained in:
18
easyflow-ui-admin/app/src/views/ai/agents/AgentList.test.ts
Normal file
18
easyflow-ui-admin/app/src/views/ai/agents/AgentList.test.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import agentListSource from './AgentList.vue?raw';
|
||||
import apiSource from './api.ts?raw';
|
||||
|
||||
describe('AgentList 可见范围入口', () => {
|
||||
it('exposes the three scope choices and uses the dedicated partial-update API', () => {
|
||||
expect(agentListSource).toContain("label: '个人'");
|
||||
expect(agentListSource).toContain("label: '部门'");
|
||||
expect(agentListSource).toContain("label: '公开'");
|
||||
expect(agentListSource).toContain('updateAgentVisibilityScope');
|
||||
expect(agentListSource).toContain('agent-publish-chip');
|
||||
expect(agentListSource).toContain('agent-publish-chip__dot');
|
||||
expect(agentListSource).toContain('<template #details="{ item }">');
|
||||
expect(agentListSource).not.toContain('<template #corner="{ item }">');
|
||||
expect(apiSource).toContain('/api/v1/agent/visibilityScope/update');
|
||||
});
|
||||
});
|
||||
@@ -1,22 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
/* cspell:ignore tryit */
|
||||
import type {AgentInfo} from './types';
|
||||
import type { AgentInfo } from './types';
|
||||
|
||||
import type {ActionButton, CardPrimaryAction,} from '#/components/page/CardList.vue';
|
||||
import type {
|
||||
ActionButton,
|
||||
CardPrimaryAction,
|
||||
} from '#/components/page/CardList.vue';
|
||||
import CardList from '#/components/page/CardList.vue';
|
||||
|
||||
import {markRaw, onMounted, ref} from 'vue';
|
||||
import {useRouter} from 'vue-router';
|
||||
import { computed, markRaw, onMounted, ref } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
import {Delete, Edit, Plus, Promotion} from '@element-plus/icons-vue';
|
||||
import {ElMessage, ElMessageBox, ElTag} from 'element-plus';
|
||||
import {tryit} from 'radash';
|
||||
import { useAccess } from '@easyflow/access';
|
||||
|
||||
import {
|
||||
Check,
|
||||
Delete,
|
||||
Edit,
|
||||
Lock,
|
||||
OfficeBuilding,
|
||||
Plus,
|
||||
Promotion,
|
||||
} from '@element-plus/icons-vue';
|
||||
import { ElIcon, ElMessage, ElMessageBox, ElPopover } from 'element-plus';
|
||||
import { tryit } from 'radash';
|
||||
|
||||
import defaultAgentAvatar from '#/assets/defaultUserAvatar.png';
|
||||
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
|
||||
import PageData from '#/components/page/PageData.vue';
|
||||
import PageSide from '#/components/page/PageSide.vue';
|
||||
import {$t} from '#/locales';
|
||||
import { $t } from '#/locales';
|
||||
import AiResourceCornerMeta from '#/views/ai/shared/AiResourceCornerMeta.vue';
|
||||
import {
|
||||
canAiResourceDelete,
|
||||
canAiResourceOffline,
|
||||
@@ -31,6 +45,7 @@ import {
|
||||
submitAgentDeleteApproval,
|
||||
submitAgentOfflineApproval,
|
||||
submitAgentPublishApproval,
|
||||
updateAgentVisibilityScope,
|
||||
} from './api';
|
||||
|
||||
const router = useRouter();
|
||||
@@ -38,6 +53,35 @@ const pageDataRef = ref();
|
||||
const sideList = ref<any[]>([]);
|
||||
const AGENT_TAB_PAGE_KEY = '/ai/agents';
|
||||
const DEFAULT_AGENT_TITLE = '未命名智能体';
|
||||
type VisibilityScope = 'DEPT' | 'PRIVATE' | 'PUBLIC';
|
||||
|
||||
const { hasAccessByCodes } = useAccess();
|
||||
const canManageAgent = computed(() => hasAccessByCodes(['/api/v1/agent/save']));
|
||||
const updatingVisibilityScopeId = ref<null | number | string>(null);
|
||||
const visibilityScopePopoverRefs = ref<Record<string, any>>({});
|
||||
const visibilityScopeMeta = {
|
||||
PRIVATE: {
|
||||
description: '仅创建者可使用',
|
||||
icon: Lock,
|
||||
label: '个人',
|
||||
tone: 'private',
|
||||
},
|
||||
DEPT: {
|
||||
description: '本部门及下级部门可使用',
|
||||
icon: OfficeBuilding,
|
||||
label: '部门',
|
||||
tone: 'dept',
|
||||
},
|
||||
PUBLIC: {
|
||||
description: '租户内所有有聊天权限的用户可使用',
|
||||
icon: Promotion,
|
||||
label: '公开',
|
||||
tone: 'public',
|
||||
},
|
||||
};
|
||||
const visibilityScopeOptions = (
|
||||
['PRIVATE', 'DEPT', 'PUBLIC'] as VisibilityScope[]
|
||||
).map((value) => ({ value, ...visibilityScopeMeta[value] }));
|
||||
|
||||
const headerButtons = [
|
||||
{
|
||||
@@ -128,6 +172,54 @@ function resolveNavTitle(row: AgentInfo) {
|
||||
return String(row.name || '').trim() || DEFAULT_AGENT_TITLE;
|
||||
}
|
||||
|
||||
function resolveVisibilityScopeMeta(scope?: string) {
|
||||
return (
|
||||
visibilityScopeMeta[scope as VisibilityScope] || visibilityScopeMeta.PRIVATE
|
||||
);
|
||||
}
|
||||
|
||||
function setVisibilityScopePopoverRef(id: number | string, el: any) {
|
||||
const cacheKey = String(id);
|
||||
if (el) {
|
||||
visibilityScopePopoverRefs.value[cacheKey] = el;
|
||||
return;
|
||||
}
|
||||
delete visibilityScopePopoverRefs.value[cacheKey];
|
||||
}
|
||||
|
||||
function closeVisibilityScopePopover(id: number | string) {
|
||||
visibilityScopePopoverRefs.value[String(id)]?.hide?.();
|
||||
}
|
||||
|
||||
async function updateVisibilityScope(
|
||||
row: AgentInfo,
|
||||
visibilityScope: VisibilityScope,
|
||||
) {
|
||||
if (!row?.id) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
!canManageAgent.value ||
|
||||
updatingVisibilityScopeId.value === row.id ||
|
||||
row.visibilityScope === visibilityScope
|
||||
) {
|
||||
closeVisibilityScopePopover(row.id);
|
||||
return;
|
||||
}
|
||||
updatingVisibilityScopeId.value = row.id;
|
||||
try {
|
||||
const res = await updateAgentVisibilityScope(row.id, visibilityScope);
|
||||
if (res.errorCode === 0) {
|
||||
row.visibilityScope = visibilityScope;
|
||||
ElMessage.success(res.message || $t('message.saveOkMessage'));
|
||||
closeVisibilityScopePopover(row.id);
|
||||
pageDataRef.value?.reload?.();
|
||||
}
|
||||
} finally {
|
||||
updatingVisibilityScopeId.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function changeCategory(category: any) {
|
||||
pageDataRef.value?.setQuery({ categoryId: category.id });
|
||||
}
|
||||
@@ -148,22 +240,22 @@ function resolvePublishStatusMeta(
|
||||
) {
|
||||
switch (resolveAiResourceDisplayStatus(displayPublishStatus, publishStatus)) {
|
||||
case 'DELETE_PENDING': {
|
||||
return { label: '删除中', type: 'danger' as const };
|
||||
return { label: '删除中', tone: 'danger' };
|
||||
}
|
||||
case 'OFFLINE': {
|
||||
return { label: '已下线', type: 'info' as const };
|
||||
return { label: '已下线', tone: 'draft' };
|
||||
}
|
||||
case 'OFFLINE_PENDING': {
|
||||
return { label: '下线中', type: 'warning' as const };
|
||||
return { label: '下线中', tone: 'pending' };
|
||||
}
|
||||
case 'PUBLISH_PENDING': {
|
||||
return { label: '发布中', type: 'warning' as const };
|
||||
return { label: '发布中', tone: 'pending' };
|
||||
}
|
||||
case 'PUBLISHED': {
|
||||
return { label: '已发布', type: 'success' as const };
|
||||
return { label: '已发布', tone: 'published' };
|
||||
}
|
||||
default: {
|
||||
return { label: '草稿', type: 'info' as const };
|
||||
return { label: '草稿', tone: 'draft' };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -267,25 +359,124 @@ async function handleDeleteAction(row: AgentInfo) {
|
||||
:primary-action="primaryAction"
|
||||
:actions="actions"
|
||||
>
|
||||
<template #corner="{ item }">
|
||||
<ElTag
|
||||
size="small"
|
||||
effect="plain"
|
||||
round
|
||||
:type="
|
||||
resolvePublishStatusMeta(
|
||||
item.displayPublishStatus,
|
||||
item.publishStatus,
|
||||
).type
|
||||
"
|
||||
>
|
||||
{{
|
||||
resolvePublishStatusMeta(
|
||||
item.displayPublishStatus,
|
||||
item.publishStatus,
|
||||
).label
|
||||
}}
|
||||
</ElTag>
|
||||
<template #details="{ item }">
|
||||
<AiResourceCornerMeta>
|
||||
<template #publish>
|
||||
<div
|
||||
class="agent-publish-chip"
|
||||
:class="
|
||||
'agent-publish-chip--' +
|
||||
resolvePublishStatusMeta(
|
||||
item.displayPublishStatus,
|
||||
item.publishStatus,
|
||||
).tone
|
||||
"
|
||||
>
|
||||
<span class="agent-publish-chip__dot"></span>
|
||||
<span>{{
|
||||
resolvePublishStatusMeta(
|
||||
item.displayPublishStatus,
|
||||
item.publishStatus,
|
||||
).label
|
||||
}}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template #scope>
|
||||
<ElPopover
|
||||
v-if="canManageAgent"
|
||||
:ref="(el) => setVisibilityScopePopoverRef(item.id, el)"
|
||||
trigger="click"
|
||||
placement="bottom-end"
|
||||
:width="208"
|
||||
popper-class="agent-visibility-popover"
|
||||
>
|
||||
<template #reference>
|
||||
<button
|
||||
type="button"
|
||||
class="agent-scope-chip"
|
||||
:class="`agent-scope-chip--${resolveVisibilityScopeMeta(item.visibilityScope).tone}`"
|
||||
:disabled="updatingVisibilityScopeId === item.id"
|
||||
@click.stop
|
||||
>
|
||||
<ElIcon class="agent-scope-chip__icon">
|
||||
<component
|
||||
:is="
|
||||
resolveVisibilityScopeMeta(item.visibilityScope)
|
||||
.icon
|
||||
"
|
||||
/>
|
||||
</ElIcon>
|
||||
<span class="agent-scope-chip__label">
|
||||
{{
|
||||
resolveVisibilityScopeMeta(item.visibilityScope)
|
||||
.label
|
||||
}}
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
<div class="agent-scope-panel" @click.stop>
|
||||
<button
|
||||
v-for="option in visibilityScopeOptions"
|
||||
:key="option.value"
|
||||
type="button"
|
||||
class="agent-scope-option"
|
||||
:class="[
|
||||
`agent-scope-option--${option.tone}`,
|
||||
{
|
||||
'agent-scope-option--active':
|
||||
item.visibilityScope === option.value,
|
||||
},
|
||||
]"
|
||||
:disabled="updatingVisibilityScopeId === item.id"
|
||||
@click.stop="
|
||||
updateVisibilityScope(item, option.value)
|
||||
"
|
||||
>
|
||||
<span class="agent-scope-option__leading">
|
||||
<span class="agent-scope-option__icon-wrap">
|
||||
<ElIcon class="agent-scope-option__icon">
|
||||
<component :is="option.icon" />
|
||||
</ElIcon>
|
||||
</span>
|
||||
<span class="agent-scope-option__text">
|
||||
<span class="agent-scope-option__label">
|
||||
{{ option.label }}
|
||||
</span>
|
||||
<span class="agent-scope-option__desc">
|
||||
{{ option.description }}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<ElIcon
|
||||
v-if="item.visibilityScope === option.value"
|
||||
class="agent-scope-option__check"
|
||||
>
|
||||
<Check />
|
||||
</ElIcon>
|
||||
</button>
|
||||
</div>
|
||||
</ElPopover>
|
||||
<div
|
||||
v-else
|
||||
class="agent-scope-chip agent-scope-chip--readonly"
|
||||
:class="`agent-scope-chip--${resolveVisibilityScopeMeta(item.visibilityScope).tone}`"
|
||||
>
|
||||
<ElIcon class="agent-scope-chip__icon">
|
||||
<component
|
||||
:is="
|
||||
resolveVisibilityScopeMeta(item.visibilityScope)
|
||||
.icon
|
||||
"
|
||||
/>
|
||||
</ElIcon>
|
||||
<span class="agent-scope-chip__label">
|
||||
{{
|
||||
resolveVisibilityScopeMeta(item.visibilityScope).label
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</AiResourceCornerMeta>
|
||||
</template>
|
||||
</CardList>
|
||||
</template>
|
||||
@@ -317,4 +508,252 @@ async function handleDeleteAction(row: AgentInfo) {
|
||||
height: calc(100vh - 192px);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.agent-publish-chip {
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
box-shadow: inset 0 1px 0 hsl(var(--card) / 46%);
|
||||
}
|
||||
|
||||
.agent-publish-chip__dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
background: currentColor;
|
||||
border-radius: 999px;
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.agent-publish-chip--draft {
|
||||
color: hsl(var(--muted-foreground));
|
||||
background: hsl(var(--muted) / 42%);
|
||||
border-color: hsl(var(--line-subtle));
|
||||
}
|
||||
|
||||
.agent-publish-chip--pending {
|
||||
color: hsl(var(--warning));
|
||||
background: hsl(var(--warning) / 12%);
|
||||
border-color: hsl(var(--warning) / 14%);
|
||||
}
|
||||
|
||||
.agent-publish-chip--published {
|
||||
color: hsl(var(--success));
|
||||
background: hsl(var(--success) / 12%);
|
||||
border-color: hsl(var(--success) / 14%);
|
||||
}
|
||||
|
||||
.agent-publish-chip--danger {
|
||||
color: hsl(var(--destructive));
|
||||
background: hsl(var(--destructive) / 10%);
|
||||
border-color: hsl(var(--destructive) / 14%);
|
||||
}
|
||||
|
||||
.agent-scope-chip {
|
||||
display: inline-flex;
|
||||
gap: 6px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 22px;
|
||||
padding: 0 8px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
line-height: 1;
|
||||
color: hsl(var(--text-strong));
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
transition:
|
||||
border-color 0.18s ease,
|
||||
background-color 0.18s ease,
|
||||
color 0.18s ease,
|
||||
transform 0.18s ease,
|
||||
box-shadow 0.18s ease;
|
||||
}
|
||||
|
||||
button.agent-scope-chip {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button.agent-scope-chip:hover {
|
||||
background: hsl(var(--card) / 76%);
|
||||
box-shadow: 0 8px 16px -16px hsl(var(--foreground) / 28%);
|
||||
}
|
||||
|
||||
button.agent-scope-chip:focus-visible {
|
||||
outline: none;
|
||||
box-shadow:
|
||||
0 0 0 4px hsl(var(--primary) / 12%),
|
||||
0 10px 22px -18px hsl(var(--foreground) / 32%);
|
||||
}
|
||||
|
||||
button.agent-scope-chip:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.agent-scope-chip--readonly {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.agent-scope-chip__icon {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.agent-scope-chip__label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.agent-scope-chip--private {
|
||||
color: hsl(var(--primary));
|
||||
background: hsl(var(--primary) / 10%);
|
||||
border-color: hsl(var(--primary) / 14%);
|
||||
}
|
||||
|
||||
.agent-scope-chip--dept {
|
||||
color: hsl(var(--warning));
|
||||
background: hsl(var(--warning) / 12%);
|
||||
border-color: hsl(var(--warning) / 14%);
|
||||
}
|
||||
|
||||
.agent-scope-chip--public {
|
||||
color: hsl(var(--success));
|
||||
background: hsl(var(--success) / 12%);
|
||||
border-color: hsl(var(--success) / 14%);
|
||||
}
|
||||
|
||||
.agent-scope-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.agent-scope-option {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 10px 8px;
|
||||
text-align: left;
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
transition:
|
||||
background-color 0.18s ease,
|
||||
transform 0.18s ease,
|
||||
color 0.18s ease;
|
||||
}
|
||||
|
||||
.agent-scope-option:hover {
|
||||
background: hsl(var(--foreground) / 4%);
|
||||
}
|
||||
|
||||
.agent-scope-option:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 4px hsl(var(--primary) / 12%);
|
||||
}
|
||||
|
||||
.agent-scope-option:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.72;
|
||||
}
|
||||
|
||||
.agent-scope-option__leading {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.agent-scope-option__icon-wrap {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
background: transparent;
|
||||
border-radius: 9px;
|
||||
}
|
||||
|
||||
.agent-scope-option__icon {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.agent-scope-option__text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.agent-scope-option__label {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: hsl(var(--text-strong));
|
||||
}
|
||||
|
||||
.agent-scope-option__desc {
|
||||
font-size: 11px;
|
||||
line-height: 1.35;
|
||||
color: hsl(var(--text-muted));
|
||||
}
|
||||
|
||||
.agent-scope-option__check {
|
||||
flex-shrink: 0;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.agent-scope-option--private .agent-scope-option__icon-wrap {
|
||||
color: hsl(var(--primary));
|
||||
background: hsl(var(--primary) / 10%);
|
||||
}
|
||||
|
||||
.agent-scope-option--dept .agent-scope-option__icon-wrap {
|
||||
color: hsl(var(--warning));
|
||||
background: hsl(var(--warning) / 12%);
|
||||
}
|
||||
|
||||
.agent-scope-option--public .agent-scope-option__icon-wrap {
|
||||
color: hsl(var(--success));
|
||||
background: hsl(var(--success) / 12%);
|
||||
}
|
||||
|
||||
.agent-scope-option--private.agent-scope-option--active {
|
||||
background: hsl(var(--primary) / 8%);
|
||||
}
|
||||
|
||||
.agent-scope-option--dept.agent-scope-option--active {
|
||||
background: hsl(var(--warning) / 8%);
|
||||
}
|
||||
|
||||
.agent-scope-option--public.agent-scope-option--active {
|
||||
background: hsl(var(--success) / 8%);
|
||||
}
|
||||
|
||||
.agent-scope-option--private .agent-scope-option__check {
|
||||
color: hsl(var(--primary));
|
||||
}
|
||||
|
||||
.agent-scope-option--dept .agent-scope-option__check {
|
||||
color: hsl(var(--warning));
|
||||
}
|
||||
|
||||
.agent-scope-option--public .agent-scope-option__check {
|
||||
color: hsl(var(--success));
|
||||
}
|
||||
|
||||
:global(.agent-visibility-popover.el-popover.el-popper) {
|
||||
padding: 8px;
|
||||
border-color: hsl(var(--line-subtle));
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 18px 34px -28px hsl(var(--foreground) / 20%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -26,6 +26,16 @@ export function updateAgent(agent: AgentInfo) {
|
||||
return api.post<RequestResult<AgentInfo>>('/api/v1/agent/update', agent);
|
||||
}
|
||||
|
||||
export function updateAgentVisibilityScope(
|
||||
id: number | string,
|
||||
visibilityScope: string,
|
||||
) {
|
||||
return api.post<RequestResult<AgentInfo>>(
|
||||
'/api/v1/agent/visibilityScope/update',
|
||||
{ id, visibilityScope },
|
||||
);
|
||||
}
|
||||
|
||||
export function updateAgentToolBindings(
|
||||
agentId: number | string,
|
||||
bindings: AgentToolBinding[],
|
||||
|
||||
@@ -26,6 +26,12 @@ const props = defineProps<{
|
||||
|
||||
const emit = defineEmits<{ change: [] }>();
|
||||
|
||||
const visibilityScopeOptions = [
|
||||
{ label: '个人', value: 'PRIVATE' },
|
||||
{ label: '部门', value: 'DEPT' },
|
||||
{ label: '公开', value: 'PUBLIC' },
|
||||
];
|
||||
|
||||
function handleModelChange(modelId: AgentInfo['modelId']) {
|
||||
const selectedModel = props.models.find(
|
||||
(model) => model.value === String(modelId ?? ''),
|
||||
@@ -86,6 +92,16 @@ function handleModelChange(modelId: AgentInfo['modelId']) {
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="可见范围">
|
||||
<ElSelect v-model="agent.visibilityScope" @change="emit('change')">
|
||||
<ElOption
|
||||
v-for="item in visibilityScopeOptions"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="模型" required>
|
||||
<ElSelect v-model="agent.modelId" filterable @change="handleModelChange">
|
||||
<ElOption
|
||||
|
||||
@@ -32,6 +32,25 @@ describe('useAgentDesignerState generation stream', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('useAgentDesignerState visibility scope', () => {
|
||||
it('defaults new and legacy agents to private visibility', () => {
|
||||
expect(createEmptyAgent().visibilityScope).toBe('PRIVATE');
|
||||
|
||||
const designer = useAgentDesignerState();
|
||||
designer.reset({ name: '旧智能体' });
|
||||
|
||||
expect(designer.state.agent.visibilityScope).toBe('PRIVATE');
|
||||
expect(designer.buildPayloadAgent().visibilityScope).toBe('PRIVATE');
|
||||
});
|
||||
|
||||
it('preserves the selected visibility scope in the save payload', () => {
|
||||
const designer = useAgentDesignerState();
|
||||
designer.reset({ name: '部门智能体', visibilityScope: 'DEPT' });
|
||||
|
||||
expect(designer.buildPayloadAgent().visibilityScope).toBe('DEPT');
|
||||
});
|
||||
});
|
||||
|
||||
describe('useAgentDesignerState document context budget', () => {
|
||||
it('defaults new and legacy agents to twenty thousand tokens', () => {
|
||||
expect(
|
||||
|
||||
@@ -94,6 +94,7 @@ export function createEmptyAgent(): AgentInfo {
|
||||
description: '',
|
||||
avatar: '',
|
||||
categoryId: '',
|
||||
visibilityScope: 'PRIVATE',
|
||||
executionConfigJson: {
|
||||
documentContextBudgetTokens: 20_000,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user