deerflow-code/frontend-web/docs/ai-writing-对话驱动写作台-实现方案.md
2026-09-07 18:24:55 +08:00

33 KiB
Raw Permalink Blame History

AI 写作「对话驱动写作台」实现方案(可落地版)

需求:复制现有 AI 写作代码,新增一个独立页面(原页面/原路由零改动)。在新页面里 大改交互流程——去掉「素材收集 / 大纲规划 / 作家写作 / 编辑审核」四个阶段干预卡里的输入框, 只保留原来的确认按钮;在页面底部新增一个统一的多行智能输入框,具备强意图理解能力: 重新搜索、新增检索词、添加检索素材、重新规划大纲、按要求改大纲、提修改意见、审核意见、 素材不足继续搜集、对写作内容提问……覆盖现有全部交互甚至更多。

交互节奏不变:一步一确认——进行到某个专家阶段时,交互就针对该专家(阶段作用域); 用户可以点原来的确认按钮,也可以在底部输入框里发「继续下一步」的意图推进。 意图拿不准时主动向用户发起协助/澄清,绝不盲目触发高代价动作(定稿 / 重搜等)。

本文是实现指引,落地时按第 9 节路线图分阶段推进。文中所有文件路径、符号名均对齐当前代码。


1. 现状梳理(改造地基)

现有 AI 写作是一套独立 LangGraph 子系统(不是 lead_agent),前后端都已成型、可复用。

1.1 后端 ai_writing graph

  • 图工厂:offline-backend-20260512/backend/packages/harness/deerflow/agents/ai_writing/graph.py (make_ai_writing_graph,registered as assistant_id="ai_writing")
  • 状态:.../ai_writing/state.py(AIWritingState)
  • 四个「阶段大脑」节点:
阶段 节点 文件
素材收集 researcher nodes/researcher.py
大纲规划 writer_outline nodes/writer_outline.py
作家写作 writer_draft nodes/writer_draft.py
编辑审核 editor nodes/editor.py
  • 五个暂停点(interrupt(),Command(resume=payload) 续跑)——这是对话改造的核心可复用资产:
pause_point 语义 现有 action
material_confirm 素材确认 confirm / re_search / enable_skill_search
outline_confirm 大纲确认 confirm / re_outline
draft_confirm 草稿确认 to_editor / finalize / user_revise
review_confirm 编辑打回确认 accept_review / force_finalize
section_help 素材不足求助 section_help(+sectionDecisions)
  • resume 载荷(UserInterventionPayload,types/ai-writing.ts)字段:action、approvedMaterialIds、 userQuery(自然语言补充检索)、editedOutline、outlineFeedback、userRevisionNotes、 overrideVerdict、selectedIssueIndices、sectionDecisions。 协议已同时支持「自然语言 + 结构化 action」——这是对话层能复用的关键。

结论:状态机 / 流式 / 暂停·续跑协议 / 持久化都可复用,无需重写引擎。改造本质是 「把分散在干预卡里的输入框,换成一个底部智能输入框 + 意图路由层」,再把意图翻译回现有 action + payload;仅少量新意图(对内容提问、素材不足自动回退重搜、追加审核意见)需新增能力。

1.2 前端 open-canvas 子系统

  • 主页面:frontend-web/src/open-canvas/pages/AIWritingPage.tsx
    • 路由注册:open-canvas/routes/OpenCanvasRoutes.tsx(/page/canvas/ai-writing/*)、 pages/WorkspaceRoutes.tsx(/page/workspace/ai-writing/*)、pages/NotebookAIWritingPage.tsx
  • 状态机 + 流式:contexts/AIWritingContext.tsx(useReducer + LangGraph useStream,assistantId:'ai_writing')
  • 事件翻译 / reducer:hooks/useAIWritingStream.ts
  • 类型:types/ai-writing.ts
  • 左栏面板:components/ai-writing/AIWritingPanel.tsx(时间线 + 干预卡 + 状态栏;idle 时挂启动表单)
  • 要改造的输入 UI(本次重点):
    • 干预卡 components/ai-writing/InterventionCard.tsx:内含 MaterialConfirmCard(素材:有 MaterialsToolbar 输入框)、 OutlineConfirmCard(大纲:有 feedback textarea)、 DraftConfirmCard(草稿:有「修改意见」textarea)、 ReviewConfirmCard(审核:有「补充修改指令」textarea)、 SectionHelpCard(素材不足:按钮组)。 每张卡里都既有输入框又有确认/动作按钮——本次要去掉输入框、保留按钮。
    • 启动表单 components/ai-writing/AIWritingForm.tsx(idle 阶段的配置表单)——本次由底部输入框接管启动。
  • 已存在的对话原型(可借鉴):components/ai-writing/WritingSetupChat.tsx (useThreadStream 起 lead_agent 线程 + setup_writing 审批卡回填表单;仅管启动前配置,不直接复用)。
  • 底部输入框可直接复用 UI 组件:@/components/ai-elements/prompt-input (PromptInput / PromptInputTextarea / PromptInputSubmit / PromptInputFooter,见 WritingSetupChat)。

2. 目标与范围

2.1 必须满足

  1. 复制式新增:新目录 / 新路由 / 新侧边栏入口,旧页面、旧路由、旧组件零改动(「初始的不用动」)。
  2. 页面底部单一多行智能输入框接管全流程交互;四个阶段干预卡里的输入框全部移除。
  3. 保留确认按钮:每个阶段到达暂停点时,消息流里仍渲染产物卡 + 原来的确认/动作按钮 (素材「确认素材」、大纲「确认大纲」、草稿「让编辑审核 / 确认定稿」、审核「按编辑意见修改 / 强制定稿」、 素材不足的三选一按钮)。用户点按钮或在底部输入框发自然语言意图二选一均可推进。
  4. 强意图理解:把用户自由文本准确路由到正确动作,覆盖现有全部交互 + 更多(见 3.2)。
  5. 阶段作用域:意图解析必须知道「当前停在哪个专家阶段」,把同一句话按当前阶段翻译成对应 action。
  6. 素材不足自动回退重搜:修改意见需要的信息现有素材没有时,先重搜补素材、补完自动继续原意图。
  7. 拿不准就协助:低置信意图不猜着执行,走澄清追问(clarify)或用户协助。
  8. 保留右侧草稿实时预览(可编辑)与时间线 / 进度展示。

2.2 明确不做(本期)

  • 不改旧 AIWritingPage 及其 AIWritingForm / InterventionCard(这两个是要在副本里改的)。
  • 不替换 ai_writing graph 四个阶段大脑逻辑,不动五个暂停点 / checkpoint / 持久化。
  • 不引新状态管理库(继续 useReducer + useStream)。

2.3 复制策略(关键决策)

「复制一份」= 复制会被大改的表现层组件(页面 + 干预卡 + 面板),复用不改的引擎层:

复制(新建副本,大改) 复用(原样,不改;仅对 types 做追加式扩展)
新页面 AIWritingChatPage.tsx contexts/AIWritingContext.tsx(状态机 + 流式)
新面板 WritingChatPanel.tsx(消息流 + 底部输入框) hooks/useAIWritingStream.ts(事件 → state)
新消息卡 chat-cards/*(产物卡+确认按钮,无输入框) components/ai-writing/AIWritingDraftPanel.tsx(右侧草稿预览)
新意图客户端 api/ai-writing-intent.ts 各流式展示子组件(MaterialsCard/OutlineCard/ReviewCard/SkillStepsCard…)
(可选)新 contexts/WritingChatContext.tsx 包一层「pending 意图 / 澄清态」 types/ai-writing.ts(只加字段不改旧字段,保证旧页面不受影响)

不复用、也不改 的三个「输入框组件」:AIWritingForm / InterventionCard / WritingFormContext—— 旧页面继续用它们,新页面完全不引用它们。这样「初始的不用动」得到硬保证。

为什么复用 AIWritingContext 而不复制它?它不含任何输入框 UI,只是「状态机 + 与后端 graph 的 流式桥」,复用它不会改动旧页面的任何呈现(旧页面照常在自己的 Provider 实例里跑)。复用能显著 降低维护成本、避免两套引擎漂移。若要绝对物理隔离,也可整目录复制 AIWritingContext + useAIWritingStream 到新目录——推荐先复用,仅当后续需要给对话态加大量图内新协议时再分叉。


3. 核心设计

3.1 三层结构

┌──────────────────────────────────────────────────────────────┐
│  对话 UI 层(新)  WritingChatPanel                             │
│   - 消息流:用户消息 + AI 阶段产物卡(含【保留的确认按钮】)+ 进度   │
│   - 底部:统一多行智能输入框(唯一自由输入入口)                    │
│   - 右侧:草稿实时预览(复用 AIWritingDraftPanel)                │
└───────────────┬──────────────────────────────────────────────┘
                │ 用户自然语言(+ 当前 status/pausePoint 上下文)
                ▼
┌──────────────────────────────────────────────────────────────┐
│  意图解析层(新,核心)  POST /api/ai-writing/sessions/{id}/intent │
│   输出:{ intent, pausePoint, action, payload,                  │
│          needResearch, researchQuery, answer, confidence, clarify }│
└───────────────┬──────────────────────────────────────────────┘
                │ 结构化 action + payload
                ▼
┌──────────────────────────────────────────────────────────────┐
│  执行层(复用现有 AIWritingContext)                             │
│   idle → startWriting(AIWritingRequest)                         │
│   暂停 → submitIntervention(UserInterventionPayload)            │
│   问答 → 旁路回答(不改写作状态)                                 │
│   素材不足 → 先重搜、缓存 pending、补完自动续跑                     │
└──────────────────────────────────────────────────────────────┘

设计原则:意图解析层是「翻译官」——把自由文本翻译成执行层已经懂的指令。能复用 action + payload 的绝不新造协议;确认按钮点击直接走执行层(不经意图层,零延迟、零误判)。

3.2 意图分类体系(覆盖全流程 + 更多)

按「意图 → 触发时机(当前 status/pausePoint)→ 映射执行」组织,即意图解析引擎的目标 schema。 「甚至更多」 = G(问答)、H(控制)、以及 B/C/D/E 里的「素材不足自动回退重搜」。

A. 启动类(status = idle)

意图 用户说法示例 映射
start_writing 「写一篇关于新能源出口的深度分析,2000 字」 解析成 AIWritingRequest → startWriting()
start_with_outline 「按这个大纲写:…」 AIWritingRequest.userOutline
start_imitate 「仿照这篇样文写…」 writingModeType='imitate' + sampleText

B. 素材类(pausePoint = material_confirm)

意图 示例 映射
confirm_materials 「素材可以,继续 / 下一步」 {action:'confirm', approvedMaterialIds}
research_again 「重新搜索素材」 {action:'re_search'}(无 userQuery=覆盖式重检)
add_material/add_keyword 「再补点关于 X 的素材」「加个关键词 Y」 {action:'re_search', userQuery:'X/Y'}(追加)
select_materials 「只用第 1、3 条」 {action:'confirm', approvedMaterialIds:[…]}
drop_materials 「去掉第 2 条」 同上(反选后的子集)

C. 大纲类(pausePoint = outline_confirm)

意图 示例 映射
confirm_outline 「大纲 OK,开始写」 {action:'confirm'}
reoutline 「重写大纲」 {action:'re_outline'}(feedback 可空)
revise_outline 「第二章拆成两节」「调整顺序」 {action:'re_outline', outlineFeedback:自然语言}

D. 写作 / 草稿类(pausePoint = draft_confirm)

意图 示例 映射
to_editor 「交给编辑审核」 {action:'to_editor'}
finalize 「就这样定稿」 {action:'finalize'} (高代价:低置信必澄清)
revise_draft 「第三段太啰嗦,精简」「补个 2024 案例」 {action:'user_revise', userRevisionNotes:意见}
rewrite_section 「重写第二章」 user_revise + 章节定位写进 notes
change_tone/style 「更口语一点 / 更正式」 user_revise + notes
apply_review(若已有审核结果) 「按编辑意见改」「只接受第 1、2 条」 {action:'user_revise', selectedIssueIndices:[…]}

E. 编辑审核类(pausePoint = review_confirm)

意图 示例 映射
accept_review 「按编辑意见改」 {action:'accept_review', selectedIssueIndices}
partial_accept_review 「只接受第 1、2 条」 accept_review + selectedIssueIndices 子集
add_review_opinion 「再补一条:核查数据准确性」 accept_review + userRevisionNotes(并入补充指令,现协议已支持)
force_finalize 「不改了,强制定稿」 {action:'force_finalize', overrideVerdict:true} (高代价:必澄清)

F. 素材不足求助类(pausePoint = section_help)

意图 映射
section_supplement {action:'section_help', sectionDecisions:[…'supplement']}
section_loose sectionDecisions:[…'loose']
section_delete sectionDecisions:[…'delete']

G. 问答类(新;任意 status;旁路,不改写作状态)

意图 示例 映射
ask_about_content 「第二章讲了啥?」「为什么用这个论点?」 意图节点直接带回 answer,对话流渲染(见 5.4)
ask_meta 「现在到哪步了?」「用了哪些素材?」 读当前 state 直接回答,不走图

H. 控制类(新 / 半新)

意图 映射
next_step(通用「继续/下一步」) 按当前 pausePoint 映射到该阶段的默认确认(material/outline→confirm,draft→to_editor…;等价点确认按钮)
restart_stage 重跑当前阶段(复用 resumeWriting() 空 command 续跑)
run_background 转后台自动跑:suspendAIWritingToBackground()
cancel pauseWriting()(stream.stop())
unknown/clarify 无法判定 → 反问澄清 / 用户协助(防误触发硬指标)

3.3 「素材不足自动重搜」判定与回退(用户强调点)

触发:用户在大纲/草稿/审核阶段提出修改意见,但意见需要的信息现有素材里没有。

判定来源(组合):

  1. 意图节点直接判:把「素材摘要(keywords + 每条 title/source)」喂给意图 prompt,让它判断 「这条意见能否用现有素材满足」;不能 → needResearch=true + researchQuery。
  2. 执行阶段兜底:writer_draft 严格模式已有 blocked_sections → section_help 暂停点, 对话层把它翻译成「素材不足,是否重搜?」的追问。

回退动作(首期纯前端实现,不动后端协议):needResearch=true 时,前端把用户的修改 payload 缓存为 pendingIntent,先 submitIntervention({action:'re_search', userQuery:researchQuery}) 补素材;监听到新一轮 material_confirm(素材追加完成)后,自动提交 pendingIntent。 需处理「重搜期间用户又改主意」→ 允许覆盖 pending。


4. 意图解析引擎:方案与契约

采用方案 A:后端 LLM 意图节点(独立 REST),叠加高频短句规则快路径优化。

理由:needResearch 判定需要完整写作上下文(素材/大纲/草稿),后端天然持有 checkpoint state; 与 setup_writing 一脉相承,离线模型选择策略统一;输出 schema 稳定、前端只消费。

4.1 后端入口

app/gateway/routers/ai_writing.py 新增:

POST /api/ai-writing/sessions/{session_id}/intent
Body: { text: string, status: string, pausePoint?: string }
Resp: IntentResult(见 4.3)

实现:读该 session 的 checkpoint state(素材摘要 / 大纲纲要 / 草稿字数·章节 / 审核意见)→ 用 ai_writing 配置模型(复用 intent_parser.py 同套 create_chat_model + parse_json + 模型容错 _model_fallback)解析 → 返回结构化契约。不改图拓扑。

新增 prompt:agents/ai_writing/prompts/intent_router_prompts.py

  • 输入:用户文本、current_status/pause_point、素材摘要、大纲纲要、草稿字数+章节标题、审核意见列表。
  • 输出:严格 JSON(4.3 契约)。硬要求:只在证据充分时给高 confidence,否则给 clarify; finalize/force_finalize/re_search 等高代价意图必须高置信才不澄清。

4.2 前端快路径(先跑规则,未命中再调后端)

api/ai-writing-intent.ts 里对当前 pausePoint 做少量确定性短语命中,直接产出 payload,省一次往返:

  • 「继续/下一步/确认/可以/ok/好的」→ 当前阶段默认 confirm(draft 阶段=to_editor)。
  • 「重新搜索/重搜」(material)→ re_search。「重写大纲」(outline)→ re_outline。
  • 「定稿/强制定稿」→ 不进快路径(高代价,一律走后端 + 可能澄清)。
  • 命中即执行;未命中 → 调后端 intent 接口。

4.3 意图解析输出契约

{
  "intent": "revise_draft",        // 见 3.2 分类
  "pausePoint": "draft_confirm",   // 需要 resume 时;否则 null
  "action": "user_revise",         // 映射到现有 action
  "payload": {                     // 直接可喂 submitIntervention 的字段(camelCase)
    "userRevisionNotes": "第三段精简,并补一个 2024 年的案例"
  },
  "needResearch": true,            // 素材是否不足
  "researchQuery": "2024 行业案例", // needResearch 时的检索意图
  "answer": null,                  // 问答类意图的直接回答(旁路)
  "confidence": 0.86,
  "clarify": null                  // 低置信时的反问话术(非空则不执行、只追问)
}

前端消费顺序:

  1. answer 非空 → 对话流渲染回答(问答旁路,不动写作状态)。
  2. clarify 非空 或 confidence < 阈值(建议 0.6) → 渲染反问气泡,等用户澄清(防误触发)。
  3. needResearch=true → 缓存 pendingIntent=payload,先重搜,收到新素材后自动提交。
  4. 否则 → idle 走 startWriting(...);暂停态走 submitIntervention({action, ...payload})。

5. 前端改造方案

5.1 新页面与路由(复制式)

  • 新页面:open-canvas/pages/AIWritingChatPage.tsx (骨架照抄 AIWritingPage.tsx 的 Provider 包裹与左右分栏;左栏换成 WritingChatPanel,右栏仍 AIWritingDraftPanel;idle 不再挂 AIWritingForm,改由底部输入框启动)。
  • 路由注册(新增,不动旧行):
    • open-canvas/routes/OpenCanvasRoutes.tsx 加 path="ai-writing-chat/*"。
    • 侧边栏 core/page-layout/sidebar-menu.ts:在 qa-research 旁新增 { id:"qa-research-chat", label:"AI写作(对话版)", icon:FileText, path:"/page/canvas/ai-writing-chat" }。 (或先不加、内部灰度直链验证。)

5.2 新面板 WritingChatPanel.tsx(左栏主体)

职责 = 消息流容器 + 底部输入框,替代 AIWritingPanel 里的「时间线 + InterventionCard + 状态栏」。 复用 useAIWriting() 读 state / 调 startWriting / submitIntervention / pauseWriting / suspendAIWritingToBackground。

消息流渲染(把 ProgressEvent / 阶段产物适配成消息卡,复用现有展示子组件):

  • 运行中:research_progress/outline_chunk/draft_chunk/review_chunk → 进度 / 流式卡 (复用 SkillStepsCard/OutlineStreamingView/DraftGeneratingView/ReviewStreamingView 的展示部分)。
  • 到达暂停点:渲染 产物卡 + 保留的确认按钮(见 5.3),不再有输入框。
  • 用户消息、AI 澄清追问、问答回答:普通气泡。

底部输入框:直接复用 @/components/ai-elements/prompt-input(PromptInput+PromptInputTextarea+ PromptInputSubmit),Enter 发送、Shift+Enter 换行;发送时读当前 state.status/currentPause?.pausePoint 交给意图路由(见 5.5)。运行中(非暂停点)可禁用发送或转「排队/提示当前在生成」。

5.3 新消息卡 chat-cards/*(保留按钮、去掉输入框)

把 InterventionCard.tsx 的五张卡各复制一份到 open-canvas/components/ai-writing-chat/chat-cards/, 删掉其中的 textarea / MaterialsToolbar 输入部分,保留产物展示 + 确认/动作按钮:

新卡 展示(复用) 保留的按钮 删除的输入
MaterialConfirmChatCard MaterialsCard(勾选保留)+ SkillStepsCard 「确认素材,规划大纲」「重新搜索」 MaterialsToolbar 的 userQuery 输入框
OutlineConfirmChatCard OutlineCard(可点标题微调保留) 「确认大纲,开始写作」 feedback textarea + 发送
DraftConfirmChatCard ReviewCard(若有审核,勾选保留) 「按编辑审核意见修改」「让编辑继续审核」「确认定稿」 「修改意见」textarea
ReviewConfirmChatCard ReviewCard(勾选保留) 「按编辑意见修改」「强制定稿」 「补充修改指令」textarea
SectionHelpChatCard 章节 + 三选一按钮组 三选一 + 「提交并继续」 (本就无自由输入,原样保留)

勾选态(素材/审核意见)保留——它是「点按钮」路径的一部分,不算自由输入框。用户想用自然语言 「只用第 1、3 条」也能走底部输入框(意图层产出 approvedMaterialIds/selectedIssueIndices)。 按钮点击 直接调 submitIntervention,与旧卡完全一致,零改动风险。

5.4 问答旁路(新能力)

「对写作内容提问」不改写作 state。首期轻量实现:意图节点检出 ask_* 时读 state 直接带回 answer, 前端在消息流渲染为普通 AI 气泡即可(一次调用出答案)。完整版(后续)可另起只读 lead_agent 线程注入 草稿/大纲作背景,类似 WritingSetupChat 的 useThreadStream。

5.5 交互流程(对话版)串起来

  1. 空闲:底部输入「写一篇关于 X 的深度分析,2000 字」→ 意图 start_writing → 组 AIWritingRequest → startWriting()。(缺关键字段时先 clarify 追问字数/读者/类型。)
  2. 运行中:进度/流式卡渲染。
  3. 到暂停点:渲染产物卡 + 按钮 + 一句提示「你可以点上面的按钮,或直接说:确认继续 / 补充素材 / 改大纲…」。
    • 点按钮 → 直接 submitIntervention(旧逻辑)。
    • 发文字 → resolveIntent(text, status, pausePoint)(先快路径、后后端)→ 按 4.3 消费。
  4. 问答:任意时刻提问 → 旁路 answer,不打断写作。
  5. 素材不足:needResearch 或 section_help → 追问/执行「重搜 → 自动续跑 pending 意图」。
  6. 拿不准:clarify/低置信 → 反问气泡,不执行。

5.6 pending 意图 & 澄清态(新增本地状态)

在 WritingChatPanel(或新 WritingChatContext)维护:

  • pendingIntent: UserInterventionPayload | null —— 素材不足重搜完成后自动提交。
  • awaitingClarify: { originalText: string } | null —— 澄清态,用户下一句与上一句拼接再解析。
  • pending 生命周期:设置 → 提交 re_search → 监听 reducer 里新一轮 awaiting_material_confirm (state.status 从 researching 回到 awaiting_material_confirm)→ 自动 submitIntervention(pending) → 清空。

6. 后端改造方案

6.1 意图解析入口(新增,唯一后端改动主体)

  • app/gateway/routers/ai_writing.py:新增 POST /sessions/{id}/intent(见 4.1)。 读 checkpoint state 用 app.state.checkpointer + make_ai_writing_graph().aget_state(...) (参照 ai_writing_job_executor.py 的读法)取素材/大纲/草稿/审核摘要。
  • agents/ai_writing/prompts/intent_router_prompts.py:新增意图 prompt(见 4.1)。
  • 复用 nodes/intent_parser.py 的模型创建 / parse_json / _model_fallback 容错。

6.2 不需要改的部分

  • 四个阶段大脑节点、五个暂停点、checkpoint、StreamBridge、持久化、sessions/transcript REST——全不动。
  • 「素材不足自动续跑」「问答旁路」首期都在前端 / 意图节点实现,不扩 resume 协议。

6.3 可选增强(阶段 3,按需)

  • add_review_opinion 完整版:review_confirm resume 增字段 extra_review_notes(首期已用现有 userRevisionNotes 降级承载,够用)。
  • resume_intent 后端化(把「重搜完自动续跑」搬到后端,减少前端状态机复杂度)。
  • undo / 回退到上一暂停点(依赖 checkpoint 回滚)。

7. 数据流时序(改稿 + 素材不足自动重搜)

用户(draft_confirm 暂停): "第三段补个2024年的行业案例"
  │ 底部输入框 → resolveIntent(text, status='awaiting_draft_confirm', pausePoint='draft_confirm')
  ▼ POST /api/ai-writing/sessions/{id}/intent { text, status, pausePoint }
后端: 读 state(素材摘要) + LLM 解析
  │ 返回 { intent:revise_draft, action:user_revise,
  │        payload:{userRevisionNotes:"第三段…补2024案例"},
  │        needResearch:true, researchQuery:"2024 行业案例", confidence:0.9 }
  ▼
前端: needResearch=true → pendingIntent = payload
  │ submitIntervention({action:'re_search', userQuery:"2024 行业案例"})
  ▼ LangGraph resume → researcher 追加素材 → status 回到 awaiting_material_confirm
前端: 监听到新一轮素材确认 → 自动提交 pendingIntent
  │ submitIntervention({action:'user_revise', userRevisionNotes:"第三段…补2024案例"})
  ▼ writer_draft 用新素材改稿 → draft_chunk… → draft_ready → draft_confirm
前端: 消息流展示新草稿卡 + "已按你的意见改写并补充了 2024 案例"

8. 关键实现细节与坑

  1. 阶段作用域:resolveIntent 必须带 state.currentPause?.pausePoint + state.status—— 同一句「重新来」在 material 是重搜、在 outline 是重写大纲。AIWritingContext 已有这两个字段,直接读。
  2. 确认按钮零改动:新卡的按钮 onClick 原样调 submitIntervention(payload),与旧卡逐字一致, 风险最低;只删输入框。
  3. 防误触发:低置信(<0.6)或 clarify 非空一律追问;finalize/force_finalize/re_search 即使命中也要求高置信,否则澄清。绝不盲目定稿/覆盖重搜。
  4. pending 意图队列:素材不足是「先插重搜、再回原意图」,用 5.6 的小状态机;重搜完成前允许覆盖 pending。
  5. 问答不污染 transcript:问答/澄清消息在前端标记 kind:'qa'|'clarify',与写作进度事件区分( AIWritingContext 的 transcript 只存 progressEvents/completedInterventions,问答气泡是纯前端消息, 默认不入 transcript,避免历史回看错乱)。
  6. 流式产物→消息卡:复用 OutlineStreamingView/DraftGeneratingView/ReviewStreamingView/ SkillStepsCard 的展示部分,套进消息容器,不重写渲染。
  7. 右侧草稿预览:AIWritingDraftPanel + DraftSync 原样复用(DraftSync 依据 status/markdown 同步右侧画布)。
  8. 离线内网:意图模型走 config.yaml → ai_writing 配置模型;检索仍走技能/内网 ES,不联网。
  9. 模型选择透传:submitIntervention 的 resume 已把 state.request?.modelName 一并回传(见 AIWritingContext),新页面沿用即可。
  10. 旧页面隔离验证:改完后回归旧 /page/canvas/ai-writing 与 /page/workspace/ai-writing、 笔记本嵌入页,确认零变化(新代码不 import 旧的 AIWritingForm/InterventionCard/WritingFormContext)。

9. 分阶段实施路线图

阶段 0 — 骨架(不含意图)

  • 复制 AIWritingChatPage + 注册新路由 + 侧边栏入口;复用 AIWritingContext/useStream/DraftPanel。
  • 复制五张 chat-cards(删输入框、留按钮);底部输入框先只做 idle 直发 start_writing (文本原样当 userIntent,其余字段取默认)+ 暂停点靠按钮推进。端到端跑通。

阶段 1 — 意图解析(核心)

  • 后端 POST /sessions/{id}/intent + intent_router_prompts.py,返回 4.3 契约。
  • 前端 api/ai-writing-intent.ts(快路径 + 后端)接入 WritingChatPanel,覆盖 A~F 类意图。
  • 低置信 clarify 澄清态(5.6)。

阶段 2 — 问答旁路 + 素材不足自动重搜

  • G 类问答(意图节点直接带 answer)。
  • needResearch + pending 意图机制(前端实现重搜后自动续跑,5.6)。

阶段 3 — 增强(按需)

  • add_review_opinion 扩协议、resume_intent 后端化、undo/回退、完整问答只读线程。

阶段 4 — 打磨

  • 消息卡视觉、历史回看(transcript)、后台挂起入口、灰度到侧边栏。

10. 关键文件清单(落地对照)

新增(前端)

  • open-canvas/pages/AIWritingChatPage.tsx — 新页面(复制 AIWritingPage 骨架改造)
  • open-canvas/components/ai-writing-chat/WritingChatPanel.tsx — 消息流 + 底部输入框
  • open-canvas/components/ai-writing-chat/chat-cards/{MaterialConfirmChatCard,OutlineConfirmChatCard,DraftConfirmChatCard,ReviewConfirmChatCard,SectionHelpChatCard}.tsx — 保留按钮、去掉输入框
  • open-canvas/components/ai-writing-chat/progressToMessage.ts — ProgressEvent → 消息卡适配
  • open-canvas/api/ai-writing-intent.ts — 意图解析客户端(快路径 + POST …/intent)
  • (可选)open-canvas/contexts/WritingChatContext.tsx — pending 意图 / 澄清态

修改(前端,仅追加,不动旧逻辑)

  • open-canvas/routes/OpenCanvasRoutes.tsx — 加一条 ai-writing-chat/* 路由
  • core/page-layout/sidebar-menu.ts — 加一个侧边栏入口(可选)
  • open-canvas/types/ai-writing.ts — 仅追加 IntentResult 等新类型,不改旧字段

新增(后端)

  • app/gateway/routers/ai_writing.py — 加 POST /sessions/{id}/intent
  • agents/ai_writing/prompts/intent_router_prompts.py — 意图 prompt
  • tests/test_ai_writing_intent.py — 意图接口单测(TDD 强制)

复用(不改)

  • open-canvas/contexts/AIWritingContext.tsx、hooks/useAIWritingStream.ts
  • open-canvas/components/ai-writing/{AIWritingDraftPanel,DraftSync,MaterialsCard,OutlineCard,ReviewCard,SkillStepsCard,OutlineStreamingView,DraftGeneratingView,ReviewStreamingView}.tsx
  • agents/ai_writing/graph.py、四个阶段节点、五个暂停点、nodes/intent_parser.py

绝不动(保证「初始的不用动」)

  • open-canvas/pages/AIWritingPage.tsx 及其引用的 components/ai-writing/{AIWritingForm,InterventionCard}.tsx、contexts/WritingFormContext.tsx
  • 旧路由 /page/canvas/ai-writing、/page/workspace/ai-writing、笔记本嵌入页

11. 待确认(默认取值已给出,可直接推进)

  1. 意图引擎:后端 LLM 节点(方案 A)+ 前端短句快路径 —— 默认采用。
  2. AIWritingContext / useAIWritingStream:复用(不物理复制)——默认采用;需绝对隔离可改为复制。
  3. 新页面入口:侧边栏新增「AI写作(对话版)」 —— 默认加;若要先灰度可只留直链。
  4. 「素材不足自动重搜」:首期前端 pending 续跑(不动后端 resume 协议)——默认采用。
  5. 问答旁路:首期意图节点直接带 answer —— 默认采用。

以上默认按「A + 复用引擎 + 侧边栏入口 + 前端 pending + 意图节点带答案」推进,如需调整请指出。