DocFlow AI 编辑与聊天链路
解释文档提案、接受拒绝、聊天参数、流式解析及未接线接口。
本页整理自 2026-10-04 的 DocFlow 静态调查材料。原材料没有提供仓库 URL、分支或提交哈希;正文中的路径、行号、计数与依赖版本均指向该未锚定快照。本轮整理读取了归档报告,未取得原工作副本、启动产品或验证外部后端。下文的“复核”指原材料记载的复核,前端路径存在与运行可用性分别判断。
AI 数据流
编辑器 Agent 智能编辑链路
入口复核:DocumentHeader 的"打开 AI 助手"按钮(document-actions.tsx:42,150)与 ContentItemMenu 的 AI 续写(useContentItemActions.tsx:86-88)都只是 chatStore.setIsOpen 打开同一个 AgentEditPanel(page.tsx:36-39 动态导入、:324 渲染)——这是编辑器内唯一真实落地的 AI 功能(侧栏 ai 块点击仅 console.log)。
数据流:
- 用户在 AgentEditPanel 输入自然语言指令;
useDocumentEdit.handleSubmit把editor.getJSON()全量 Tiptap 文档与指令、documentId 一起 POST 到/api/v1/collaboration/agent/edit(timeout 120s;services/collaboration/index.ts:105,108);请求体无任何 prompt 字段——prompt 组装完全在后端;- 代码注释自述后端为 "LangGraph 三节点串行调用 LLM"(
index.ts:107:意图识别 → 锚点定位 → 提案生成),SSE 依次回 thinking/intent/anchor/proposal 四类 token 流与三个结构化结果(index.ts:49-58);面板按"理解意图 → 定位位置 → 生成内容"三步展示。注意:"LangGraph 三节点"是前端注释的说法,后端不在本仓库无法从所查仓库直接核实; - 渲染节流:token 先累积进 ref,setTimeout(0) 合并 flush,避免每个 SSE chunk 触发一次 React 渲染(
useDocumentEdit.ts:201-231)。
diff 落地与接受/拒绝(原材料复核)
提案经 applyOpToEditor(useDocumentEdit.ts:99-174)落地,四个 case:append_to_doc / insert_after / insert_before / replace,均走 editor.chain().focus().insertContentAt(pos, nodes)(:107,116,131,169)。replace 特殊:先给被替换文本加 variant: 'deleted' 的 agentSuggestion mark(:151-167,mark 创建在 :154),再在目标后插入新内容,形成红绿 diff。AgentSuggestion 扩展(extensions/AgentSuggestion/index.ts)提供:
acceptAgentSuggestion(:72-128):移除 added mark、删除 deleted 所在父块;rejectAgentSuggestion(:131-180):移除 deleted mark、删除 added 所在父块;- 逐条与批量(acceptAll/rejectAll)在
useDocumentEdit.ts:392-440。
AI 聊天链路
独立页面 /chat-ai(与编辑器互不集成——README 自述"后续集成到编辑器侧边栏"属进行中规划):
- 请求组装(原材料复核,计数有勘误):requestData = conversation_id(仅有会话时)+ model + messages(用户可配 SystemPrompt 作为 system 消息 + 全部历史消息一次性发出 + 新用户消息)+ 11 个采样参数(top_p/enable_thinking/thinking_budget/max_tokens/temperature/enable_web_search/top_k/frequency_penalty/min_p/stop/n)(
useChat.ts:134-155)。调研原文称"15 个参数",复核清点所列采样参数实为 11 个、请求全部字段共 14 个。 - 长会话无截断/滑窗逻辑:调研材料未见任何截断或滑窗处理——前端把全部历史原样拼入每轮请求,每轮提交的历史内容随累计消息增长;当每轮新增消息长度近似固定时,单轮输入量近似线性增长,累计输入量可能更快增长;是否存在服务端截断无法核实(后端不在本仓库),用户侧可见的唯一控制手段是删除会话。
- 默认配置:system prompt 一句话(
chat-ai/constants.ts:36),默认参数 temperature=1 / topP=0.95 / thinkingBudget=4096 等(:42-56)。 - 会话管理:分页/加载更多/删除/改标题(
useConversations.ts:105-215);新会话用 13 位时间戳临时 URL ID,初始消息经 sessionStorage 中转、后端返回真实 conversation_id 后 history.replaceState 无刷新换 URL(chat-ai/[id]/page.tsx:31-38,46-62)。 - 渲染节流:5ms 缓冲批量 flush(
useChat.ts:158-253)。
流式解析:只有 streamPost 一条活路(原材料复核)
- 响应为 OpenAI 兼容 chunk 结构:choices[].delta.content(正文)与 delta.reasoning_content(深度思考流)(
services/chat-ai/type.ts:112-131;前端类型未出现 'chat.completion.chunk' 字面量,但结构即标准格式)。 - 自研
streamPost(services/request/client.ts:1019-1238):fetch(:1045)→ body.getReader()(:1143)→ TextDecoder(:1144)→ buffer 按行 split(:1160-1181)→parseOpenAIStreamLine(:1243-1279)剥 "data: " 前缀、遇 [DONE] 返回 null。 - 新会话 ID:onHeaders 提取 Session-Id 响应头(
services/chat-ai/index.ts:220-227)。 - 另一条 SSE 通道是死代码:
@azure/core-sse@2.3.0已装并在 client.ts:902-1008 实现了 sseStream(createSseStream + getReader),但全库零调用;request.sse(返回原始 Response,client.ts:747)仅被 AiApi 的三个本身无调用方的接口(ContinueWriting/Question/StreamAgent)使用。
半成品与孤儿接口
- 服务层定义齐全但零调用方:ChatAiApi.Autocomplete/Polish/Brainstorm(支持多 choices 并发)、AiApi.ContinueWriting/Question/TextToImage/StreamAgent/GeneratePodcastAsync——README 重点宣传的编辑器内"头脑风暴/润色/续写"UI 不存在,仅遗留
styles/partials/ai-brainstorm.css。 - 知识库接口双重封装:AiApi 与 KnowledgeApi 各自封装同一组 /api/v1/ai/knowledge* 端点,页面两个都在用(CreateKnowledgeDialog 用 KnowledgeApi 建库、KnowledgeDocumentList 用 AiApi 传文件/URL)。
- 用户 API Key:设置页存 localStorage(
api-key-settings.tsx:53-58),无任何读取方。
最后更新于