- 新增带导航+侧边栏的独立页面 DashboardAgentPage:按 taskId 取/存会话, 有有效 report-json 直显大屏(DashboardApp),否则进生成过程(不自动跳)+输入框可改 - 后端 dashboard_sessions 存储(model/sql/__init__)+路由/by-task(GET/PUT 不分权) + deps/app/models 接线;新表靠 create_all 建,无迁移 - 扩展 useStep3Dashboard:buildInitialPrompt(输入任务JSON) + hydrateTranscript(恢复聊天记录) - 抽出共享 DashboardChatPanel;report-template 增 buildDashboardPromptFromJson - 输入 seam core/auth/dashboard-input:JSON 接口未就绪先用占位/演示数据兜底 - 路由 StrategyRoutes dashboard-agent + 侧边栏「问答管理→大屏绘制」 - 圆桌业务链卡片「关系图」改横向布局 - 顺带提交:AIWritingContext 登录切换处理、thread-access-error helper Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
2.9 KiB
Python
85 lines
2.9 KiB
Python
"""按 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)
|