fix(web): 智能体汇报展示层兜底与进度口径(FIX-7)

- 汇报正文里的 UUID、能力 ID、原因码展示时换成名称和人话,原文收进「正文原文」,历史不改
- 步骤进度统一 stepProgress:分子只数完成,跳过单独计(「4/6 · 跳过 2」)
- 进度行不再把失败的调用算进动作计数(3 次被拒的派发曾写成「派出了 5 个子会话」);
  实际结果行按会话树显示派出的子会话数
- 会话标题里的 ISO 时间与 download_failed 等码转人话

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-30 00:00:03 +08:00
1 parent 1b22bb5131
commit 417af9f253
9 files changed
+393 -27

No files matched your search

@@ -17,6 +17,7 @@ import { Button } from "~/components/ui/button.tsx";
import { Textarea } from "~/components/ui/textarea.tsx";
import { errorMessage } from "~/lib/api.ts";
import { cn, formatDateTime } from "~/lib/utils.ts";
import { stepProgress } from "./conversation-model.ts";
import type { ApprovalView, OptionsView } from "./use-agent-stream.ts";
// 自动化优先的会话交互(AG-2):步骤清单(agent.plan)、方案选择(agent.propose_options)、步骤处的审批卡。
@@ -54,11 +55,10 @@ export function RunPlan({
fill?: boolean;
}) {
if (!plan?.steps.length) return null;
const done = plan.steps.filter((s) => s.status === "done" || s.status === "skipped").length;
const current = plan.steps.find((s) => s.status === "running") ?? plan.steps.find((s) => s.status === "pending");
const failed = plan.steps.some((s) => s.status === "failed");
const progress = stepProgress(plan.steps);
const failed = progress.failed > 0;
if (compact) {
const pct = Math.round((done / plan.steps.length) * 100);
const pct = progress.pct;
return (
<section aria-label="步骤进度" className="rounded-xl border border-border/70 px-3 py-2">
<div className="flex min-w-0 items-center gap-2 text-meta">
@@ -67,11 +67,9 @@ export function RunPlan({
className={cn("size-3.5 shrink-0 text-muted-foreground", failed && "text-destructive")}
/>
<span className="shrink-0 text-foreground tabular-nums">
步骤 {done}/{plan.steps.length}
</span>
<span className="min-w-0 flex-1 truncate text-muted-foreground">
{current ? `当前:${current.title}` : failed ? "有步骤失败" : "全部完成"}
步骤 {progress.done}/{progress.total}
</span>
<span className="min-w-0 flex-1 truncate text-muted-foreground">{progress.status}</span>
</div>
<div className="mt-1.5 h-1 overflow-hidden rounded-full bg-foreground/[0.08]" aria-hidden>
<div
@@ -89,6 +87,7 @@ export function RunPlan({
<TodoList
title="步骤"
items={planTodoItems(plan.steps)}
count={progress.count}
defaultOpen
collapseOnComplete={!fill && !active}
maxHeightClassName={fill ? "max-h-none" : "max-h-56"}