fix(open-3qfx): 免登录建会话补 default 用户上下文,修复 thread_meta 不落库

开放接口 /api/open/3qfx/ask 免登录、无 user context,start_run 写 thread_meta
前先 thread_store.get() 默认 user_id=AUTO,resolve_user_id(AUTO) 在无 context 时
抛 RuntimeError 被 start_run 的 try/except 当「非致命」吞掉,thread_meta 行从未
创建,前端按 metadata.taskId 怎么也搜不到这条会话(run 却已建)。

- 调 start_run 前显式 set_current_user 为 default 用户桶(后台 run_agent task
  在 create_task 时快照此 context,故后台运行也归属 default,符合任务深链对话
  全局共享、按创建者解析文件的语义),thread_meta 正常落库。
- 把 cop_task_detail_* 配置补到实际加载的 offline-backend-20260512/config.yaml
  (此前只加在不生效的 backend/config.yaml)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
吉鑫升andClaude Opus 4.8 committed 2026-06-25 21:40:57 +08:00
1 parent 5f01e8dd03
commit f3f11461de
2 files changed
+33 -1

No files matched your search

@@ -42,6 +42,7 @@ from pydantic import BaseModel, Field
from app.gateway.routers.thread_runs import RunCreateRequest
from app.gateway.services import start_run
from deerflow.config import get_app_config
from deerflow.runtime.user_context import DEFAULT_USER_ID, reset_current_user, set_current_user
logger = logging.getLogger(__name__)
@@ -51,6 +52,18 @@ router = APIRouter(prefix="/api/open/3qfx", tags=["open"])
_THREEQ_BUSINESS_CODE = "3Q"
class _OpenDefaultUser:
"""开放接口(免登录)以「default」用户桶运行的占位 user。
满足 :class:`deerflow.runtime.user_context.CurrentUser` 协议(仅需 ``.id``)。
免登录请求本身没有 user context,而 ``start_run`` 写 thread_meta 时默认 ``user_id=AUTO``,
无 context 会抛 ``RuntimeError`` → 被 ``start_run`` 的 try/except 当「非致命」吞掉 →
**thread_meta 行从未创建**,于是前端按 ``metadata.taskId`` 怎么也搜不到这条会话。
"""
id = DEFAULT_USER_ID
class ThreeQAskRequest(BaseModel):
"""3qfx 开放问答请求体。"""
@@ -174,8 +187,16 @@ async def ask_3qfx(body: ThreeQAskRequest, request: Request) -> ThreeQAskRespons
multitask_strategy="reject",
)
# 免登录 → 无 user context。显式设成「default」用户桶,否则 start_run 写 thread_meta 时
# resolve_user_id(AUTO) 抛 RuntimeError 被吞掉,thread_meta 建不出来、前端按 taskId 搜不到。
# run_agent 是后台 task,在 create_task 时快照本 context,故后台运行也归属 default 用户
# (与 metadata.taskId「任务深链对话全局共享、按创建者解析文件」语义一致)。
# enforce_access=False:开放接口已自行解析 admin 配置的 3Q 智能体,不再按当前(无)登录用户做可见性校验。
record = await start_run(run_body, thread_id, request, enforce_access=False)
token = set_current_user(_OpenDefaultUser())
try:
record = await start_run(run_body, thread_id, request, enforce_access=False)
finally:
reset_current_user(token)
return ThreeQAskResponse(
thread_id=record.thread_id,
+11
View File
@@ -354,6 +354,9 @@ task_deeplink:
test: true # 目的树查询走 mock.purpose_detail 假数据;同时 rwfx 进入「3q 是否完成」预检走 mock.sq_report 假数据
delete_test: true # 删除接口走 mock.delete 假数据(该接口尚未开发完)
action_test: true # 行动→任务解析走 mock.action_detail 假数据(xdfx 行动id→任务id)
# 开放接口 POST /api/open/3qfx/ask 按 taskId 拉取任务详情拼开场白;上游不可达时打开下面开关走 mock.cop_task_detail。
cop_task_detail_test: true
cop_task_detail_url: "https://ch1.b.uat.4.cn/consumer/taskAnalyseSearch/cop-task-detail"
purpose_detail_url: "https://ch1.b.uat.4.cn/consumer/taskAnalyseSearch/getTaskPurposeDetail"
# rwfx 与 xdfx 共用同一删除接口:rwfx 追加 ?taskId=(不传 actionId);xdfx 追加 ?actionId=(不传 taskId,直接不出现)。
delete_url: "https://ch1.b.uat.4.cn/bwjt/dropSixOrSevenData"
@@ -417,3 +420,11 @@ task_deeplink:
taskId: 3338
categoryType: "敌情关键事件 JSON"
contentJson: "[{\"topic\":\"示例研判事件\",\"count\":1}]"
# cop_task_detail_test=true 时原样返回给开放接口 /api/open/3qfx/ask(结构同真实 cop-task-detail 返回)。
cop_task_detail:
data:
id: 2055
overview: "暑期文旅消费高峰期间的舆情态势综合研判与引导任务"
taskDirection: "正向引导 + 风险预警"
taskName: "任务01:暑期文旅舆情综合研判"
taskContent: "围绕暑期文旅消费高峰,对重点城市、重点景区的公众情绪与舆情态势做综合研判,识别情绪拐点与潜在风险,提出正向引导与处置建议。"