feat: 任务详情 LLM 请求数(cost_records 存 completions)

This commit is contained in:
host committed 2026-10-30 12:58:41 +08:00
1 parent 2ff8975f43
commit ccb5a8638d
9 files changed
+215 -77

No files matched your search

@@ -5,7 +5,6 @@ import { shortId, fmt } from "../api/client";
import { STATUS_EXPLAIN } from "../api/types";
import { firstChar, durationOf, tokenOf, fmtCostUsd } from "../api/taskMeta";
import DetailActions from "./detail/DetailActions";
import BrowserPanel from "./detail/BrowserPanel";
import ReviewPanel from "./detail/ReviewPanel";
import { CoordPanel, AgentsPanel, ApprovalPanel, PeerPanel, ThreadPanel } from "./detail/DetailLists";
@@ -14,15 +13,15 @@ import { CoordPanel, AgentsPanel, ApprovalPanel, PeerPanel, ThreadPanel } from "
// 审批 + 任务间消息 + 线程, all stacked under the conversation —
// is gone. The same panels now live in four inspector tabs so
// only one group is visible at a time:
// 概览:状态/耗时/token/成本 + 基本信息 + prompt + 操作与结果
// 概览:状态/耗时/token/LLM 请求数/成本 + 基本信息 + prompt + 操作与结果
// 协作:协调子任务 / 子代理链路 / 给其他任务发消息
// 评审与审批:评审队列 / 运行时审批队列
// 线程:线程管理
// Data, actions and sub-sections are unchanged; only grouping
// and visibility changed.
type DetailTab = "overview" | "collab" | "review" | "threads" | "browser";
type DetailTab = "overview" | "collab" | "review" | "threads";
const DETAIL_TABS: Array<[DetailTab, string]> = [
["overview", "概览"], ["collab", "协作"], ["review", "评审与审批"], ["threads", "线程"], ["browser", "浏览器"],
["overview", "概览"], ["collab", "协作"], ["review", "评审与审批"], ["threads", "线程"],
];
export default function TaskDetailPanel() {
const ctx = useConsole();
@@ -59,6 +58,15 @@ export default function TaskDetailPanel() {
<div className="detail-card-label">token</div>
<div className="detail-card-value">{tok}</div>
</div>
<div className="detail-card" title="LLM 请求数 = GET /tasks/{id}/cost 的 llm_requests,即 cost_records 的 completions 之和:host.py 每收到一次 thread/tokenUsage/updated(一次上游补全)计 1,worker 每轮终局记账时累加;估算行(无真实用量)计 0;部署前已记账的老任务没有 completions 列,显示 0 而非回填数">
<div className="detail-card-label">LLM 请求数</div>
<div className="detail-card-value">
{cost === undefined ? "加载中…" : cost === null ? "—" : (cost.llm_requests ?? 0).toLocaleString()}
</div>
{cost === undefined ? <div className="muted">成本加载中…</div>
: cost === null ? <div className="muted">成本明细加载失败,LLM 请求数不可用</div>
: <div className="muted">上游补全次数之和| 轮数 {cost.turns ?? 0} | fallback {cost.fallback_count ?? 0}</div>}
</div>
<div className="detail-card" title="成本明细:GET /tasks/{id}/cost 聚合;美元只计有价行,无价 token 单列;缓存是输入 token 的子集,不另计">
<div className="detail-card-label">成本</div>
<div className="detail-card-value">
@@ -66,7 +74,7 @@ export default function TaskDetailPanel() {
</div>
{cost === undefined ? <div className="muted">成本加载中…</div>
: cost === null ? <div className="muted">成本明细加载失败(“查成本”按钮仍可手动拉取原始 JSON)</div>
: <div className="muted">token {(cost.total_tokens ?? 0).toLocaleString()}(实际 {(cost.actual_tokens ?? 0).toLocaleString()} / 估算 {(cost.estimated_tokens ?? 0).toLocaleString()},缓存 {(cost.cached_input_tokens ?? 0).toLocaleString()},无价 {(cost.unpriced_actual_tokens ?? 0).toLocaleString()})| 轮数 {cost.turns ?? 0} | fallback {cost.fallback_count ?? 0}</div>}
: <div className="muted">token {(cost.total_tokens ?? 0).toLocaleString()}(实际 {(cost.actual_tokens ?? 0).toLocaleString()} / 估算 {(cost.estimated_tokens ?? 0).toLocaleString()},缓存 {(cost.cached_input_tokens ?? 0).toLocaleString()},无价 {(cost.unpriced_actual_tokens ?? 0).toLocaleString()})| fallback {cost.fallback_count ?? 0}</div>}
</div>
</div>
</Card>
@@ -105,8 +113,6 @@ export default function TaskDetailPanel() {
</>) : tab === "review" ? (<>
<Card title="评审队列"><ReviewPanel /></Card>
<Card title="运行时审批队列"><ApprovalPanel /></Card>
</>) : tab === "browser" ? (<>
<Card title="浏览器远控"><BrowserPanel /></Card>
</>) : (<>
<Card title="线程"><ThreadPanel /></Card>
</>)}