Files
deerflow-code/frontend-web/src/roundtable-planning/components/Step3Panel.tsx
T
fengxiangdebaoziandClaude Opus 4.8 fca39eeaee 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>
2026-06-17 19:45:35 +08:00

133 lines
4.9 KiB
TypeScript

/**
* Step 3 主面板 —— 方案结果展示。
*
* 当前是 `HighFidelityReport` 的薄壳;放它在这里只是为了让 Step 1 / Step 2 /
* Step 3 三步在主页面里以同样的导入风格出现,方便阅读。
*
* Step 3 真实逻辑请改 `HighFidelityReport.tsx` —— 包括各席位 artifact
* 拉取 / 文本类预览 / window.open 下载 / 「重新起草」按钮等。
*/
import { HighFidelityReport } from "@/roundtable-planning/components/HighFidelityReport";
import type {
DraftStep3Snapshot,
DraftStep3SummarySnapshot,
} from "@/roundtable-planning/api/drafts";
import type { ModelOption } from "@/roundtable-planning/components/Step3ReportMode";
import type { Step2Dialogue } from "@/roundtable-planning/hooks/useStep2Orchestration";
import type { UseStep3DashboardReturn } from "@/roundtable-planning/hooks/useStep3Dashboard";
import type { ReportIntent, UseStep3ReportReturn } from "@/roundtable-planning/hooks/useStep3Report";
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;
coordinatorName: string | null;
consensusText: string;
hasConsensus: boolean;
step2RoundtableDialogues: Step2Dialogue[];
agentNameToRole: Record<
string,
{ speakerId: number; avatarType: string; displayName: string }
>;
/** Step 1 结构化意图 + 当前模型 —— 透传给「结果绘制」的方案可视化智能体。 */
intentReady: ReportIntent | null;
selectedModel: string;
/** 可选模型列表 + 加载态 + 切换器 —— 透传给「结果绘制」的模型选择。 */
availableModels: ReadonlyArray<ModelOption>;
modelsLoading: boolean;
setSelectedModel: (model: string) => void;
/** 草稿里已存的上次绘制结果 + 完成回调 —— 透传给「结果绘制」做持久化。 */
savedReport?: DraftStep3Snapshot | null;
onReportSaved?: (snapshot: DraftStep3Snapshot) => void;
/** 业务链写给总控的编排提示 —— 注入「总结报告」智能体。 */
coordinatorPrompt?: string | null;
/** 草稿里已存的上次总结结果 + 完成回调 —— 透传给「总结报告」做持久化。 */
savedSummary?: DraftStep3SummarySnapshot | null;
onSummarySaved?: (snapshot: DraftStep3SummarySnapshot) => void;
/** 页面层常驻的三个 Step3 生成流(2026-06-13 提升:切走不断流,进入续看)。 */
summaryFlow: UseStep3SummaryReturn;
reportFlow: UseStep3ReportReturn;
dashboardFlow: UseStep3DashboardReturn;
onReset: () => void;
/** Step 2 沙箱预览产出文件(与第二步相同)。 */
openArtifactPreview: (threadId: string, path: string) => void;
seatStubMessages: Record<string, unknown[]>;
}
export function Step3Panel(props: Step3PanelProps) {
const {
threadIds,
coordinatorName,
consensusText,
hasConsensus,
step2RoundtableDialogues,
agentNameToRole,
intentReady,
selectedModel,
availableModels,
modelsLoading,
setSelectedModel,
savedReport,
onReportSaved,
coordinatorPrompt,
savedSummary,
onSummarySaved,
summaryFlow,
reportFlow,
dashboardFlow,
onReset,
openArtifactPreview,
seatStubMessages,
} = props;
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 = useMemo(
() => Object.fromEntries(
Object.entries(agentNameToRole).map(([k, v]) => [k, v.displayName]),
),
[agentNameToRole],
);
return (
<HighFidelityReport
threadIds={threadIds}
coordinatorName={coordinatorName}
consensusText={consensusText}
hasConsensus={hasConsensus}
seatDeliveries={seatDeliveries}
seatNameMap={seatNameMap}
intentReady={intentReady}
selectedModel={selectedModel}
availableModels={availableModels}
modelsLoading={modelsLoading}
setSelectedModel={setSelectedModel}
savedReport={savedReport}
onReportSaved={onReportSaved}
coordinatorPrompt={coordinatorPrompt}
savedSummary={savedSummary}
onSummarySaved={onSummarySaved}
summaryFlow={summaryFlow}
reportFlow={reportFlow}
dashboardFlow={dashboardFlow}
onReset={onReset}
openArtifactPreview={openArtifactPreview}
seatStubMessages={seatStubMessages}
/>
);
}