feat: taskId 深链会商按任务隔离草稿 + 第三步自动结构化流程图

- 深链 ?taskId=&goPath=*-A 透传 taskId 进会商,按 taskId 隔离存取草稿(一个 taskId 多条、可新建);
  后端新增 GET /api/roundtable-drafts/by-task/{id} 列表 + RoundtableJobRepository.status_map_by_drafts 富化。
- 第三步生成 md 报告后自动结构化输出流程图(仅 taskId 模式):有报告基于报告、无报告基于各席位交付,
  整段内联数据来源逐条抽取;层级优先用业务链总控提示词写明的层级,否则用 stages 的 goal。
- 流程图节点加 group(层级名)标签 + detail(条目名称+理由);强 prompt 压制 coordinatorPrompt 报告锚定,
  禁阶段编号节点;FLOW_STRUCTURE_RULE 精确画法(根=任务、每层每条成节点、按对应关系串分支、排除汇总段落)。
- flow-graph 解析容错:JSON.parse 失败退回正则逐字段抽取,兼容裸换行/尾逗号,避免节点被整体丢弃。
- 修:重开第二步后第三步基于新一轮分析重新生成(复位 step3 闸门 + 中断旧三流)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
fengxiangdebaoziandClaude Opus 4.8 committed 2026-06-17 19:45:35 +08:00
1 parent e6a41dbc97
commit fca39eeaee
17 files changed
+472 -37

No files matched your search

@@ -19,6 +19,7 @@ import type { ReportIntent, UseStep3ReportReturn } from "@/roundtable-planning/h
import type { UseStep3SummaryReturn } from "@/roundtable-planning/hooks/useStep3Summary";
import type { ThreadIdMap } from "@/roundtable-planning/api/multi-agent";
import { stripReasoning } from "@/roundtable-planning/lib/reasoning";
import { useMemo } from "react";
export interface Step3PanelProps {
threadIds: ThreadIdMap | null;
@@ -81,18 +82,25 @@ export function Step3Panel(props: Step3PanelProps) {
seatStubMessages,
} = props;
const seatDeliveries = step2RoundtableDialogues
.filter((d) => d.confidence === "子智能体交付")
.map((d) => ({
sender: String(d.sender ?? ""),
avatarType: String(d.avatarType ?? "blue"),
// 交付内容只保留模型生成的主体输出,剥离 `<think>...</think>` 推理过程
// —— 既用于渲染各席位交付卡片,也会喂给总结/报告模型,避免推理噪声污染。
content: stripReasoning(String(d.content ?? "")),
}));
const seatDeliveries = useMemo(
() =>
step2RoundtableDialogues
.filter((d) => d.confidence === "子智能体交付")
.map((d) => ({
sender: String(d.sender ?? ""),
avatarType: String(d.avatarType ?? "blue"),
// 交付内容只保留模型生成的主体输出,剥离 `<think>...</think>` 推理过程
// —— 既用于渲染各席位交付卡片,也会喂给总结/报告模型,避免推理噪声污染。
content: stripReasoning(String(d.content ?? "")),
})),
[step2RoundtableDialogues],
);
const seatNameMap = Object.fromEntries(
Object.entries(agentNameToRole).map(([k, v]) => [k, v.displayName]),
const seatNameMap = useMemo(
() => Object.fromEntries(
Object.entries(agentNameToRole).map(([k, v]) => [k, v.displayName]),
),
[agentNameToRole],
);
return (