server: 任务列表一次聚合回 total_tokens

_list_tasks 在取附件的同时用 _task_tokens_map 一次查
cost_records 按 task_id 求和(GROUP BY),一屏只多一条
查询,不按任务逐个调成本接口。无记录计 0、表不存在时
全计 0 且列表不失败;_task_to_dict 新增 total_tokens
参数,默认 None(非列表调用方不把“未算”写成 0)。
前端 TaskListSection 的 token 栏位此前已接好 total_tokens,
补上后列表行直接显示真数,不再显示 token —;前端注释
与占位文案同步更新。
新测试 test_task_list_tokens.py 3 项:HTTP 列表聚合
(actual+estimated 加总、无记录为 0)、缺表不炸、
_task_to_dict 默认 None。
This commit is contained in:
host committed 2026-10-29 18:27:53 +08:00
1 parent 65a875ada9
commit 9eedee5a3d
4 files changed
+168 -14

No files matched your search

@@ -21,16 +21,12 @@ import type { Task } from "../api/types";
// 累计总时长,服务端需保留首次 started_at 或累加各轮时长,
// 那是服务端字段缺口,不是前端能算出来的。
//
// token:列表接口(_task_to_dict)目前不回任何 token 字段,
// 单任务成本在 GET /tasks/{id}/cost 里(total_tokens、
// actual_tokens、estimated_tokens)。列表行不逐个调 /cost:
// 一屏 N 个任务就是 N 个额外请求,会把列表刷新拖慢、还容易
// 撞限流。所以这里只留栏位:服务端一旦在列表里补
// total_tokens 就显示真数;分项只有 actual/estimated 时加总
// 显示;都没有时显示“token —”,不编造、不估算。
// 服务端补字段的最小改法:_task_to_dict 里给每行附
// cost_records 按 task_id 求和的 total_tokens(或在列表查询
// 里 LEFT JOIN 聚合一次),不需要新端点。
// token:列表接口一次聚合回 total_tokens(服务端
// _task_tokens_map:cost_records 按 task_id 求和,一屏只多
// 一条查询)。列表行不逐个调 /cost:逐个调是一屏 N 个额外
// 请求,会把列表刷新拖慢、还容易撞限流。分项只有
// actual/estimated 时加总显示;都没有(非列表调用方、
// total_tokens 为 null)时显示“token —”,不编造、不估算。
function firstChar(t: Task): string {
const p = (t.prompt || "").trim();
if (p) return [...p][0];
@@ -87,7 +83,7 @@ function tokenOf(t: Task): [string, string] {
if (actual !== null || estimated !== null) {
return [((actual || 0) + (estimated || 0)).toLocaleString() + " token", "token:actual + estimated 分项加总"];
}
return ["token —", "token:列表接口未返回 token 字段(服务端需在任务列表里补 total_tokens);单任务真数在任务详情的成本里可查,本行不逐个调成本接口、不编造"];
return ["token —", "token:本行未带 token 字段;单任务真数在任务详情的成本里可查,本行不逐个调成本接口、不编造"];
}
// GitHub issues-style task list: search on top, the project selector