console: 任务详情自动显示成本明细

打开详情就自动拉 GET /tasks/{id}/cost(不再只靠
“查成本”按钮出 JSON),详情顶部新一行:美元、总
token(实际/估算、缓存、无价单列)、轮数、fallback
次数;美元小于 1 美分时用 4 位小数,避免小任务
显示成 $0.00 误导成免费;加载中/失败有各自的
弱化文案,成本拉失败不影响详情其它内容;原
“查成本”按钮不动,仍可手动拉原始 JSON。
服务端不用改:成本接口与 _get_task 的 token 聚合
都已在 #150 / 详情 meta 那单里就位。
This commit is contained in:
host committed 2026-10-30 00:39:13 +08:00
1 parent 0f7162934b
commit 994c4ea5d1
7 files changed
+57 -31

No files matched your search

@@ -2,7 +2,7 @@ import { useConsole } from "../context";
import { Card } from "../components/ui";
import { shortId, fmt } from "../api/client";
import { STATUS_EXPLAIN } from "../api/types";
import { firstChar, durationOf, tokenOf } from "../api/taskMeta";
import { firstChar, durationOf, tokenOf, fmtCostUsd } from "../api/taskMeta";
import DetailActions from "./detail/DetailActions";
import ReviewPanel from "./detail/ReviewPanel";
import { CoordPanel, AgentsPanel, ApprovalPanel, PeerPanel, ThreadPanel } from "./detail/DetailLists";
@@ -22,6 +22,9 @@ export default function TaskDetailPanel() {
<div>
状态 <b className={"st-" + t.status}>{t.status}</b>({STATUS_EXPLAIN[t.status] || "未知状态"})
<br /><span style={{ display: "inline-flex", alignItems: "center", gap: 6 }}><span className="issue-first" title={"任务首字:" + fc} aria-hidden="true">{fc}</span><span title={durTitle}>耗时 {dur}</span><span> · </span><span title={tokTitle}>{tok}</span></span>
<br />{ctx.costSummary === undefined ? <span className="muted">成本加载中…</span>
: ctx.costSummary === null ? <span className="muted">成本明细加载失败(“查成本”按钮仍可手动拉取原始 JSON)</span>
: <span title="成本明细:GET /tasks/{id}/cost 聚合;美元只计有价行,无价 token 单列;缓存是输入 token 的子集,不另计">成本 {fmtCostUsd(ctx.costSummary.usd_micros)} | token {(ctx.costSummary.total_tokens ?? 0).toLocaleString()}(实际 {(ctx.costSummary.actual_tokens ?? 0).toLocaleString()} / 估算 {(ctx.costSummary.estimated_tokens ?? 0).toLocaleString()},缓存 {(ctx.costSummary.cached_input_tokens ?? 0).toLocaleString()},无价 {(ctx.costSummary.unpriced_actual_tokens ?? 0).toLocaleString()})| 轮数 {ctx.costSummary.turns ?? 0} | fallback {ctx.costSummary.fallback_count ?? 0}</span>}
<br />任务 {t.id} | turn {shortId(t.turn_id)} | root turn {shortId(t.root_turn_id)}
<br />executor {t.executor || ""} | 主机 {t.worktree_host || ""}
<br />模型 {t.model || "默认"} | 强度 {t.effort || "默认"}