style: code format
This commit is contained in:
parent
b7e10c6666
commit
90e3a79a77
@ -124,9 +124,7 @@ def virtual_path_for_thread_file(thread_id: str, path: str | Path) -> str:
|
||||
else:
|
||||
workspace_relative = relative_path.as_posix()
|
||||
relative_path_str = (
|
||||
_WORKSPACE_DIR_NAME
|
||||
if workspace_relative in {"", "."}
|
||||
else f"{_WORKSPACE_DIR_NAME}/{workspace_relative}"
|
||||
_WORKSPACE_DIR_NAME if workspace_relative in {"", "."} else f"{_WORKSPACE_DIR_NAME}/{workspace_relative}"
|
||||
)
|
||||
|
||||
prefix = get_virtual_path_prefix().rstrip("/")
|
||||
|
||||
@ -8,8 +8,7 @@ import requests
|
||||
from langchain.tools import InjectedToolCallId
|
||||
from langchain_core.messages import ToolMessage
|
||||
from langgraph.prebuilt.tool_node import ToolRuntime
|
||||
from langgraph.types import Command
|
||||
from langgraph.types import interrupt
|
||||
from langgraph.types import Command, interrupt
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from yuxi import config, graph_base
|
||||
|
||||
@ -516,7 +516,9 @@ async def delete_mcp_server(db: AsyncSession, name: str) -> bool:
|
||||
# =============================================================================
|
||||
|
||||
|
||||
async def set_server_enabled(db: AsyncSession, name: str, enabled: bool, updated_by: str = None) -> tuple[bool, MCPServer]:
|
||||
async def set_server_enabled(
|
||||
db: AsyncSession, name: str, enabled: bool, updated_by: str = None
|
||||
) -> tuple[bool, MCPServer]:
|
||||
"""Set server enabled status."""
|
||||
server = await get_mcp_server(db, name)
|
||||
if not server:
|
||||
|
||||
@ -143,7 +143,12 @@ import hljs from 'highlight.js/lib/common'
|
||||
import 'md-editor-v3/lib/preview.css'
|
||||
import { useThemeStore } from '@/stores/theme'
|
||||
import { getFileIcon, getFileIconColor } from '@/utils/file_utils'
|
||||
import { getCodeLanguageByPath, getPreviewTypeByPath, isHtmlPreview, isMarkdownPreview } from '@/utils/file_preview'
|
||||
import {
|
||||
getCodeLanguageByPath,
|
||||
getPreviewTypeByPath,
|
||||
isHtmlPreview,
|
||||
isMarkdownPreview
|
||||
} from '@/utils/file_preview'
|
||||
import { downloadViewerFile, getViewerFileContent } from '@/apis/viewer_filesystem'
|
||||
|
||||
const props = defineProps({
|
||||
@ -176,7 +181,9 @@ const normalizedArtifacts = computed(() =>
|
||||
return {
|
||||
path: normalizedPath,
|
||||
name: normalizedPath.split('/').pop() || normalizedPath,
|
||||
canPreview: ['text', 'markdown', 'pdf', 'image'].includes(getPreviewTypeByPath(normalizedPath))
|
||||
canPreview: ['text', 'markdown', 'pdf', 'image'].includes(
|
||||
getPreviewTypeByPath(normalizedPath)
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
@ -741,7 +741,8 @@ const getConfigOptions = (value) => {
|
||||
return liveSkillOptions.value.length > 0 ? liveSkillOptions.value : value?.options || []
|
||||
}
|
||||
if (value?.template_metadata?.kind === 'subagents') {
|
||||
const options = liveSubagentOptions.value.length > 0 ? liveSubagentOptions.value : value?.options || []
|
||||
const options =
|
||||
liveSubagentOptions.value.length > 0 ? liveSubagentOptions.value : value?.options || []
|
||||
return options.filter((option) => option?.enabled !== false)
|
||||
}
|
||||
return value?.options || []
|
||||
|
||||
@ -27,11 +27,17 @@
|
||||
|
||||
<!-- 服务器列表 -->
|
||||
<div class="list-container">
|
||||
<div v-if="!filteredEnabledServers.length && !filteredDisabledServers.length" class="empty-text">
|
||||
<div
|
||||
v-if="!filteredEnabledServers.length && !filteredDisabledServers.length"
|
||||
class="empty-text"
|
||||
>
|
||||
<a-empty :image="false" :description="searchQuery ? '无匹配服务器' : '暂无服务器'" />
|
||||
</div>
|
||||
<div v-if="filteredEnabledServers.length" class="list-section-title">已添加</div>
|
||||
<template v-for="(server, index) in filteredEnabledServers" :key="`enabled-${server.name}`">
|
||||
<template
|
||||
v-for="(server, index) in filteredEnabledServers"
|
||||
:key="`enabled-${server.name}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentServer?.name === server.name }"
|
||||
@ -44,7 +50,11 @@
|
||||
</div>
|
||||
<div class="item-status">
|
||||
<span class="status-chip status-chip-success">已添加</span>
|
||||
<button type="button" class="inline-hover-action" @click.stop="handleSetServerEnabled(server, false)">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-hover-action"
|
||||
@click.stop="handleSetServerEnabled(server, false)"
|
||||
>
|
||||
移除
|
||||
</button>
|
||||
</div>
|
||||
@ -62,7 +72,10 @@
|
||||
></div>
|
||||
</template>
|
||||
<div v-if="filteredDisabledServers.length" class="list-section-title">可添加</div>
|
||||
<template v-for="(server, index) in filteredDisabledServers" :key="`disabled-${server.name}`">
|
||||
<template
|
||||
v-for="(server, index) in filteredDisabledServers"
|
||||
:key="`disabled-${server.name}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentServer?.name === server.name, disabled: true }"
|
||||
@ -74,7 +87,11 @@
|
||||
<span class="item-name">{{ server.name }}</span>
|
||||
</div>
|
||||
<div class="item-status">
|
||||
<button type="button" class="skill-inline-action skill-inline-action-primary" @click.stop="handleSetServerEnabled(server, true)">
|
||||
<button
|
||||
type="button"
|
||||
class="skill-inline-action skill-inline-action-primary"
|
||||
@click.stop="handleSetServerEnabled(server, true)"
|
||||
>
|
||||
添加
|
||||
</button>
|
||||
</div>
|
||||
@ -556,8 +573,12 @@ const filteredServers = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const filteredEnabledServers = computed(() => filteredServers.value.filter((item) => !!item.enabled))
|
||||
const filteredDisabledServers = computed(() => filteredServers.value.filter((item) => !item.enabled))
|
||||
const filteredEnabledServers = computed(() =>
|
||||
filteredServers.value.filter((item) => !!item.enabled)
|
||||
)
|
||||
const filteredDisabledServers = computed(() =>
|
||||
filteredServers.value.filter((item) => !item.enabled)
|
||||
)
|
||||
|
||||
const isStdioTransport = computed(
|
||||
() =>
|
||||
|
||||
@ -19,13 +19,18 @@
|
||||
|
||||
<div class="list-container">
|
||||
<div
|
||||
v-if="filteredInstalledSkills.length === 0 && filteredUninstalledBuiltinSkills.length === 0"
|
||||
v-if="
|
||||
filteredInstalledSkills.length === 0 && filteredUninstalledBuiltinSkills.length === 0
|
||||
"
|
||||
class="empty-text"
|
||||
>
|
||||
<a-empty :image="false" description="无匹配技能" />
|
||||
</div>
|
||||
<div v-if="filteredInstalledSkills.length" class="list-section-title">已添加 Skills</div>
|
||||
<template v-for="(skill, index) in filteredInstalledSkills" :key="`installed-${skill.slug}`">
|
||||
<template
|
||||
v-for="(skill, index) in filteredInstalledSkills"
|
||||
:key="`installed-${skill.slug}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentSkill?.slug === skill.slug }"
|
||||
@ -38,7 +43,11 @@
|
||||
</div>
|
||||
<div class="item-status">
|
||||
<span class="status-chip status-chip-success">已添加</span>
|
||||
<button type="button" class="inline-hover-action" @click.stop="confirmDeleteSkill(skill)">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-hover-action"
|
||||
@click.stop="confirmDeleteSkill(skill)"
|
||||
>
|
||||
移除
|
||||
</button>
|
||||
</div>
|
||||
@ -46,18 +55,28 @@
|
||||
<div class="item-details">
|
||||
<span class="item-desc">{{ skill.description || '暂无描述' }}</span>
|
||||
<div class="item-tags">
|
||||
<span class="source-tag" :class="{ builtin: skill.sourceType === 'builtin' }">{{ skill.sourceLabel }}</span>
|
||||
<span class="source-tag" :class="{ builtin: skill.sourceType === 'builtin' }">{{
|
||||
skill.sourceLabel
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="index < filteredInstalledSkills.length - 1 || filteredUninstalledBuiltinSkills.length > 0"
|
||||
v-if="
|
||||
index < filteredInstalledSkills.length - 1 ||
|
||||
filteredUninstalledBuiltinSkills.length > 0
|
||||
"
|
||||
class="list-separator"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<div v-if="filteredUninstalledBuiltinSkills.length" class="list-section-title">可添加 Skills</div>
|
||||
<template v-for="(skill, index) in filteredUninstalledBuiltinSkills" :key="`builtin-${skill.slug}`">
|
||||
<div v-if="filteredUninstalledBuiltinSkills.length" class="list-section-title">
|
||||
可添加 Skills
|
||||
</div>
|
||||
<template
|
||||
v-for="(skill, index) in filteredUninstalledBuiltinSkills"
|
||||
:key="`builtin-${skill.slug}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentSkill?.slug === skill.slug }"
|
||||
@ -85,7 +104,10 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="index < filteredUninstalledBuiltinSkills.length - 1" class="list-separator"></div>
|
||||
<div
|
||||
v-if="index < filteredUninstalledBuiltinSkills.length - 1"
|
||||
class="list-separator"
|
||||
></div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@ -155,7 +177,9 @@
|
||||
<div v-if="!isInstalledSkill" class="builtin-uninstalled-state">
|
||||
<h3>{{ currentSkill.description }}</h3>
|
||||
<p>版本 {{ currentSkill.version }}</p>
|
||||
<a-button type="primary" @click="handleInstallBuiltin(currentSkill)">安装内置 Skill</a-button>
|
||||
<a-button type="primary" @click="handleInstallBuiltin(currentSkill)"
|
||||
>安装内置 Skill</a-button
|
||||
>
|
||||
</div>
|
||||
|
||||
<a-tabs v-else v-model:activeKey="activeTab" class="minimal-tabs">
|
||||
@ -432,15 +456,23 @@ const installedSkillCards = computed(() => {
|
||||
const filteredInstalledSkills = computed(() => installedSkillCards.value.filter(matchesSearch))
|
||||
|
||||
const filteredUninstalledBuiltinSkills = computed(() => {
|
||||
return (builtinSkills.value || []).filter((skill) => skill.status === 'not_installed' && matchesSearch(skill))
|
||||
return (builtinSkills.value || []).filter(
|
||||
(skill) => skill.status === 'not_installed' && matchesSearch(skill)
|
||||
)
|
||||
})
|
||||
|
||||
const isInstalledSkill = computed(() => {
|
||||
return !!(currentSkill.value && (currentSkill.value.installed_record || currentSkill.value.dir_path))
|
||||
return !!(
|
||||
currentSkill.value &&
|
||||
(currentSkill.value.installed_record || currentSkill.value.dir_path)
|
||||
)
|
||||
})
|
||||
|
||||
const isBuiltinInstalledSkill = computed(() => {
|
||||
return !!(isInstalledSkill.value && (currentSkill.value?.is_builtin || currentSkill.value?.installed_record))
|
||||
return !!(
|
||||
isInstalledSkill.value &&
|
||||
(currentSkill.value?.is_builtin || currentSkill.value?.installed_record)
|
||||
)
|
||||
})
|
||||
|
||||
const currentSkillStatusLabel = computed(() => {
|
||||
@ -642,7 +674,13 @@ const handleTreeSelect = async (keys, info) => {
|
||||
}
|
||||
|
||||
const saveCurrentFile = async () => {
|
||||
if (!currentSkill.value || !selectedPath.value || selectedIsDir.value || isBuiltinInstalledSkill.value) return
|
||||
if (
|
||||
!currentSkill.value ||
|
||||
!selectedPath.value ||
|
||||
selectedIsDir.value ||
|
||||
isBuiltinInstalledSkill.value
|
||||
)
|
||||
return
|
||||
savingFile.value = true
|
||||
try {
|
||||
await skillApi.updateSkillFile(currentSkill.value.slug, {
|
||||
@ -746,11 +784,17 @@ const confirmDeleteSkill = (targetSkill = null) => {
|
||||
const target = targetSkill || currentSkill.value
|
||||
if (!target) return
|
||||
|
||||
const installed =
|
||||
!!(target && (target.installed_record || target.dir_path || target.is_builtin || target.sourceType))
|
||||
const installed = !!(
|
||||
target &&
|
||||
(target.installed_record || target.dir_path || target.is_builtin || target.sourceType)
|
||||
)
|
||||
if (!installed) return
|
||||
|
||||
const isBuiltinTarget = !!(target?.is_builtin || target?.installed_record || target?.sourceType === 'builtin')
|
||||
const isBuiltinTarget = !!(
|
||||
target?.is_builtin ||
|
||||
target?.installed_record ||
|
||||
target?.sourceType === 'builtin'
|
||||
)
|
||||
const actionText = isBuiltinTarget ? '卸载' : '删除'
|
||||
const detailText = isBuiltinTarget
|
||||
? '卸载后会移除已安装文件和数据库记录,但仍可从“未安装 Skills”中重新安装。'
|
||||
|
||||
@ -20,11 +20,20 @@
|
||||
|
||||
<!-- SubAgent 列表 -->
|
||||
<div class="list-container">
|
||||
<div v-if="!filteredEnabledSubAgents.length && !filteredDisabledSubAgents.length" class="empty-text">
|
||||
<a-empty :image="false" :description="searchQuery ? '无匹配 SubAgent' : '暂无 SubAgent'" />
|
||||
<div
|
||||
v-if="!filteredEnabledSubAgents.length && !filteredDisabledSubAgents.length"
|
||||
class="empty-text"
|
||||
>
|
||||
<a-empty
|
||||
:image="false"
|
||||
:description="searchQuery ? '无匹配 SubAgent' : '暂无 SubAgent'"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="filteredEnabledSubAgents.length" class="list-section-title">已添加</div>
|
||||
<template v-for="(agent, index) in filteredEnabledSubAgents" :key="`enabled-${agent.name}`">
|
||||
<template
|
||||
v-for="(agent, index) in filteredEnabledSubAgents"
|
||||
:key="`enabled-${agent.name}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentAgent?.name === agent.name }"
|
||||
@ -37,7 +46,11 @@
|
||||
</div>
|
||||
<div class="item-status">
|
||||
<span class="status-chip status-chip-success">已添加</span>
|
||||
<button type="button" class="inline-hover-action danger" @click.stop="handleSetAgentEnabled(agent, false)">
|
||||
<button
|
||||
type="button"
|
||||
class="inline-hover-action danger"
|
||||
@click.stop="handleSetAgentEnabled(agent, false)"
|
||||
>
|
||||
移除
|
||||
</button>
|
||||
</div>
|
||||
@ -50,13 +63,18 @@
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="index < filteredEnabledSubAgents.length - 1 || filteredDisabledSubAgents.length > 0"
|
||||
v-if="
|
||||
index < filteredEnabledSubAgents.length - 1 || filteredDisabledSubAgents.length > 0
|
||||
"
|
||||
class="list-separator"
|
||||
></div>
|
||||
</template>
|
||||
|
||||
<div v-if="filteredDisabledSubAgents.length" class="list-section-title">可添加</div>
|
||||
<template v-for="(agent, index) in filteredDisabledSubAgents" :key="`disabled-${agent.name}`">
|
||||
<template
|
||||
v-for="(agent, index) in filteredDisabledSubAgents"
|
||||
:key="`disabled-${agent.name}`"
|
||||
>
|
||||
<div
|
||||
class="list-item extension-list-item"
|
||||
:class="{ active: currentAgent?.name === agent.name }"
|
||||
@ -68,7 +86,11 @@
|
||||
<span class="item-name">{{ agent.name }}</span>
|
||||
</div>
|
||||
<div class="item-status">
|
||||
<button type="button" class="skill-inline-action skill-inline-action-primary" @click.stop="handleSetAgentEnabled(agent, true)">
|
||||
<button
|
||||
type="button"
|
||||
class="skill-inline-action skill-inline-action-primary"
|
||||
@click.stop="handleSetAgentEnabled(agent, true)"
|
||||
>
|
||||
添加
|
||||
</button>
|
||||
</div>
|
||||
@ -172,7 +194,10 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-section" v-if="currentAgent.is_builtin || currentAgent.enabled === false">
|
||||
<div
|
||||
class="detail-section"
|
||||
v-if="currentAgent.is_builtin || currentAgent.enabled === false"
|
||||
>
|
||||
<div class="section-header">
|
||||
<Info :size="14" />
|
||||
<span>类型</span>
|
||||
@ -325,8 +350,12 @@ const filteredSubAgents = computed(() => {
|
||||
)
|
||||
})
|
||||
|
||||
const filteredEnabledSubAgents = computed(() => filteredSubAgents.value.filter((item) => item.enabled !== false))
|
||||
const filteredDisabledSubAgents = computed(() => filteredSubAgents.value.filter((item) => item.enabled === false))
|
||||
const filteredEnabledSubAgents = computed(() =>
|
||||
filteredSubAgents.value.filter((item) => item.enabled !== false)
|
||||
)
|
||||
const filteredDisabledSubAgents = computed(() =>
|
||||
filteredSubAgents.value.filter((item) => item.enabled === false)
|
||||
)
|
||||
|
||||
// 获取 SubAgent 列表
|
||||
const fetchSubAgents = async () => {
|
||||
|
||||
@ -71,7 +71,7 @@ const TOOL_RENDERERS = {
|
||||
write_todos: TodoListTool
|
||||
}
|
||||
|
||||
const TOOL_RENDERER_HIDE = ["present_artifacts"]
|
||||
const TOOL_RENDERER_HIDE = ['present_artifacts']
|
||||
|
||||
const currentRenderer = computed(() => TOOL_RENDERERS[toolId.value] || null)
|
||||
const isHidden = computed(() => TOOL_RENDERER_HIDE.includes(toolId.value))
|
||||
|
||||
@ -20,7 +20,10 @@
|
||||
|
||||
<a-tooltip :title="`当前分类:${currentCategoryLabel}`">
|
||||
<a-dropdown trigger="click">
|
||||
<a-button class="sidebar-tool category-trigger" :class="{ active: !!selectedCategory }">
|
||||
<a-button
|
||||
class="sidebar-tool category-trigger"
|
||||
:class="{ active: !!selectedCategory }"
|
||||
>
|
||||
<SlidersHorizontal :size="14" />
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
@ -194,7 +197,9 @@ const filteredTools = computed(() => {
|
||||
})
|
||||
|
||||
const currentCategoryLabel = computed(
|
||||
() => categoryLabels[selectedCategory.value] || (selectedCategory.value ? selectedCategory.value : '全部分类')
|
||||
() =>
|
||||
categoryLabels[selectedCategory.value] ||
|
||||
(selectedCategory.value ? selectedCategory.value : '全部分类')
|
||||
)
|
||||
|
||||
const fetchTools = async () => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user