feat(admin): 任务观测支持下钻 —— 轨迹/输出/评测/DSL
全平台任务页此前只能看列表,点进去什么都没有。现在点一行开抽屉,四个页签:
执行轨迹、最终输出、评测明细、提交时的 DSL。不含审批操作——审批是客户端
用户的行为(桌面端 ApprovalBar),管理端只做观测。
不复用用户面的 /tasks/:id/replay:Task/Eval 都在租户插件作用域内,用请求 ctx
查别的租户的任务不会报错,而是静默返回空输出/空轨迹,UI 上表现为"这任务没
产出",比报错难查得多。新增 admin 端点走 WithoutTenant。
数据取自 sundynix_task 收尾落库的 output/trace 列,不依赖 Redis 流(10min TTL)。
所以这是复盘视图,运行中的任务轨迹为空——UI 里明确写出来,免得被当成轨迹丢了。
修的两处与测试环境失真有关(写测试时暴露的):
- 测试库没配 NamingStrategy,与 OpenPostgres 不一致:多数模型有显式
TableName() 碰巧对得上,但 Task 这类没有的会退化成 "tasks",导致写裸
SQL 的查询在测试里查无此表。现已对齐 sundynix_ 前缀 + 单数表名。
- graph 的 ::text 换成标准 cast(... as text):前者是 Postgres 专有,
换掉后这条查询才能被内存库覆盖。
新增 5 组测试,其中一组专门先证明"租户过滤在测试环境里确实开着"——否则
"跨租户能读到"的断言可能只是因为插件没装,属于假过。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -361,6 +361,34 @@ export interface AdminTask {
|
||||
eval_overall: number;
|
||||
}
|
||||
|
||||
export interface AdminEval {
|
||||
overall: number;
|
||||
rule: number;
|
||||
llm: number;
|
||||
faithful: number;
|
||||
level: string;
|
||||
flags: string; // JSON 数组字符串
|
||||
reason: string;
|
||||
sources: number;
|
||||
corrected: boolean;
|
||||
}
|
||||
|
||||
export interface AdminTaskDetail extends AdminTask {
|
||||
graph: string;
|
||||
output: string;
|
||||
trace: string;
|
||||
eval: AdminEval | null;
|
||||
}
|
||||
|
||||
// 任务下钻。走 /admin 而非用户面的 /tasks/:id/replay —— 后者受租户插件过滤,
|
||||
// 管理员看别的租户的任务会静默拿到空输出/空轨迹(不报错),排查时极具误导性。
|
||||
export async function adminTaskDetail(id: string): Promise<{ task: AdminTaskDetail; exec: unknown[] }> {
|
||||
const res = guard(await fetch(`${ADMIN}/tasks/${encodeURIComponent(id)}`, { headers: authHeaders() }));
|
||||
const d = (await res.json().catch(() => ({}))) as { task?: AdminTaskDetail; exec?: unknown[]; error?: string };
|
||||
if (!res.ok) throw new Error(d.error ?? `task detail failed: ${res.status}`);
|
||||
return { task: d.task as AdminTaskDetail, exec: d.exec ?? [] };
|
||||
}
|
||||
|
||||
// adminTasks 全平台任务流 + 状态计数。status 空=全部;tenant 空=全租户;含 HITL 待审批(status=waiting)。
|
||||
export async function adminTasks(
|
||||
status = "",
|
||||
|
||||
Reference in New Issue
Block a user