diff --git a/frontend-web/src/open-canvas/components/ai-writing/AIWritingPanel.tsx b/frontend-web/src/open-canvas/components/ai-writing/AIWritingPanel.tsx index 8313c76f..8c488573 100644 --- a/frontend-web/src/open-canvas/components/ai-writing/AIWritingPanel.tsx +++ b/frontend-web/src/open-canvas/components/ai-writing/AIWritingPanel.tsx @@ -17,6 +17,24 @@ import { useCanvasGraphContext } from '../../contexts/CanvasGraphContext'; import { useAIWriting } from '../../hooks/useAIWritingStream'; import { useAIWritingSessions } from '../../hooks/useAIWritingSessions'; import { adminCleanupAIWritingSessions } from '../../api/ai-writing-sessions'; + +/** + * 暂停 / 继续功能开关(默认 false = 关)。 + * + * 历史背景:legacy 路径下,为了让用户点"停止"后还能"继续",引入了 per-worker + * 内存 dict(``_event_queues`` / ``_session_pending_pause``)。多 worker 部署下 + * 这些 dict 互相看不见 → SSE 重连失败 / "会话丢失" → 触发了整个 ai-writing-优化.md + * 的迁移计划。 + * + * 当前 LangGraph Server 路径下架构已无 per-worker 状态,但 ``stream.stop()`` 仅 + * 取消客户端 SSE 订阅,**不会真正暂停后端 run**(LLM 继续烧 token);``resume`` + * 也无法重新订阅同一个 run。这是个产品语义没想清楚的功能,先关掉。 + * + * 后期想清楚怎么做"真·暂停"(``client.runs.cancel(run_id, action='interrupt')`` + * 保留 checkpoint)+ "真·继续"(``client.runs.joinStream`` 续上原 run)时, + * 把这个 flag 翻成 true 即可,UI / hook 全套代码都已就位。 + */ +const ENABLE_PAUSE_RESUME_UI = false; import { AIWritingForm } from './AIWritingForm'; import { AIWritingTimeline } from './AIWritingTimeline'; import { InterventionCard } from './InterventionCard'; @@ -48,8 +66,7 @@ const STATUS_LABEL: Record = { export function AIWritingPanel() { const navigate = useNavigate(); const { setArtifact } = useCanvasGraphContext(); - // pauseWriting / resumeWriting 当前 UI 不暴露(见 header 注释),从解构里省略避免 unused 警告 - const { state, startWriting, submitIntervention, reset } = useAIWriting(); + const { state, startWriting, submitIntervention, pauseWriting, resumeWriting, reset } = useAIWriting(); const { sessions, loading: sessionsLoading, refresh, rename, remove } = useAIWritingSessions(); const { articleTypes, refresh: refreshArticleTypes } = useArticleTypes(); @@ -270,12 +287,36 @@ export function AIWritingPanel() { 新建 )} - {/* ⏸️/▶️ "停止 / 继续" 按钮暂时隐藏 —— - 当前实现是 stream.stop() 断 SSE 订阅而非真正取消后端 run, - 点了停止后端继续烧 token,点继续 useStream 也不会自动重连, - 用户体验是半残废的。等后期想清楚怎么"真·暂停"(cancel run + - 保留 checkpoint)+ "真·继续"(重新订阅同一 run)再加回来。 - hook 里的 pauseWriting / resumeWriting 代码保留以便后期复用。 */} + {/* ⏸️/▶️ "停止 / 继续" 由 ENABLE_PAUSE_RESUME_UI 控制(默认 false 隐藏)。 + 后期把 flag 翻成 true 即可恢复,UI / hook 全套代码都已就位。 */} + {ENABLE_PAUSE_RESUME_UI && isRunning && !state.isPaused && ( + + )} + {ENABLE_PAUSE_RESUME_UI && state.isPaused && ( + <> + + + + )} {(isDone || isError) && (