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 # 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: format:
cd backend && uv run ruff format package cd backend && uv run ruff format package
cd backend && uv run ruff check package --fix cd backend && uv run ruff check package --fix
cd backend && uv run ruff check --select I 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, virtual_path_for_thread_file,
) )
from .provider import ( from .provider import (
SandboxConnection,
ProvisionerSandboxProvider, ProvisionerSandboxProvider,
SandboxConnection,
get_sandbox_provider, get_sandbox_provider,
init_sandbox_provider, init_sandbox_provider,
sandbox_id_for_thread, sandbox_id_for_thread,

View File

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

View File

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

View File

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

View File

@ -405,7 +405,13 @@ class SkillsMiddleware(AgentMiddleware):
pure = PurePosixPath(raw if raw.startswith("/") else f"/{raw}") pure = PurePosixPath(raw if raw.startswith("/") else f"/{raw}")
parts = [p for p in pure.parts if p not in ("/", "")] parts = [p for p in pure.parts if p not in ("/", "")]
slug: str | None = None 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] slug = parts[3]
if not is_valid_skill_slug(slug): if not is_valid_skill_slug(slug):

View File

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

View File

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

View File

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

View File

@ -130,8 +130,6 @@ async def build_visible_knowledge_mounts(
return mounts return mounts
def cache_minio_object(*, source_url: str, metadata: dict[str, Any] | None = None) -> Path: def cache_minio_object(*, source_url: str, metadata: dict[str, Any] | None = None) -> Path:
bucket_name, object_name = parse_minio_url(source_url) bucket_name, object_name = parse_minio_url(source_url)
minio_client = get_minio_client() 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 "") etag = str(getattr(stat, "etag", "") or "")
last_modified = getattr(stat, "last_modified", None) last_modified = getattr(stat, "last_modified", None)
version_key = etag or (last_modified.isoformat() if last_modified else "") 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 suffix = Path(object_name).suffix
objects_root = get_kb_cache_root() / "objects" objects_root = get_kb_cache_root() / "objects"

View File

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

View File

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

View File

@ -548,22 +548,6 @@ const isReadOnlyConfig = computed(() => !userStore.isAdmin)
const isSavingConfig = ref(false) const isSavingConfig = ref(false)
const isDeletingConfig = 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 segmentConfigKeys = computed(() => {
const keys = Object.keys(configurableItems.value) const keys = Object.keys(configurableItems.value)
return { return {

View File

@ -108,7 +108,7 @@
<script setup> <script setup>
import { computed, ref } from 'vue' 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 RefsComponent from '@/components/RefsComponent.vue'
import { Copy, Check } from 'lucide-vue-next' import { Copy, Check } from 'lucide-vue-next'
import { ToolCallRenderer } from '@/components/ToolCallingResult' import { ToolCallRenderer } from '@/components/ToolCallingResult'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -206,8 +206,6 @@ import {
EyeOutlined, EyeOutlined,
DownloadOutlined, DownloadOutlined,
DeleteOutlined, DeleteOutlined,
CheckCircleOutlined,
CloseCircleOutlined,
ReloadOutlined ReloadOutlined
} from '@ant-design/icons-vue' } from '@ant-design/icons-vue'
import { evaluationApi } from '@/apis/knowledge_api' 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]) { if (asciiMatch && asciiMatch[1]) {
return asciiMatch[1] return asciiMatch[1]
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -406,9 +406,7 @@ const modelStatus = computed(() => configStore.config?.model_provider_status)
// //
const customProviders = computed(() => { const customProviders = computed(() => {
const providers = configStore.config?.model_names || {} const providers = configStore.config?.model_names || {}
return Object.fromEntries( return Object.fromEntries(Object.entries(providers).filter(([, value]) => value.custom === true))
Object.entries(providers).filter(([key, value]) => value.custom === true)
)
}) })
// //
@ -652,22 +650,6 @@ const customProviderRules = {
env: [{ required: true, message: '请输入API密钥或环境变量', trigger: 'blur' }] 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 = () => { const openAddCustomProviderModal = () => {
customProviderModal.visible = true customProviderModal.visible = true
@ -735,18 +717,14 @@ const saveCustomProvider = async () => {
custom: true custom: true
} }
let result
if (customProviderModal.isEdit) { if (customProviderModal.isEdit) {
result = await customProviderApi.updateCustomProvider( await customProviderApi.updateCustomProvider(
customProviderModal.data.providerId, customProviderModal.data.providerId,
providerData providerData
) )
message.success('自定义供应商更新成功') message.success('自定义供应商更新成功')
} else { } else {
result = await customProviderApi.addCustomProvider( await customProviderApi.addCustomProvider(customProviderModal.data.providerId, providerData)
customProviderModal.data.providerId,
providerData
)
message.success(`自定义供应商 ${customProviderModal.data.providerId} 添加成功`) message.success(`自定义供应商 ${customProviderModal.data.providerId} 添加成功`)
} }
@ -784,7 +762,7 @@ const cancelCustomProvider = () => {
// //
const deleteCustomProvider = async (providerId) => { const deleteCustomProvider = async (providerId) => {
try { try {
const result = await customProviderApi.deleteCustomProvider(providerId) await customProviderApi.deleteCustomProvider(providerId)
message.success('自定义供应商删除成功') message.success('自定义供应商删除成功')
await configStore.refreshConfig() await configStore.refreshConfig()
} catch (error) { } 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 store = useDatabaseStore()
const props = defineProps({ defineProps({
visible: { visible: {
type: Boolean, type: Boolean,
default: true default: true
@ -359,15 +359,12 @@ const props = defineProps({
}) })
// //
const emit = defineEmits(['toggleVisible']) defineEmits(['toggleVisible'])
const searchLoading = computed(() => store.state.searchLoading) const searchLoading = computed(() => store.state.searchLoading)
const queryResult = ref('') const queryResult = ref('')
const showRawData = ref(false) const showRawData = ref(false)
// LightRAG
const isLightRAG = computed(() => store.database?.kb_type?.toLowerCase() === 'lightrag')
// LightRAG // LightRAG
const isLightRAGResult = computed(() => { const isLightRAGResult = computed(() => {
return ( return (
@ -386,7 +383,6 @@ const queryExamples = ref([])
const currentExampleIndex = ref(0) const currentExampleIndex = ref(0)
const loadingQuestions = ref(false) const loadingQuestions = ref(false)
const generatingQuestions = ref(false) const generatingQuestions = ref(false)
const searchConfigModalVisible = ref(false)
// //
let exampleCarouselInterval = null let exampleCarouselInterval = null
@ -417,17 +413,6 @@ const extractFileName = (filePath) => {
} }
} }
//
const openSearchConfigModal = () => {
searchConfigModalVisible.value = true
}
//
const handleSearchConfigSave = (config) => {
console.log('查询测试中的检索配置已更新:', config)
//
}
// //
const loadSampleQuestions = async () => { const loadSampleQuestions = async () => {
if (!store.database?.db_id) return 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 // 使 store
const taskerStore = useTaskerStore() 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 () => { const toggleErrorOnly = async () => {
resultsLoading.value = true 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) => { const formatTime = (timeStr) => {
if (!timeStr) return '-' if (!timeStr) return '-'
const date = new Date(timeStr) const date = new Date(timeStr)

View File

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

View File

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

View File

@ -268,7 +268,6 @@ import { MdPreview } from 'md-editor-v3'
import 'md-editor-v3/lib/preview.css' import 'md-editor-v3/lib/preview.css'
import { useThemeStore } from '@/stores/theme' import { useThemeStore } from '@/stores/theme'
import { import {
Upload,
RotateCw, RotateCw,
Download, Download,
Trash2, Trash2,
@ -346,8 +345,6 @@ watch(selectedPath, (newPath) => {
} }
}) })
const formatRelativeTime = (time) => (time ? dayjs(time).fromNow() : '-')
const toolDependencyOptions = computed(() => const toolDependencyOptions = computed(() =>
(dependencyOptions.tools || []).map((i) => (dependencyOptions.tools || []).map((i) =>
typeof i === 'object' ? { label: i.name, value: i.id } : { label: i, value: i } typeof i === 'object' ? { label: i.name, value: i.id } : { label: i, value: i }
@ -406,7 +403,7 @@ const fetchSkills = async () => {
} }
} }
await fetchDependencyOptions() await fetchDependencyOptions()
} catch (error) { } catch {
message.error('加载失败') message.error('加载失败')
} finally { } finally {
loading.value = false loading.value = false
@ -420,7 +417,9 @@ const fetchDependencyOptions = async () => {
dependencyOptions.tools = data.tools || [] dependencyOptions.tools = data.tools || []
dependencyOptions.mcps = data.mcps || [] dependencyOptions.mcps = data.mcps || []
dependencyOptions.skills = data.skills || [] dependencyOptions.skills = data.skills || []
} catch {} } catch {
// ignore error
}
} }
const syncDependencyFormFromSkill = (skillRecord) => { 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 = () => { const confirmDeleteSkill = () => {
if (!currentSkill.value) return if (!currentSkill.value) return
Modal.confirm({ Modal.confirm({

View File

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

View File

@ -226,7 +226,18 @@
<script setup> <script setup>
import { ref, reactive, computed, onMounted } from 'vue' import { ref, reactive, computed, onMounted } from 'vue'
import { message, Modal } from 'ant-design-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 { subagentApi } from '@/apis/subagent_api'
import { toolApi } from '@/apis/tool_api' import { toolApi } from '@/apis/tool_api'
import { formatFullDateTime } from '@/utils/time' import { formatFullDateTime } from '@/utils/time'

View File

@ -334,18 +334,6 @@ function statusLabel(status) {
return map[status] || 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) { function progressStatus(status) {
if (status === 'failed') return 'exception' if (status === 'failed') return 'exception'
if (status === 'cancelled') return 'normal' if (status === 'cancelled') return 'normal'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -85,7 +85,10 @@ const targetPath = computed(() => parsedArgs.value.path || parsedArgs.value.dir_
const outputMode = computed(() => parsedArgs.value.output_mode || '') const outputMode = computed(() => parsedArgs.value.output_mode || '')
const isFileListResult = computed(() => { 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(() => { const fileMatches = computed(() => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -184,11 +184,9 @@ import DebugComponent from '@/components/DebugComponent.vue'
import { message } from 'ant-design-vue' import { message } from 'ant-design-vue'
import { import {
CircleUser, CircleUser,
UserRoundCheck,
BookOpen, BookOpen,
Sun, Sun,
Moon, Moon,
User,
LogOut, LogOut,
Upload, Upload,
Settings, Settings,
@ -223,7 +221,7 @@ const editedProfile = ref({
phone_number: '' phone_number: ''
}) })
const props = defineProps({ defineProps({
showRole: { showRole: {
type: Boolean, type: Boolean,
default: false 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(() => { const userRoleText = computed(() => {
switch (userStore.userRole) { 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 = () => { const logout = () => {
userStore.logout() userStore.logout()
@ -413,7 +396,7 @@ const handleAvatarChange = async (info) => {
// //
try { try {
avatarUploading.value = true avatarUploading.value = true
const result = await userStore.uploadAvatar(info.file.originFileObj || info.file) await userStore.uploadAvatar(info.file.originFileObj || info.file)
message.success('头像上传成功!') message.success('头像上传成功!')
} catch (error) { } catch (error) {
console.error('头像上传失败:', 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) => { const getRoleClass = (role) => {
switch (role) { switch (role) {
case 'superadmin': case 'superadmin':

View File

@ -220,7 +220,7 @@ const renderCallStatsChart = () => {
params.forEach((param) => { params.forEach((param) => {
total += param.value total += param.value
const truncatedName = truncateLegend(param.seriesName) 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/>` result += `${truncatedName}: ${formatValueForDisplay(param.value)}<br/>`
}) })
const labelMap = { const labelMap = {
@ -230,7 +230,7 @@ const renderCallStatsChart = () => {
tools: '工具调用' tools: '工具调用'
} }
const formattedTotal = formatValueForDisplay(total) 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: { legend: {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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