diff --git a/frontend-web/src/open-canvas/contexts/AIWritingContext.tsx b/frontend-web/src/open-canvas/contexts/AIWritingContext.tsx index 92d797ab..0b6834c4 100644 --- a/frontend-web/src/open-canvas/contexts/AIWritingContext.tsx +++ b/frontend-web/src/open-canvas/contexts/AIWritingContext.tsx @@ -528,8 +528,14 @@ export function AIWritingProvider({ children }: { children: ReactNode }) { dispatch({ type: 'pause' }); }, []); - // 「继续」:清掉当前阶段流式缓冲后,从最近的 checkpoint 重新驱动 graph 续跑 + // 「继续」:清掉当前阶段流式缓冲后,从最近的 checkpoint 恢复 graph 续跑 // (会重跑当前未完成的阶段,已完成阶段不丢)。同时用于断网后 run 已死的兜底恢复。 + // + // **关键**:必须带一个 `command`(哪怕是空对象),后端 worker 才会把它翻成 + // `langgraph.types.Command` 让 Pregel **从最近 checkpoint 恢复**(与 4 个干预卡续跑同机制); + // 不带 command 时 worker 按 graph_input **起新一轮**=从图入口 intent 重跑(就是之前 + // "暂停后继续又从识别意图开始" 的根因,见 runtime/runs/worker.py 注释)。空 Command + // 没有 interrupt 可消费 → Pregel 直接续跑 checkpoint 里挂起的当前阶段节点。 const resumeWriting = useCallback(() => { const stream = streamRef.current; if (!stream) { @@ -541,6 +547,7 @@ export function AIWritingProvider({ children }: { children: ReactNode }) { void (async () => { try { await stream.submit(undefined, { + command: {}, streamMode: [...WRITING_STREAM_MODE], ...RESILIENT_RUN_OPTS, ...(resumeModelName ? { config: { configurable: { model_name: resumeModelName } } } : {}),