style(lint): 优化格式

This commit is contained in:
Wenjie Zhang 2026-03-26 13:53:35 +08:00
parent 56d11db978
commit dbc230e205
72 changed files with 189 additions and 363 deletions

View File

@ -30,13 +30,9 @@ logs:
# LINTING AND FORMATTING
######################
lint:
cd backend && uv run ruff check package
cd backend && uv run ruff format --check package
cd backend && uv run ruff check --select I package
format:
cd backend && uv run ruff format package
cd backend && uv run ruff check package --fix
cd backend && uv run ruff check --select I package --fix
docker compose exec -T web pnpm run format
cd web && pnpm run format
cd web && pnpm run lint

View File

@ -10,8 +10,8 @@ from .paths import (
virtual_path_for_thread_file,
)
from .provider import (
SandboxConnection,
ProvisionerSandboxProvider,
SandboxConnection,
get_sandbox_provider,
init_sandbox_provider,
sandbox_id_for_thread,

View File

@ -1,6 +1,5 @@
from __future__ import annotations
import asyncio
import os
from abc import abstractmethod
from pathlib import Path
@ -11,8 +10,9 @@ from langgraph.graph.state import CompiledStateGraph
from yuxi import config as sys_config
from yuxi.agents.context import BaseContext
from yuxi.utils import logger
from yuxi.storage.postgres.manager import pg_manager
from yuxi.utils import logger
class BaseAgent:
"""

View File

@ -21,10 +21,7 @@ from .prompt import PROMPT
async def _build_middlewares(context):
"""构建中间件列表"""
all_mcp_tools = (
await get_tools_from_all_servers()
) # 因为异步加载,无法放在 RuntimeConfigMiddleware 的 __init__ 中
all_mcp_tools = await get_tools_from_all_servers() # 因为异步加载,无法放在 RuntimeConfigMiddleware 的 __init__ 中
# summary middleware
# 主 Agent 上下文优化90k tokens 触发压缩128k context window 的 70%
@ -80,7 +77,6 @@ class ChatbotAgent(BaseAgent):
def __init__(self, **kwargs):
super().__init__(**kwargs)
async def get_graph(self, context=None, **kwargs):
context = context or self.context_schema() # 获取上下文配置

View File

@ -83,4 +83,4 @@ DEEP_PROMPT = """你是一位专家级研究员。你的工作是进行彻底的
- /home/gem/user-data/workspace/用于存放工作文件和中间结果
- /home/gem/user-data/outputs/用于存放最终输出结果
- /home/gem/user-data/uploads/用于存放用户上传的文件
"""
"""

View File

@ -405,7 +405,13 @@ class SkillsMiddleware(AgentMiddleware):
pure = PurePosixPath(raw if raw.startswith("/") else f"/{raw}")
parts = [p for p in pure.parts if p not in ("/", "")]
slug: str | None = None
if len(parts) == 5 and parts[0] == "home" and parts[1] == "gem" and parts[2] == "skills" and parts[4] == "SKILL.md":
if (
len(parts) == 5
and parts[0] == "home"
and parts[1] == "gem"
and parts[2] == "skills"
and parts[4] == "SKILL.md"
):
slug = parts[3]
if not is_valid_skill_slug(slug):

View File

@ -221,9 +221,7 @@ class Config(BaseModel):
if os.path.exists(self.model_dir):
logger.debug(f"Model directory ({self.model_dir}) contains: {os.listdir(self.model_dir)}")
else:
logger.debug(
f"Model directory ({self.model_dir}) does not exist. If not configured, please ignore it."
)
logger.debug(f"Model directory ({self.model_dir}) does not exist. If not configured, please ignore it.")
# 检查模型提供商的环境变量
self.model_provider_status = {}

View File

@ -1,28 +1,23 @@
import uuid
from dataclasses import dataclass
from datetime import UTC, datetime
from pathlib import Path
import aiofiles
from fastapi import HTTPException, UploadFile
from sqlalchemy.ext.asyncio import AsyncSession
from yuxi.agents.backends.sandbox import (
ensure_thread_dirs,
sandbox_uploads_dir,
)
from yuxi.services.doc_converter import ATTACHMENT_ALLOWED_EXTENSIONS, MAX_ATTACHMENT_SIZE_BYTES
UPLOADS_VIRTUAL_PREFIX = "/home/gem/user-data/uploads"
from yuxi.agents.buildin import agent_manager
from yuxi.config import config as app_config
from yuxi.plugins.parser import Parser
from yuxi.repositories.conversation_repository import ConversationRepository
from yuxi.services.doc_converter import ATTACHMENT_ALLOWED_EXTENSIONS, MAX_ATTACHMENT_SIZE_BYTES
from yuxi.utils.datetime_utils import utc_isoformat
from yuxi.utils.logging_config import logger
ATTACHMENT_ALLOWED_EXTENSIONS: tuple[str, ...] = (".txt", ".md", ".docx", ".html", ".htm")
MAX_ATTACHMENT_SIZE_BYTES = 5 * 1024 * 1024 # 5 MB
UPLOADS_VIRTUAL_PREFIX = "/home/gem/user-data/uploads"
MAX_ATTACHMENT_MARKDOWN_CHARS = 32_000

View File

@ -8,7 +8,6 @@ from pathlib import Path
import aiofiles
from fastapi import UploadFile
from yuxi.config import config as app_config
from yuxi.plugins.parser import Parser
from yuxi.utils import logger

View File

@ -130,8 +130,6 @@ async def build_visible_knowledge_mounts(
return mounts
def cache_minio_object(*, source_url: str, metadata: dict[str, Any] | None = None) -> Path:
bucket_name, object_name = parse_minio_url(source_url)
minio_client = get_minio_client()
@ -139,7 +137,7 @@ def cache_minio_object(*, source_url: str, metadata: dict[str, Any] | None = Non
etag = str(getattr(stat, "etag", "") or "")
last_modified = getattr(stat, "last_modified", None)
version_key = etag or (last_modified.isoformat() if last_modified else "")
cache_key = hashlib.sha256(f"{bucket_name}:{object_name}:{version_key}".encode("utf-8")).hexdigest()
cache_key = hashlib.sha256(f"{bucket_name}:{object_name}:{version_key}".encode()).hexdigest()
suffix = Path(object_name).suffix
objects_root = get_kb_cache_root() / "objects"

View File

@ -5,15 +5,14 @@ from pathlib import Path
from typing import Any
from fastapi import HTTPException
from yuxi import config as conf
from yuxi.repositories.conversation_repository import ConversationRepository
from yuxi.agents.backends.sandbox import (
ensure_thread_dirs,
resolve_virtual_path,
sandbox_user_data_dir,
virtual_path_for_thread_file,
)
from yuxi.repositories.conversation_repository import ConversationRepository
from yuxi.services.conversation_service import require_user_conversation

View File

@ -33,48 +33,47 @@
.search-box {
padding: 8px 12px 0;
:deep(.ant-input-affix-wrapper) {
height: 28px;
padding: 0 12px;
:deep(.ant-input-affix-wrapper) {
height: 28px;
padding: 0 12px;
// border: none;
border-radius: 8px;
background-color: var(--gray-0);
box-shadow: none;
&:hover,
&:focus,
&.ant-input-affix-wrapper-focused {
// border: none;
border-radius: 8px;
background-color: var(--gray-0);
box-shadow: none;
&:hover,
&:focus,
&.ant-input-affix-wrapper-focused {
// border: none;
box-shadow: none;
}
}
}
:deep(.ant-input-prefix) {
margin-right: 8px;
color: var(--gray-400);
}
:deep(.ant-input-prefix) {
margin-right: 8px;
color: var(--gray-400);
}
:deep(.ant-input) {
height: 100%;
background-color: transparent;
}
:deep(.ant-input) {
height: 100%;
background-color: transparent;
}
:deep(.ant-input::placeholder) {
color: var(--gray-400);
}
:deep(.ant-input::placeholder) {
color: var(--gray-400);
}
:deep(.ant-input-clear-icon) {
color: var(--gray-400);
}
:deep(.ant-input-clear-icon) {
color: var(--gray-400);
}
:deep(.ant-input-clear-icon:hover) {
color: var(--gray-500);
}
// :deep(.ant-input-outlined) {
// border: none;
// }
:deep(.ant-input-clear-icon:hover) {
color: var(--gray-500);
}
// :deep(.ant-input-outlined) {
// border: none;
// }
}
.list-container {

View File

@ -548,22 +548,6 @@ const isReadOnlyConfig = computed(() => !userStore.isAdmin)
const isSavingConfig = ref(false)
const isDeletingConfig = ref(false)
const hasOtherConfigs = computed(() => {
if (isEmptyConfig.value) return false
return Object.entries(configurableItems.value).some(([, value]) => {
const isBasic =
value.template_metadata?.kind === 'prompt' || value.template_metadata?.kind === 'llm'
const isTools =
value.template_metadata?.kind === 'mcps' ||
value.template_metadata?.kind === 'knowledges' ||
value.template_metadata?.kind === 'tools' ||
value.template_metadata?.kind === 'skills' ||
value.template_metadata?.kind === 'subagents'
return !isBasic && !isTools
})
})
const segmentConfigKeys = computed(() => {
const keys = Object.keys(configurableItems.value)
return {

View File

@ -108,7 +108,7 @@
<script setup>
import { computed, ref } from 'vue'
import { CaretRightOutlined, ThunderboltOutlined, LoadingOutlined } from '@ant-design/icons-vue'
import { CaretRightOutlined } from '@ant-design/icons-vue'
import RefsComponent from '@/components/RefsComponent.vue'
import { Copy, Check } from 'lucide-vue-next'
import { ToolCallRenderer } from '@/components/ToolCallingResult'

View File

@ -168,7 +168,7 @@
</template>
<template v-else-if="isMarkdown">
<MdPreview
class="flat-md-preview "
class="flat-md-preview"
:modelValue="formatContent(currentFile?.content)"
:theme="theme"
previewTheme="github"

View File

@ -37,7 +37,6 @@ import { message } from 'ant-design-vue'
import { multimodalApi } from '@/apis/agent_api'
const fileInputRef = ref(null)
const imageInputRef = ref(null)
const props = defineProps({
disabled: {

View File

@ -92,7 +92,8 @@
<div
class="card card-select"
v-if="
configStore.config?.enable_content_guard && configStore.config?.enable_content_guard_llm
configStore.config?.enable_content_guard &&
configStore.config?.enable_content_guard_llm
"
>
<span class="label">{{ items?.content_guard_llm_model?.des }}</span>
@ -254,7 +255,6 @@ onMounted(async () => {
<style lang="less" scoped>
.basic-settings-section {
.section {
background-color: var(--gray-0);
padding: 10px 16px;

View File

@ -120,7 +120,7 @@ import {
Trash2,
MoreVertical
} from 'lucide-vue-next'
import dayjs, { parseToShanghai } from '@/utils/time'
import { parseToShanghai } from '@/utils/time'
import { useChatUIStore } from '@/stores/chatUI'
import { useInfoStore } from '@/stores/info'
import { useUserStore } from '@/stores/user'

View File

@ -3,7 +3,7 @@
<div class="params-info">
<p>调整分块参数可以控制文本的切分方式影响检索质量和文档加载效率</p>
</div>
<a-form :model="tempChunkParams" name="chunkConfig" autocomplete="off" layout="vertical">
<a-form :model="localParams" name="chunkConfig" autocomplete="off" layout="vertical">
<a-form-item v-if="showPreset" name="chunk_preset_id">
<template #label>
<span class="chunk-preset-label">
@ -14,7 +14,7 @@
</span>
</template>
<a-select
v-model:value="tempChunkParams.chunk_preset_id"
v-model:value="localParams.chunk_preset_id"
:options="presetOptions"
style="width: 100%"
/>
@ -27,7 +27,7 @@
<div class="chunk-row" v-if="showChunkSizeOverlap">
<a-form-item label="Chunk Size" name="chunk_size">
<a-input-number
v-model:value="tempChunkParams.chunk_size"
v-model:value="localParams.chunk_size"
:min="100"
:max="10000"
style="width: 100%"
@ -36,7 +36,7 @@
</a-form-item>
<a-form-item label="Chunk Overlap" name="chunk_overlap">
<a-input-number
v-model:value="tempChunkParams.chunk_overlap"
v-model:value="localParams.chunk_overlap"
:min="0"
:max="1000"
style="width: 100%"
@ -51,7 +51,7 @@
name="qa_separator"
>
<a-input
v-model:value="tempChunkParams.qa_separator"
v-model:value="localParams.qa_separator"
placeholder="输入分隔符,例如 \n\n\n 或 ---"
style="width: 100%"
/>
@ -97,6 +97,10 @@ const props = defineProps({
}
})
// 使 computed
// tempChunkParamsref
const localParams = computed(() => props.tempChunkParams)
const presetOptions = computed(() => {
const options = []
const defaultPresetLabel = CHUNK_PRESET_LABEL_MAP[props.databasePresetId] || 'General'

View File

@ -46,7 +46,7 @@ import { message } from 'ant-design-vue'
const configStore = useConfigStore()
const props = defineProps({
defineProps({
value: {
type: String,
default: ''

View File

@ -206,8 +206,6 @@ import {
EyeOutlined,
DownloadOutlined,
DeleteOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
ReloadOutlined
} from '@ant-design/icons-vue'
import { evaluationApi } from '@/apis/knowledge_api'
@ -429,7 +427,7 @@ const parseDownloadFilename = (contentDisposition) => {
}
}
const asciiMatch = contentDisposition.match(/filename=\"?([^\";]+)\"?/i)
const asciiMatch = contentDisposition.match(/filename="?([^";]+)"?/i)
if (asciiMatch && asciiMatch[1]) {
return asciiMatch[1]
}

View File

@ -397,10 +397,9 @@
</template>
<script setup>
import { ref, computed, watch, h } from 'vue'
import { ref, computed, h } from 'vue'
import { useDatabaseStore } from '@/stores/database'
import { message, Modal } from 'ant-design-vue'
import { useUserStore } from '@/stores/user'
import { documentApi } from '@/apis/knowledge_api'
import {
CheckCircleFilled,
@ -420,8 +419,6 @@ import {
FolderPlus,
CheckSquare,
FileText,
FileCheck,
Plus,
Database,
FileUp,
Search,
@ -430,7 +427,6 @@ import {
} from 'lucide-vue-next'
const store = useDatabaseStore()
const userStore = useUserStore()
const sortField = ref('filename')
const sortOptions = [
@ -485,7 +481,6 @@ const lock = computed(() => store.state.lock)
const batchDeleting = computed(() => store.state.batchDeleting)
const batchParsing = computed(() => store.state.chunkLoading)
const batchIndexing = computed(() => store.state.chunkLoading)
const autoRefresh = computed(() => store.state.autoRefresh)
const selectedRowKeys = computed({
get: () => store.selectedRowKeys,
set: (keys) => (store.selectedRowKeys = keys)
@ -660,7 +655,7 @@ const customRow = (record) => {
onOk: async () => {
try {
await store.moveFile(file_id, record.file_id)
} catch (error) {
} catch {
// error handled in store
}
}
@ -996,10 +991,6 @@ const handleRefresh = () => {
store.getDatabaseInfo(undefined, true) // Skip query params for manual refresh
}
const toggleAutoRefresh = () => {
store.toggleAutoRefresh()
}
const toggleRightPanel = () => {
console.log(props.rightPanelVisible)
emit('toggleRightPanel')
@ -1039,7 +1030,7 @@ const handleDeleteFolder = (record) => {
try {
await store.deleteFile(record.file_id)
message.success('删除成功')
} catch (error) {
} catch {
// Error handled in store but we can add extra handling if needed
}
}
@ -1245,7 +1236,6 @@ const handleIndexConfigCancel = () => {
//
import { getFileIcon, getFileIconColor, formatRelativeTime } from '@/utils/file_utils'
import { parseToShanghai } from '@/utils/time'
import ChunkParamsConfig from '@/components/ChunkParamsConfig.vue'
</script>

View File

@ -160,8 +160,12 @@
<div class="stat-pill uploading" v-if="uploadingUploadCount > 0">
上传中 {{ uploadingUploadCount }}
</div>
<div class="stat-pill queued" v-if="queuedUploadCount > 0">排队 {{ queuedUploadCount }}</div>
<div class="stat-pill error" v-if="failedUploadCount > 0">失败 {{ failedUploadCount }}</div>
<div class="stat-pill queued" v-if="queuedUploadCount > 0">
排队 {{ queuedUploadCount }}
</div>
<div class="stat-pill error" v-if="failedUploadCount > 0">
失败 {{ failedUploadCount }}
</div>
</div>
</div>
<div class="progress-header-right">
@ -192,9 +196,7 @@
<div class="progress-tip" v-if="hasPendingUploads">
文件夹上传采用队列模式最多同时上传 {{ MAX_UPLOAD_CONCURRENCY }} 个文件
</div>
<div class="progress-tip" v-else>
上传队列已完成可点击添加到知识库继续下一步
</div>
<div class="progress-tip" v-else>上传队列已完成可点击添加到知识库继续下一步</div>
</div>
</div>
</div>
@ -292,12 +294,12 @@
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { message, Upload, Tooltip, Modal } from 'ant-design-vue'
import { message, Upload, Modal } from 'ant-design-vue'
import { useUserStore } from '@/stores/user'
import { useDatabaseStore } from '@/stores/database'
import { ocrApi } from '@/apis/system_api'
import { fileApi, documentApi } from '@/apis/knowledge_api'
import { CheckCircleFilled, ReloadOutlined } from '@ant-design/icons-vue'
import { ReloadOutlined } from '@ant-design-icons-vue'
import {
FileUp,
FolderUp,
@ -456,7 +458,6 @@ const chunkLoading = computed(() => store.state.chunkLoading)
//
const uploadMode = ref('file')
const previousOcrSelection = ref('disable')
const MAX_UPLOAD_CONCURRENCY = 10
//
@ -596,7 +597,7 @@ const isValidUrl = (string) => {
try {
const url = new URL(string)
return url.protocol === 'http:' || url.protocol === 'https:'
} catch (_) {
} catch {
return false
}
}
@ -674,14 +675,6 @@ const removeUrl = (index) => {
urlList.value.splice(index, 1)
}
const handleUrlKeydown = (e) => {
// Ctrl + Enter
if (e.key === 'Enter' && e.ctrlKey) {
e.preventDefault()
handleFetchUrls()
}
}
// OCR
const ocrHealthStatus = ref({
rapid_ocr: { status: 'unknown', message: '' },
@ -724,12 +717,6 @@ const buildAutoIndexParams = () => {
}
}
// QA
const isQaSplitSupported = computed(() => {
const type = kbType.value?.toLowerCase()
return type === 'milvus'
})
const isGraphBased = computed(() => {
const type = kbType.value?.toLowerCase()
return type === 'lightrag'
@ -926,20 +913,12 @@ const beforeUpload = (file) => {
return true
}
const formatFileSize = (bytes) => {
if (bytes === 0 || !bytes) return '0 B'
const k = 1024
const sizes = ['B', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`
}
const formatFileTime = (timestamp) => {
if (!timestamp) return ''
try {
const date = new Date(timestamp)
return date.toLocaleString()
} catch (e) {
} catch {
return timestamp
}
}

View File

@ -30,7 +30,7 @@
<script setup>
import { Graph } from '@antv/g6'
import { onMounted, onUnmounted, ref, watch, nextTick } from 'vue'
import { onMounted, onUnmounted, ref, watch } from 'vue'
import { useThemeStore } from '@/stores/theme'
const props = defineProps({
@ -142,7 +142,9 @@ function initGraph() {
if (graphInstance) {
try {
graphInstance.destroy()
} catch (e) {}
} catch {
// ignore cleanup error
}
graphInstance = null
}
@ -330,7 +332,9 @@ function refreshGraph() {
if (graphInstance) {
try {
graphInstance.destroy()
} catch (e) {}
} catch {
// ignore cleanup error
}
graphInstance = null
}
if (container.value) container.value.innerHTML = ''
@ -345,13 +349,17 @@ function fitView() {
if (graphInstance)
try {
graphInstance.fitView()
} catch (_) {}
} catch {
// ignore
}
}
function fitCenter() {
if (graphInstance)
try {
graphInstance.fitCenter()
} catch (_) {}
} catch {
// ignore
}
}
function getInstance() {
return graphInstance
@ -452,7 +460,9 @@ onUnmounted(() => {
clearTimeout(renderTimeout)
try {
graphInstance?.destroy()
} catch (e) {}
} catch {
// ignore cleanup error
}
graphInstance = null
})

View File

@ -23,7 +23,7 @@
<script setup>
import { LoadingOutlined } from '@ant-design/icons-vue'
const props = defineProps({
defineProps({
title: {
type: String,
required: true

View File

@ -16,7 +16,7 @@
<script setup>
import { X } from 'lucide-vue-next'
const props = defineProps({
defineProps({
imageData: {
type: Object,
default: null

View File

@ -10,7 +10,7 @@
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
defineProps({
visible: {
type: Boolean,
default: false

View File

@ -87,7 +87,7 @@
</template>
<script setup>
import { ref, computed, onMounted, onUnmounted, watch } from 'vue'
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/preview.css'
import { mergeChunks, getChunkPreview } from '@/utils/chunkUtils'

View File

@ -406,9 +406,7 @@ const modelStatus = computed(() => configStore.config?.model_provider_status)
//
const customProviders = computed(() => {
const providers = configStore.config?.model_names || {}
return Object.fromEntries(
Object.entries(providers).filter(([key, value]) => value.custom === true)
)
return Object.fromEntries(Object.entries(providers).filter(([, value]) => value.custom === true))
})
//
@ -652,22 +650,6 @@ const customProviderRules = {
env: [{ required: true, message: '请输入API密钥或环境变量', trigger: 'blur' }]
}
// API
const maskApiKey = (apiKey) => {
if (!apiKey) return '未配置'
//
if (apiKey.startsWith('${') && apiKey.endsWith('}')) {
return apiKey
}
// API
if (apiKey.length > 8) {
return apiKey.substring(0, 4) + '***' + apiKey.substring(apiKey.length - 4)
}
return '***'
}
//
const openAddCustomProviderModal = () => {
customProviderModal.visible = true
@ -735,18 +717,14 @@ const saveCustomProvider = async () => {
custom: true
}
let result
if (customProviderModal.isEdit) {
result = await customProviderApi.updateCustomProvider(
await customProviderApi.updateCustomProvider(
customProviderModal.data.providerId,
providerData
)
message.success('自定义供应商更新成功')
} else {
result = await customProviderApi.addCustomProvider(
customProviderModal.data.providerId,
providerData
)
await customProviderApi.addCustomProvider(customProviderModal.data.providerId, providerData)
message.success(`自定义供应商 ${customProviderModal.data.providerId} 添加成功`)
}
@ -784,7 +762,7 @@ const cancelCustomProvider = () => {
//
const deleteCustomProvider = async (providerId) => {
try {
const result = await customProviderApi.deleteCustomProvider(providerId)
await customProviderApi.deleteCustomProvider(providerId)
message.success('自定义供应商删除成功')
await configStore.refreshConfig()
} catch (error) {

View File

@ -1 +1,3 @@
<template></template>
<template>
<div class="project-overview"></div>
</template>

View File

@ -347,7 +347,7 @@ import { Braces, Tags, Network, Link, FileText, ArrowRight } from 'lucide-vue-ne
const store = useDatabaseStore()
const props = defineProps({
defineProps({
visible: {
type: Boolean,
default: true
@ -359,15 +359,12 @@ const props = defineProps({
})
//
const emit = defineEmits(['toggleVisible'])
defineEmits(['toggleVisible'])
const searchLoading = computed(() => store.state.searchLoading)
const queryResult = ref('')
const showRawData = ref(false)
// LightRAG
const isLightRAG = computed(() => store.database?.kb_type?.toLowerCase() === 'lightrag')
// LightRAG
const isLightRAGResult = computed(() => {
return (
@ -386,7 +383,6 @@ const queryExamples = ref([])
const currentExampleIndex = ref(0)
const loadingQuestions = ref(false)
const generatingQuestions = ref(false)
const searchConfigModalVisible = ref(false)
//
let exampleCarouselInterval = null
@ -417,17 +413,6 @@ const extractFileName = (filePath) => {
}
}
//
const openSearchConfigModal = () => {
searchConfigModalVisible.value = true
}
//
const handleSearchConfigSave = (config) => {
console.log('查询测试中的检索配置已更新:', config)
//
}
//
const loadSampleQuestions = async () => {
if (!store.database?.db_id) return

View File

@ -418,7 +418,7 @@ const props = defineProps({
}
})
const emit = defineEmits(['switch-to-benchmarks'])
defineEmits(['switch-to-benchmarks'])
// 使 store
const taskerStore = useTaskerStore()
@ -572,14 +572,6 @@ const historyColumns = [
}
]
//
const currentBenchmark = computed(() => {
if (!selectedBenchmarkId.value || !availableBenchmarks.value) {
return null
}
return availableBenchmarks.value.find((b) => b.benchmark_id === selectedBenchmarkId.value)
})
//
const toggleErrorOnly = async () => {
resultsLoading.value = true
@ -948,12 +940,6 @@ const deleteEvaluationRecord = async (taskId) => {
}
}
//
const truncateText = (text, maxLength) => {
if (!text) return ''
return text.length > maxLength ? text.substring(0, maxLength) + '...' : text
}
const formatTime = (timeStr) => {
if (!timeStr) return '-'
const date = new Date(timeStr)

View File

@ -92,7 +92,7 @@
<script setup>
import { ref, computed, reactive, watch } from 'vue'
import { useClipboard } from '@vueuse/core'
import { message } from 'ant-design-vue'
import { message as antMessage } from 'ant-design-vue'
import {
ThumbsUp,
ThumbsDown,
@ -151,7 +151,7 @@ const feedbackState = reactive({
reason: null
})
// - message.feedback
// - antMessage.feedback
const initFeedbackState = () => {
if (msg.value?.feedback) {
feedbackState.hasSubmitted = true
@ -197,18 +197,18 @@ const copyText = async (text) => {
if (isSupported) {
try {
await copy(text)
message.success('文本已复制到剪贴板')
antMessage.success('文本已复制到剪贴板')
isCopied.value = true
setTimeout(() => {
isCopied.value = false
}, 2000)
} catch (error) {
console.error('复制失败:', error)
message.error('复制失败,请手动复制')
antMessage.error('复制失败,请手动复制')
}
} else {
console.warn('浏览器不支持自动复制')
message.warning('浏览器不支持自动复制,请手动复制')
antMessage.warning('浏览器不支持自动复制,请手动复制')
}
}
@ -244,12 +244,12 @@ const getModelName = (msg) => {
// Handle like action
const likeThisResponse = async (msg) => {
if (feedbackState.hasSubmitted) {
message.info('您已经提交过反馈了')
antMessage.info('您已经提交过反馈了')
return
}
if (!msg?.id) {
message.error('无法提交反馈消息ID不存在')
antMessage.error('无法提交反馈消息ID不存在')
console.error('Message object:', msg)
return
}
@ -261,14 +261,14 @@ const likeThisResponse = async (msg) => {
feedbackState.hasSubmitted = true
feedbackState.rating = 'like'
message.success('感谢您的反馈!')
antMessage.success('感谢您的反馈!')
} catch (error) {
console.error('Failed to submit like feedback:', error)
if (error.message?.includes('already submitted')) {
message.info('您已经提交过反馈了')
antMessage.info('您已经提交过反馈了')
feedbackState.hasSubmitted = true
} else {
message.error('提交反馈失败,请稍后重试')
antMessage.error('提交反馈失败,请稍后重试')
}
} finally {
submittingFeedback.value = false
@ -278,12 +278,12 @@ const likeThisResponse = async (msg) => {
// Handle dislike action
const dislikeThisResponse = async (msg) => {
if (feedbackState.hasSubmitted) {
message.info('您已经提交过反馈了')
antMessage.info('您已经提交过反馈了')
return
}
if (!msg?.id) {
message.error('无法提交反馈消息ID不存在')
antMessage.error('无法提交反馈消息ID不存在')
console.error('Message object:', msg)
return
}
@ -305,15 +305,15 @@ const submitDislikeFeedback = async () => {
dislikeModalVisible.value = false
dislikeReason.value = ''
message.success('感谢您的反馈!')
antMessage.success('感谢您的反馈!')
} catch (error) {
console.error('Failed to submit dislike feedback:', error)
if (error.message?.includes('already submitted')) {
message.info('您已经提交过反馈了')
antMessage.info('您已经提交过反馈了')
feedbackState.hasSubmitted = true
dislikeModalVisible.value = false
} else {
message.error('提交反馈失败,请稍后重试')
antMessage.error('提交反馈失败,请稍后重试')
}
} finally {
submittingFeedback.value = false

View File

@ -206,6 +206,8 @@ const resetToDefaults = () => {
message.success('已重置为默认配置')
}
defineExpose({ resetToDefaults })
//
const handleSave = async () => {
// databaseId

View File

@ -268,7 +268,6 @@ import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/preview.css'
import { useThemeStore } from '@/stores/theme'
import {
Upload,
RotateCw,
Download,
Trash2,
@ -346,8 +345,6 @@ watch(selectedPath, (newPath) => {
}
})
const formatRelativeTime = (time) => (time ? dayjs(time).fromNow() : '-')
const toolDependencyOptions = computed(() =>
(dependencyOptions.tools || []).map((i) =>
typeof i === 'object' ? { label: i.name, value: i.id } : { label: i, value: i }
@ -406,7 +403,7 @@ const fetchSkills = async () => {
}
}
await fetchDependencyOptions()
} catch (error) {
} catch {
message.error('加载失败')
} finally {
loading.value = false
@ -420,7 +417,9 @@ const fetchDependencyOptions = async () => {
dependencyOptions.tools = data.tools || []
dependencyOptions.mcps = data.mcps || []
dependencyOptions.skills = data.skills || []
} catch {}
} catch {
// ignore error
}
}
const syncDependencyFormFromSkill = (skillRecord) => {
@ -538,27 +537,6 @@ const handleCreateNode = async () => {
}
}
const confirmDeleteNode = () => {
if (!currentSkill.value || !selectedPath.value || selectedPath.value === 'SKILL.md') return
Modal.confirm({
title: '确认删除?',
content: `将永久删除: ${selectedPath.value}`,
okText: '删除',
okType: 'danger',
cancelText: '取消',
onOk: async () => {
try {
await skillApi.deleteSkillFile(currentSkill.value.slug, selectedPath.value)
resetFileState()
await reloadTree()
message.success('已删除')
} catch {
message.error('删除失败')
}
}
})
}
const confirmDeleteSkill = () => {
if (!currentSkill.value) return
Modal.confirm({

View File

@ -53,7 +53,6 @@ const { activeCount: activeCountRef } = storeToRefs(taskerStore)
const currentTime = ref('')
//
const organization = computed(() => infoStore.organization)
const branding = computed(() => infoStore.branding)
//

View File

@ -226,7 +226,18 @@
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-vue'
import { Search, Bot, Pencil, Trash2, Info, MessageSquare, FileText, Cpu, Wrench, Clock } from 'lucide-vue-next'
import {
Search,
Bot,
Pencil,
Trash2,
Info,
MessageSquare,
FileText,
Cpu,
Wrench,
Clock
} from 'lucide-vue-next'
import { subagentApi } from '@/apis/subagent_api'
import { toolApi } from '@/apis/tool_api'
import { formatFullDateTime } from '@/utils/time'

View File

@ -334,18 +334,6 @@ function statusLabel(status) {
return map[status] || status
}
function statusColor(status) {
const map = {
pending: 'blue',
queued: 'blue',
running: 'processing',
success: 'green',
failed: 'red',
cancelled: 'gray'
}
return map[status] || 'default'
}
function progressStatus(status) {
if (status === 'failed') return 'exception'
if (status === 'cancelled') return 'normal'

View File

@ -18,9 +18,8 @@
<script setup>
import BaseToolCall from '../BaseToolCall.vue'
import { NumberOutlined } from '@ant-design/icons-vue'
const props = defineProps({
defineProps({
toolCall: {
type: Object,
required: true
@ -31,7 +30,7 @@ const parseData = (content) => {
if (typeof content === 'string') {
try {
return JSON.parse(content)
} catch (error) {
} catch {
return content
}
}

View File

@ -1,6 +1,6 @@
<template>
<BaseToolCall :tool-call="toolCall">
<template #result="{ resultContent }">
<template #result="{}">
<div class="chart-result">
<img :src="chartUrl" />
</div>
@ -23,7 +23,7 @@ const parseData = (content) => {
if (typeof content === 'string') {
try {
return JSON.parse(content)
} catch (error) {
} catch {
return content
}
}

View File

@ -35,7 +35,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -29,7 +29,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -27,7 +27,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -85,7 +85,10 @@ const targetPath = computed(() => parsedArgs.value.path || parsedArgs.value.dir_
const outputMode = computed(() => parsedArgs.value.output_mode || '')
const isFileListResult = computed(() => {
return Array.isArray(parsedResult.value) && parsedResult.value.every((item) => typeof item === 'string')
return (
Array.isArray(parsedResult.value) &&
parsedResult.value.every((item) => typeof item === 'string')
)
})
const fileMatches = computed(() => {

View File

@ -1,6 +1,6 @@
<template>
<BaseToolCall :tool-call="toolCall">
<template #result="{ resultContent }">
<template #result="{}">
<div v-if="imageUrl" class="image-result">
<img :src="imageUrl" />
</div>
@ -26,7 +26,7 @@ const parseData = (content) => {
if (typeof content === 'string') {
try {
return JSON.parse(content)
} catch (error) {
} catch {
return content
}
}

View File

@ -7,7 +7,7 @@
<span class="description">{{ query }}</span>
</div>
</template>
<template #result="{ resultContent }">
<template #result="{}">
<div class="knowledge-graph-result">
<div class="result-summary">找到 {{ totalNodes }} 个节点, {{ totalRelations }} 个关系</div>
@ -40,7 +40,7 @@
<script setup>
import { computed, ref, watch, nextTick, onMounted, onUpdated } from 'vue'
import BaseToolCall from '../BaseToolCall.vue'
import { DeploymentUnitOutlined, ReloadOutlined } from '@ant-design/icons-vue'
import { ReloadOutlined } from '@ant-design/icons-vue'
import GraphCanvas from '@/components/GraphCanvas.vue'
const props = defineProps({
@ -54,7 +54,7 @@ const parseData = (content) => {
if (typeof content === 'string') {
try {
return JSON.parse(content)
} catch (error) {
} catch {
return { triples: [] }
}
}
@ -73,7 +73,7 @@ const query = computed(() => {
if (typeof args === 'string') {
try {
parsedArgs = JSON.parse(args)
} catch (e) {
} catch {
return ''
}
}

View File

@ -31,7 +31,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -5,7 +5,7 @@
<span class="note">{{ operationLabel }}</span>
</div>
</template>
<template #result="{ resultContent }">
<template #result="{}">
<div class="list-kbs-result">
<div class="kb-count"> {{ kbList.length }} 个知识库</div>
<div class="kb-list">

View File

@ -20,7 +20,7 @@
<script setup>
import BaseToolCall from '../BaseToolCall.vue'
const props = defineProps({
defineProps({
toolCall: {
type: Object,
required: true

View File

@ -17,7 +17,7 @@
<script setup>
import BaseToolCall from '../BaseToolCall.vue'
const props = defineProps({
defineProps({
toolCall: {
type: Object,
required: true

View File

@ -26,7 +26,7 @@
<script setup>
import BaseToolCall from '../BaseToolCall.vue'
const props = defineProps({
defineProps({
toolCall: {
type: Object,
required: true

View File

@ -30,7 +30,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -29,7 +29,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -48,7 +48,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -78,7 +78,7 @@ const query = computed(() => {
if (typeof args === 'string') {
try {
parsedArgs = JSON.parse(args)
} catch (e) {
} catch {
return ''
}
}
@ -92,7 +92,7 @@ const parseData = (content) => {
if (typeof content === 'string') {
try {
return JSON.parse(content)
} catch (error) {
} catch {
return content
}
}

View File

@ -30,7 +30,7 @@ const parsedArgs = computed(() => {
if (typeof args === 'object') return args
try {
return JSON.parse(args)
} catch (e) {
} catch {
return {}
}
})

View File

@ -184,11 +184,9 @@ import DebugComponent from '@/components/DebugComponent.vue'
import { message } from 'ant-design-vue'
import {
CircleUser,
UserRoundCheck,
BookOpen,
Sun,
Moon,
User,
LogOut,
Upload,
Settings,
@ -223,7 +221,7 @@ const editedProfile = ref({
phone_number: ''
})
const props = defineProps({
defineProps({
showRole: {
type: Boolean,
default: false
@ -234,12 +232,6 @@ const props = defineProps({
}
})
//
const userInitial = computed(() => {
if (!userStore.username) return '?'
return userStore.username.charAt(0).toUpperCase()
})
//
const userRoleText = computed(() => {
switch (userStore.userRole) {
@ -254,15 +246,6 @@ const userRoleText = computed(() => {
}
})
//
const userRoleClass = computed(() => {
return {
superadmin: userStore.userRole === 'superadmin',
admin: userStore.userRole === 'admin',
user: userStore.userRole === 'user'
}
})
// 退
const logout = () => {
userStore.logout()
@ -413,7 +396,7 @@ const handleAvatarChange = async (info) => {
//
try {
avatarUploading.value = true
const result = await userStore.uploadAvatar(info.file.originFileObj || info.file)
await userStore.uploadAvatar(info.file.originFileObj || info.file)
message.success('头像上传成功!')
} catch (error) {
console.error('头像上传失败:', error)

View File

@ -536,34 +536,6 @@ const confirmDeleteUser = (user) => {
})
}
//
const getRoleLabel = (role) => {
switch (role) {
case 'superadmin':
return '超级管理员'
case 'admin':
return '管理员'
case 'user':
return '普通用户'
default:
return role
}
}
//
const getRoleColor = (role) => {
switch (role) {
case 'superadmin':
return 'red'
case 'admin':
return 'blue'
case 'user':
return 'green'
default:
return 'default'
}
}
const getRoleClass = (role) => {
switch (role) {
case 'superadmin':

View File

@ -220,7 +220,7 @@ const renderCallStatsChart = () => {
params.forEach((param) => {
total += param.value
const truncatedName = truncateLegend(param.seriesName)
result += `<span style=\"display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color}\"></span>`
result += `<span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color}"></span>`
result += `${truncatedName}: ${formatValueForDisplay(param.value)}<br/>`
})
const labelMap = {
@ -230,7 +230,7 @@ const renderCallStatsChart = () => {
tools: '工具调用'
}
const formattedTotal = formatValueForDisplay(total)
return `<div style=\"font-weight:bold;margin-bottom:5px\">${labelMap[callDataType.value]}</div>${result}<strong>总计: ${formattedTotal}</strong>`
return `<div style="font-weight:bold;margin-bottom:5px">${labelMap[callDataType.value]}</div>${result}<strong>总计: ${formattedTotal}</strong>`
}
},
legend: {

View File

@ -1,4 +1,4 @@
import { ref, computed } from 'vue'
import { ref } from 'vue'
/**
* @typedef {Object} MentionFile

View File

@ -73,7 +73,6 @@ const DEFAULT_OPTIONS = {
reserveDecayWindowMs: 2200
}
const getIncomingSize = (chunk) => {
let total = 0
total += (chunk?.content || '').length
@ -274,7 +273,10 @@ export function useStreamSmoother({ getThreadState, options = {} }) {
remaining -= reasoningPart.emitted.length
const additionalReasoningPart = takeFromBuffer(controller.additionalReasoningBuffer, remaining)
if (additionalReasoningPart.emitted || delta.additional_kwargs?.reasoning_content !== undefined) {
if (
additionalReasoningPart.emitted ||
delta.additional_kwargs?.reasoning_content !== undefined
) {
delta.additional_kwargs = {
...(delta.additional_kwargs || {}),
reasoning_content: additionalReasoningPart.emitted

View File

@ -380,6 +380,7 @@ export const useAgentStore = defineStore(
* 保存智能体配置
* @param {Object} options - 额外参数 (e.g., { reload_graph: true })
*/
// eslint-disable-next-line no-unused-vars
async function saveAgentConfig(options = {}) {
const targetAgentId = selectedAgentId.value
const targetConfigId = selectedAgentConfigId.value

View File

@ -64,7 +64,7 @@ export const useGraphStore = defineStore('graph', {
const dynamicIdPattern = /^(.+)-(.+)-(\d+)$/
const match = state.selectedEdge.match(dynamicIdPattern)
if (match) {
const [, source, target, index] = match
const [, source, target] = match
foundEdge = state.rawGraph.edges.find(
(edge) => edge.source === source && edge.target === target
)

View File

@ -8,7 +8,6 @@ export const useInfoStore = defineStore('info', () => {
const isLoading = ref(false)
const isLoaded = ref(false)
const debugMode = ref(false)
const error = ref(null) // 错误信息
// 计算属性 - 组织信息
const organization = computed(

View File

@ -1,4 +1,4 @@
import { ref, watch } from 'vue'
import { ref } from 'vue'
import { defineStore } from 'pinia'
import { theme } from 'ant-design-vue'

View File

@ -138,7 +138,7 @@ export const getStatusText = (status) => {
processing: '处理中',
waiting: '等待处理'
}
return map[status] || status
return statusMap[status] || status
}
// 格式化文件大小

View File

@ -18,7 +18,6 @@ export const modelIcons = {
zhipu: zhipuIcon,
siliconflow: siliconflowIcon,
ark: arkIcon,
together: togetherIcon,
openrouter: openrouterIcon,
modelscope: modelscopeIcon,
minimax: minimaxIcon,

View File

@ -56,7 +56,7 @@
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { ref, onMounted, onUnmounted } from 'vue'
import { message } from 'ant-design-vue'
import { dashboardApi } from '@/apis/dashboard_api'
@ -84,7 +84,6 @@ const allStatsData = ref({
//
const loading = ref(false)
const loadingDetail = ref(false)
//
const callStatsRef = ref(null)
@ -133,9 +132,6 @@ const loadAllStats = async () => {
}
}
// loadStats
const loadStats = loadAllStats
//
const handleOpenFeedback = () => {
feedbackModal.value?.show()

View File

@ -221,8 +221,7 @@
{{ getKbTypeLabel(database.kb_type || 'lightrag') }}
</a-tag>
<!-- 保留最后一个使用 / 切分 -->
<a-tag color="blue" v-if="database.embed_info?.name"
:bordered="false">{{
<a-tag color="blue" v-if="database.embed_info?.name" :bordered="false">{{
database.embed_info.name.split('/').slice(-1)[0]
}}</a-tag>
</div>

View File

@ -204,12 +204,9 @@ import { useConfigStore } from '@/stores/config'
import {
UploadOutlined,
SyncOutlined,
GlobalOutlined,
InfoCircleOutlined,
SearchOutlined,
ReloadOutlined,
LoadingOutlined,
HighlightOutlined,
DatabaseOutlined,
ExportOutlined
} from '@ant-design/icons-vue'
@ -578,10 +575,6 @@ const getAuthHeaders = () => {
return userStore.getAuthHeaders()
}
const openLink = (url) => {
window.open(url, '_blank')
}
const getDatabaseName = () => {
const selectedDb = state.dbOptions.find((db) => db.value === state.selectedDbId)
return selectedDb ? selectedDb.label : state.selectedDbId

View File

@ -253,7 +253,7 @@ const fetchGithubStars = async () => {
const data = await response.json()
const stars = Number(data?.stargazers_count)
return Number.isFinite(stars) && stars > 0 ? stars : null
} catch (e) {
} catch {
return null
} finally {
clearTimeout(timer)

View File

@ -3,6 +3,7 @@ import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig(({ mode }) => {
// eslint-disable-next-line no-undef
const env = loadEnv(mode, process.cwd(), '')
return {
plugins: [vue()],