Files
ThearchyHelios 0d9f1d9339 用户看得到的列表补决胜键(复核 R-a9):按名称、时间等可能并列的排序后面补上同一个模型的 id,并列时两种库排出来一样
- 实测 /api/evals/calibers、/api/schedules/trigger-options 按 Workflow.name 排序遇同名并列时 SQLite、PostgreSQL 顺序不同。用 AST 逐个过了一遍 order_by:最后一个排序键是 created_at / updated_at / last_active_at / at / name / 各种 *_at 之类、不唯一的列,又不带 DISTINCT、GROUP BY 的,补「, 模型.id」(降序补 id.desc()),共 104 处,分布在 api、apps、auth、blueprints、chat、data、engine、eval、ledger、look、memory、process、providers、scheduler(runs.py 里的三处在上一个提交里)
- 按唯一列(seq、version、唯一的 name)排的不动;按聚合、coalesce 之类表达式排的说明见 db/postgres
2026-10-19 12:07:06 +08:00

47 lines
2.0 KiB
Python

"""生效记录(BE-2,只读;核实走待办)。设计文档 §3.8、§3.10。预览、回执摘要都是遮罩后的,原文在回执工件里。
开登录后 user 角色:列表不给(那是所有应用、所有运行的生效记录,记录页是给搭建者看的),使用者看动作状态经应用页的
动作状态组件;单条只给它能读的运行(can_read_run)上的,核实待办的卡片要用。"""
from __future__ import annotations
from typing import Any
from fastapi import APIRouter, HTTPException, Query
from sqlalchemy import select
from app.api.deps import can_read_run, current_principal, ensure_role, restricted
from app.db.base import SessionLocal
from app.db.models import ActionRecord
from app.process.actions import describe, row_out
router = APIRouter(prefix="/api/actions", tags=["actions"])
@router.get("")
async def list_actions(
run_id: str | None = None,
app_id: str | None = None,
state: str | None = Query(default=None, description="逗号分隔,如 unknown,failed"),
limit: int = Query(default=100, ge=1, le=500),
) -> dict[str, Any]:
ensure_role("builder")
stmt = select(ActionRecord).order_by(ActionRecord.created_at.desc(), ActionRecord.id.desc()).limit(limit)
if run_id:
stmt = stmt.where(ActionRecord.run_id == run_id)
if app_id:
stmt = stmt.where(ActionRecord.app_id == app_id)
if states := [s.strip() for s in (state or "").split(",") if s.strip()]:
stmt = stmt.where(ActionRecord.state.in_(states))
async with SessionLocal() as session:
return {"items": [row_out(r) for r in (await session.execute(stmt)).scalars()]}
@router.get("/{action_id}")
async def get_action(action_id: str) -> dict[str, Any]:
out = await describe(action_id)
if out is None:
raise HTTPException(404, "生效记录不存在,所属的运行可能已被删除")
if restricted() and not await can_read_run(current_principal(), out["run_id"]):
raise HTTPException(403, "没有权限查看这条生效记录")
return out