mirror of
https://github.com/ThearchyHelios/AgentLab.git
synced 2026-11-15 06:51:59 +00:00
0d9f1d9339
- 实测 /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
47 lines
2.0 KiB
Python
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
|