文档修改

This commit is contained in:
董宏凯 committed 2026-05-25 18:19:16 +08:00
1 parent dffb8a955b
commit 8c55d4b55d
20 files changed
+1315 -5421

No files matched your search

@@ -1,2 +1,10 @@
/**
* 圆桌规划(Roundtable Planning)模块入口。
*
* 详细架构 / API 字段速查见 `frontend-web/docs/multi-agent-frontend-dev.md`。
* 这里只暴露两个外部使用的组件:
* - `RoundtablePlanningPage`:三步合一的主页面(任务理解 → 多智能体研讨 → 方案展示)。
* - `HighFidelityReport`:Step 3 报告视图,可单独嵌入其它面板(如未来的「方案对比」)。
*/
export { default as RoundtablePlanningPage } from "./pages/RoundtablePlanningPage";
export { HighFidelityReport } from "./components/HighFidelityReport";
@@ -1,4 +1,38 @@
import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
/**
* 圆桌规划主页面(三步合一)。
*
* 这是一个约 3 600 行的单文件页面,通过 `currentStep ∈ {1,2,3}` 在同一容器内切换
* 三步 UI。架构 / 状态机 / SSE 终态语义请先读 `frontend-web/docs/multi-agent-frontend-dev.md`,
* 这里只补充阅读源码时最容易忽略的几条规则:
*
* 1) **不要并行派活**:编排循环 `runOrchestration` 内 `for (const [subName, task] of dispatched)`
* 是**顺序**而非并行——历史上并行触发 N 路 SSE,每路 token 级 setState 整表会卡顿;保持顺序。
*
* 2) **三段式流式气泡**:`appendStreamingDialogue` → `appendToDialogue`(仅增量)→
* `finalizeDialogue`(最终文本 + confidence + `streaming=false`)。三个函数都按 `id`
* 匹配,绝不要用数组下标。
*
* 3) **Step 1 init 防 StrictMode 双 mount**:用单调代数 `step1InitGenRef` 而不是闭包 cancelled
* 标志。任何 setState 完成前都要校验 `myGen === step1InitGenRef.current`。同样模式见
* `RecommendAgentsDialog` 的 `generationRef`。
*
* 4) **离开 Step 2 不销毁线程**:`step2InitRef`/`threadIds` 保留,允许用户回到 Step 2 继续看
* 完整讨论。只有「新建任务 / 加载草稿 / 推荐确认」会复位 `step2InitRef`。
*
* 5) **草稿自动保存只在前进切换时触发**(1→2、2→3),后退不保存,避免覆盖 `furthestStep`。
*
* 6) **顶栏门禁**:Step 2 需 `intentReady`;Step 3 需 `hasConsensus`(leader.dispatched===[])。
*
* 7) **Persona 抽屉**改的 model 不会立即重启编排,下一轮该席位被派活时由 `runOrchestration`
* 读 `agentConfigs[meta.speakerId]?.model` 传入 special。prompt / temp 当前**仅前端记录**。
*
* 8) **常量**:`DEFAULT_MODEL`、`MAX_CYCLES=8`、`COMMANDER_SEAT_ID=1`、`INTENT_READY_RE`。
*
* 调试开关(默认开启):
* window.__MULTI_AGENT_INIT_TIMING__ // /api/multi-agent/init 各阶段耗时
* window.__MULTI_AGENT_DEBUG__ // streamMultiAgent 帧计数 + lastEvent
*/
import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { HighFidelityReport } from "@/roundtable-planning/components/HighFidelityReport";
@@ -858,6 +892,10 @@ export default function RoundtablePlanningPage() {
// parallel meant N concurrent SSE streams each triggering a full-list
// setState on every token delta, which made the browser stutter badly
// when the leader 派活给多个席位。改为顺序后,同一时刻只有一个 SSE 在跑。
//
// ⚠️ 不要改回 Promise.all 并行 —— 详见 multi-agent-frontend-dev.md §5.4
// 与 §12.4。如果未来要并行,先把 step2RoundtableDialogues 换成 Map<id, Bubble>
// 或基于 ref 的局部更新,再放开 N 路 SSE。
for (const [subName, task] of leaderRes.dispatched) {
if (orchestrationCancelRef.current) break;
const meta = agentNameToRole[subName.toLowerCase()];
@@ -1055,7 +1093,11 @@ export default function RoundtablePlanningPage() {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isRoundTableRunning]);
// Adjust budget constraint dynamically
// Budget slider — UI demo only.
// 这是一段**未对接后端**的演示逻辑:滑动预算条只会本地 setBudgetLimit 并 1.5 秒后追加一条
// 模拟智能体口吻的气泡(根据档位选话术)。真实研讨里预算属于约束条件,应由 Step 1 的
// intent.summary.constraints 承载、由总控派活时透传给 sub-agent,而不是这条单滑块。
// 重写此功能前请同步考虑:1) 是否真的需要可调约束;2) 若需要,改成走 runOrchestration 注入新 prompt。
const handleBudgetChange = (newVal: number) => {
setBudgetLimit(newVal);
triggerToast(`💰 研商经费调优约束变更为 ${newVal} 万!各大智能体启动资源重算...`);
@@ -1098,6 +1140,10 @@ export default function RoundtablePlanningPage() {
// Save per-seat agent config overrides. We persist locally only — the next
// time the orchestration loop dispatches to this seat it will read the
// chosen model out of `agentConfigs` and pass it on the streaming call.
//
// 目前 prompt / temp 两个字段**仅前端保留**,后端尚未开放 per-agent override 接口。
// 当后端开放时,应在 streamMultiAgent 的 special 调用上同时传 prompt_override / temperature,
// 而不是改这里的本地存储结构(后者会被 useState 重置)。
const handleSaveAgentAndRecalculate = (id: number) => {
const role = roles.find(r => r.id === id);
const roleName = role?.name || "专家智能体";
@@ -2973,7 +3019,14 @@ export default function RoundtablePlanningPage() {
</div>
)}
{/* Selected Agent Persona Config Drawer / Drawer dialog box */}
{/* Selected Agent Persona Config Drawer / Drawer dialog box
────────────────────────────────────────────────────────
点击圆桌可视化里的某个智能体头像后展开,允许覆写该席位的:
- System Prompt (本地记录,后端覆写未开放)
- 推理模型 (下一轮派活时 runOrchestration 会读 agentConfigs[id].model)
- Temperature (本地记录,后端覆写未开放)
保存按钮 = handleSaveAgentAndRecalculate,不会立即重启编排,只更新
agentConfigs;真正生效在下一次该席位被 leader 派活时。 */}
{selectedAgentId && (
<div className="mx-6 mb-4 p-4.5 bg-gradient-to-r from-[var(--brand-200)]/50 via-[var(--brand-200)]/15 to-white border-2 border-primary rounded-2xl shadow-[0_8px_30px_rgba(245,34,45,0.06)] relative animate-fade-in">
<button