diff --git a/backend/server/routers/mention_router.py b/backend/server/routers/mention_router.py index a8e8b068..b25ed42b 100644 --- a/backend/server/routers/mention_router.py +++ b/backend/server/routers/mention_router.py @@ -35,8 +35,19 @@ async def search_mention_files( # NOTE: 校验 thread 归属权,防止恶意用户传入他人 thread_id 遍历文件 conv_repo = ConversationRepository(db) conversation = await conv_repo.get_conversation_by_thread_id(thread_id) - if not conversation or conversation.user_id != user_id or conversation.status == "deleted": - raise HTTPException(status_code=404, detail="对话线程不存在") + if conversation: + if conversation.user_id != user_id or conversation.status == "deleted": + raise HTTPException(status_code=404, detail="对话线程不存在") + else: + # NOTE: 如果是尚未在数据库记录的全新对话(还未发送首条消息),在格式校验安全的前提下放行。 + # 此时该 thread 专属的 uploads/outputs 目录还没创建或为空, + # 用户仅能安全地搜索到自己全局的工作区 (workspace) 文件。 + try: + from yuxi.agents.backends.sandbox.paths import _validate_thread_id + + _validate_thread_id(thread_id) + except ValueError: + raise HTTPException(status_code=400, detail="非法的 thread_id 格式") return await search_mention_files_in_index( thread_id=thread_id, diff --git a/web/src/components/MessageInputComponent.vue b/web/src/components/MessageInputComponent.vue index 07c2a4e6..06e683ca 100644 --- a/web/src/components/MessageInputComponent.vue +++ b/web/src/components/MessageInputComponent.vue @@ -425,8 +425,9 @@ const updateMentionItems = (query = '') => { subagents: filterItems(subagentItems) } - // 如果有关键字,且已绑定会话,则触发后端高性能搜索进行补充 - if (query && props.threadId) { + // NOTE: 如果是尚未开始对话的全新会话,此时 threadId 为空,允许使用临时占位 ID 检索用户全局的工作区文件 + if (query) { + const activeThreadId = props.threadId || 'new_thread_placeholder' clearTimeout(mentionSearchTimer) mentionSearchTimer = setTimeout(async () => { // 物理中断之前的未完成 HTTP 请求 @@ -440,7 +441,7 @@ const updateMentionItems = (query = '') => { try { const responseData = await searchMentionFiles( - props.threadId, + activeThreadId, query, activeAbortController.signal )