"""按 taskId 存取的「大屏绘制智能体」独立页面会话存储 API。 独立大屏页(前端 ``DashboardAgentPage``)按外部 ``task_id`` 存取:聊天记录 (``transcript``)+ 最新结构化数据(``report_json``)。**按 task 共享、不按 user 分权**(open read + 写放开),镜像 ``roundtable_drafts`` 的 by-task 语义。 Routes (prefix ``/api/dashboard-sessions``): GET /by-task/{task_id} 取该 task 的会话(无则 404) PUT /by-task/{task_id} upsert(body: {transcript?, report_json?}) """ from __future__ import annotations from typing import Any from fastapi import APIRouter, HTTPException, Request from pydantic import BaseModel from deerflow.runtime.user_context import get_effective_user_id router = APIRouter(prefix="/api/dashboard-sessions", tags=["dashboard-sessions"]) class DashboardSessionResponse(BaseModel): task_id: str transcript: Any | None = None report_json: str | None = None created_at: str | None = None updated_at: str | None = None class DashboardSessionUpsertRequest(BaseModel): # 只传需要更新的字段:聊天记录 / 结构化数据,二者皆可单独更新。 transcript: Any | None = None report_json: str | None = None def _current_user_id(request: Request) -> str: user = getattr(request.state, "user", None) if user is not None: return str(user.id) return get_effective_user_id() def _get_store(request: Request): store = getattr(request.app.state, "dashboard_session_store", None) if store is None: raise HTTPException(status_code=503, detail="Dashboard session store not available") return store def _project(row: dict[str, Any]) -> DashboardSessionResponse: return DashboardSessionResponse( task_id=row.get("task_id", ""), transcript=row.get("transcript"), report_json=row.get("report_json"), created_at=row.get("created_at"), updated_at=row.get("updated_at"), ) @router.get("/by-task/{task_id}", response_model=DashboardSessionResponse) async def get_dashboard_session(request: Request, task_id: str) -> DashboardSessionResponse: """取该 task 的大屏会话(**不按 user 分权**);无则 404。""" store = _get_store(request) row = await store.get_by_task(task_id) if row is None: raise HTTPException(status_code=404, detail="No dashboard session for this task") return _project(row) @router.put("/by-task/{task_id}", response_model=DashboardSessionResponse) async def upsert_dashboard_session( request: Request, task_id: str, body: DashboardSessionUpsertRequest ) -> DashboardSessionResponse: """按 task upsert 大屏会话(**不按 user 分权**),返回最新快照。""" store = _get_store(request) row = await store.upsert_by_task( task_id, transcript=body.transcript, report_json=body.report_json, user_id=_current_user_id(request), ) return _project(row)