Files
2026-05-15 10:42:44 +08:00

20 KiB
Raw Permalink Blame History

Open Canvas 模式需求拆解文档

1. 文档目标

本文档用于指导 DeerFlow 在现有架构中新增一个 open-canvas 风格的 Canvas 模式。

目标不是直接照搬 langchain-ai/open-canvas 的 Next.js + LangGraph.js 实现,而是在当前项目技术栈内完成一套等价能力的实现:

  • 前端:基于 React 19 + Vite + react-router-dom
  • 后端:基于 Python + FastAPI + LangGraph
  • 模型层:支持云模型与本地模型自由配置
  • 状态层:支持结构化 artifact、版本历史、局部改写、快速动作、画布编辑

本文档重点是把需求拆成“可实现、可排期、可验收”的阶段性任务。


2. 最终目标

2.1 用户视角目标

用户进入一个新的 Canvas 工作模式后,可以获得与 open-canvas 接近的体验:

  • 左侧是聊天区,右侧是 Canvas 编辑区
  • 可以从空白文本或代码模板快速开始
  • 可以通过聊天让 AI 生成一份结构化 artifact
  • 可以对 artifact 整体重写,也可以对选中的局部内容进行改写
  • artifact 支持版本历史切换
  • artifact 支持文本和代码两种主要类型
  • 支持快速动作,例如扩写、压缩、改风格、改语气、加注释、修 bug、换语言
  • 支持启用 Web 搜索增强
  • 支持切换模型
  • 支持使用本地模型,例如 Ollama 或 OpenAI-compatible 本地服务

2.2 工程视角目标

新增的 Canvas 模式需要满足以下工程原则:

  • 不破坏现有 DeerFlow 工作区
  • 不影响现有基于 artifacts: string[] 的文件产物功能
  • 可逐阶段上线
  • 前后端状态协议清晰
  • 可兼容现有 LangGraph 线程、消息流、认证和模型接口

3. 范围定义

3.1 本次需求包含

  • 前端新增 open-canvas 专用目录
  • 在 PageRoutes.tsx 中引入新的 Canvas 路由
  • 前端新增 Canvas 页面、上下文、组件、状态管理
  • 后端新增 Canvas 专用线程状态字段
  • 后端新增 Canvas Agent 图或在现有 Agent 体系中新增 Canvas 模式分支
  • 模型配置统一为 DeerFlow 后端配置驱动
  • 支持本地大模型配置与模型列表动态下发
  • 支持结构化 artifact 的保存、读取、更新、版本切换

3.2 本次需求不包含

  • 一次性复刻 open-canvas 全部 UI 细节
  • 完整照搬 Supabase 鉴权体系
  • 直接复用 open-canvas 的 Next.js API Route
  • 直接运行 open-canvas 的 LangGraph.js 后端
  • 首阶段就实现所有快捷动作、所有富文本效果、所有搜索增强能力

3.3 迁移原则

  • 借鉴 open-canvas 的能力模型,不直接迁移其运行时架构
  • 前端尽量复用其交互设计和数据结构
  • 后端以 Python 实现同等能力
  • 配置以 DeerFlow 为真源,不以 open-canvas 的 TS 文件为真源

4. 总体设计思路

4.1 前端设计思路

在现有 frontend-web/src 下新增一个专用目录,例如:

src/
  open-canvas/
    pages/
    routes/
    components/
    contexts/
    hooks/
    types/
    api/
    utils/
    constants/

建议将 Canvas 模式作为一个独立的页面子系统接入,而不是把现有工作区页面强行改造成 Canvas。

建议路由形式:

  • /canvas
  • /canvas/:threadId

也可以挂在现有页面布局下,例如:

  • /workspace/canvas
  • /workspace/canvas/:threadId

推荐优先采用独立一级功能路由:

  • 逻辑更清晰
  • 状态隔离更容易
  • 不容易污染现有 workspace 功能

4.2 后端设计思路

后端不建议直接改造现有通用 Agent 去同时承担全部 Canvas 行为,而是建议采用以下两种方案之一:

方案 A:新增独立 Canvas Assistant

  • 新增 canvas_agent
  • 使用单独的 LangGraph 状态定义
  • 前端调用时通过 assistant_id=canvas_agent

优点:

  • 与现有 lead_agent 隔离
  • 风险更低
  • 更容易对齐 open-canvas 的图结构

缺点:

  • 会产生一套新的 Agent 图维护成本

方案 B:在现有 Lead Agent 中增加 Canvas 模式分支

  • 在 thread metadata 或 configurable 中增加 ui_mode=canvas
  • Agent 根据模式进入 Canvas 路径

优点:

  • 统一入口

缺点:

  • 会显著增加现有 Agent 复杂度
  • 容易影响现有聊天和文件产物模式

推荐先做方案 A。

4.3 模型配置设计思路

模型配置统一以 DeerFlow 后端 config.yaml 为真源。

前端不维护固定模型常量列表,而是通过 /api/models 获取模型能力元数据。

为了实现 open-canvas 风格体验,需要后端模型接口至少返回:

  • name
  • display_name
  • provider
  • supports_thinking
  • supports_reasoning_effort
  • supports_vision
  • supports_tool_calling
  • supports_artifact_editing
  • supports_code_editing
  • temperature_range
  • max_tokens_range
  • base_url_source 或 provider 标识
  • is_local

5. 与当前项目的关键差异

5.1 当前 DeerFlow 现状

当前 DeerFlow 线程状态中的 artifact 主要是文件路径列表:

  • artifacts: string[]

这更接近“生成文件产物”的工作模式。

前端当前 artifact 面板也主要是:

  • 文件列表
  • 文件详情
  • 文件下载/预览

5.2 open-canvas 的关键能力

open-canvas 的核心不是“生成文件”,而是“维护一个结构化的当前文档对象”:

  • 一个 conversation 对应一个主 artifact
  • artifact 具有类型、标题、内容、版本
  • 用户可以选中部分内容让 AI 改写
  • 每次改写都会生成新版本

5.3 需要新增的核心能力

为支持 Canvas 模式,需要在 DeerFlow 中新增一套结构化 artifact 状态:

  • 当前 artifact
  • 当前版本索引
  • 历史版本列表
  • 选区信息
  • 当前编辑模式
  • 快速动作状态
  • Web 搜索结果状态

6. 分阶段实施方案

以下为推荐的 8 个阶段,每个阶段都可单独开发、联调和验收。


7. 阶段一:前端路由与目录骨架

7.1 目标

在不影响现有页面的前提下,建立 Canvas 模式的前端骨架。

7.2 需求

  • 新增 src/open-canvas/ 目录
  • 新增 Canvas 页面路由
  • 将路由接入 PageRoutes.tsx
  • 提供 Canvas 首页和 Canvas Thread 页
  • 支持空状态展示

7.3 建议目录

src/open-canvas/
  api/
    threads.ts
    runs.ts
    models.ts
  components/
    layout/
    chat/
    canvas/
    artifacts/
    quick-actions/
    selectors/
  contexts/
    CanvasThreadContext.tsx
    CanvasGraphContext.tsx
    CanvasUIContext.tsx
  hooks/
    useCanvasThread.ts
    useCanvasStream.ts
    useCanvasArtifact.ts
  pages/
    CanvasHomePage.tsx
    CanvasThreadPage.tsx
  routes/
    OpenCanvasRoutes.tsx
  types/
    artifact.ts
    thread.ts
    model.ts
  utils/
    artifact.ts
    selection.ts
    stream.ts
  constants/
    index.ts

7.4 路由建议

  • 在 PageRoutes.tsx 中新增 canvas/*
  • 在 src/open-canvas/routes/OpenCanvasRoutes.tsx 中维护子路由

建议形式:

/canvas
/canvas/:threadId

7.5 验收标准

  • 能访问 Canvas 首页
  • 能访问指定 thread 的 Canvas 页面
  • 不影响现有 workspace/* 与 strategy/*
  • 页面有独立布局骨架

8. 阶段二:前端 Canvas 布局与交互容器

8.1 目标

先做出“左聊天、右画布”的基础容器,不接真实 AI 改写逻辑。

8.2 需求

  • 左侧聊天区
  • 右侧画布区
  • 支持面板拖拽或折叠
  • 初始空状态
  • 支持“快速开始”:
    • 新建空白文本 artifact
    • 新建代码 artifact

8.3 组件拆分建议

  • CanvasShell
  • CanvasSidebar
  • CanvasChatPanel
  • CanvasArtifactPanel
  • CanvasEmptyState
  • QuickStartActions

8.4 快速开始能力

用户进入空线程时可以选择:

  • 开始写文章
  • 开始写代码
  • 从模板开始

首版模板可只做最小集:

  • 空白文档
  • HTML 模板
  • React 组件模板
  • Python 脚本模板

8.5 验收标准

  • 页面可稳定展示双栏布局
  • 快速开始能创建前端本地 artifact 状态
  • 代码和文本可分别进入不同渲染器

9. 阶段三:结构化 Artifact 数据模型

9.1 目标

定义 DeerFlow 的 Canvas Artifact 协议,作为前后端统一契约。

9.2 核心要求

需要支持以下能力:

  • 文本 artifact
  • 代码 artifact
  • 标题
  • 当前版本索引
  • 版本历史
  • 当前选中版本切换
  • 后续支持局部高亮编辑

9.3 建议数据结构

type CanvasArtifact = {
  currentIndex: number;
  contents: Array<CanvasArtifactText | CanvasArtifactCode>;
};

type CanvasArtifactText = {
  index: number;
  type: "text";
  title: string;
  fullMarkdown: string;
};

type CanvasArtifactCode = {
  index: number;
  type: "code";
  title: string;
  language: string;
  code: string;
};

9.4 线程状态建议新增字段

前端与后端需共同支持:

  • artifact
  • highlighted_text
  • highlighted_code
  • canvas_mode
  • web_search_enabled
  • web_search_results
  • quick_action_id

9.5 与现有 artifacts: string[] 的关系

建议保留现有 artifacts: string[] 不动。

新增字段:

  • artifact 用于 Canvas 主文档
  • artifacts 继续用于文件产物

这样可以兼容未来“Canvas 生成网页文件、导出文件、保存文件”的场景。

9.6 验收标准

  • 前端类型定义完成
  • 后端状态字段设计完成
  • 确认与现有线程状态兼容

10. 阶段四:后端线程状态与 API 扩展

10.1 目标

让后端线程状态可以安全存储和返回 Canvas Artifact。

10.2 需求

  • 扩展 Python ThreadState
  • 扩展状态序列化逻辑
  • 确保 /api/threads/* 返回结构化 artifact
  • 确保 LangGraph 流中可带上 artifact 更新

10.3 后端改造点

建议关注以下模块:

  • packages/harness/deerflow/agents/thread_state.py
  • 线程 state serializer
  • app/gateway/routers/threads.py
  • 流事件适配层

10.4 注意事项

  • 旧线程没有 artifact 字段时必须兼容
  • 状态更新不能破坏现有消息结构
  • 必须确保 JSON 可序列化

10.5 验收标准

  • 新建线程可写入 artifact
  • 读取线程时可返回 artifact
  • 不影响现有线程读取
  • 前端能从线程 state 中恢复 Canvas 内容

11. 阶段五:Canvas 专用 Agent 图

11.1 目标

实现与 open-canvas 类似的 AI 路由能力。

11.2 推荐方案

新增 canvas_agent,单独维护图逻辑。

11.3 节点拆分建议

首版建议至少拆成这些节点:

  • route_user_intent
  • reply_general_input
  • generate_artifact
  • rewrite_artifact
  • update_highlighted_text
  • update_highlighted_code
  • generate_followup

二期可加:

  • rewrite_artifact_theme
  • rewrite_code_theme
  • change_length
  • change_reading_level
  • translate_artifact
  • add_comments
  • add_logs
  • fix_bugs
  • port_language
  • web_search_enrich

11.4 路由逻辑要求

系统需要能判断:

  • 用户是在闲聊
  • 用户要新生成 artifact
  • 用户要整体重写当前 artifact
  • 用户要局部修改当前 artifact
  • 用户要执行某个快捷动作

11.5 状态输入要求

节点需要读取:

  • 当前消息历史
  • 当前 artifact
  • 当前选区
  • 当前模型配置
  • Web 搜索开关

11.6 输出要求

节点输出必须能更新:

  • messages
  • artifact
  • web_search_results
  • followup

11.7 验收标准

  • 能根据输入创建新 artifact
  • 能根据输入整体改写 artifact
  • 能保留版本历史
  • 能在改写后返回自然语言 followup

12. 阶段六:前端流式同步与版本管理

12.1 目标

让前端能像 open-canvas 一样在流式过程中更新画布与聊天。

12.2 需求

  • 复用现有 LangGraph stream client
  • 在 Canvas 模式中解析 artifact 更新
  • 支持流式文本更新
  • 支持版本切换
  • 支持断线后恢复线程状态

12.3 前端状态层建议

  • CanvasThreadContext:线程基础信息
  • CanvasGraphContext:消息、artifact、streaming 状态
  • CanvasUIContext:面板、编辑态、选中态

12.4 关键能力

  • 当前版本切换
  • 新版本创建后自动定位到最新版本
  • 手动编辑内容后保存
  • 流结束后线程状态持久化

12.5 验收标准

  • 发送消息时聊天和画布可同步更新
  • 版本数会增加
  • 切换历史版本稳定
  • 刷新页面后线程状态能恢复

13. 阶段七:局部选区改写

13.1 目标

实现 Canvas 模式最关键的差异化能力之一:选中局部内容进行 AI 改写。

13.2 文本选区需求

  • 支持在 Markdown 文本中选择一段文本
  • 记录选区位置与原始文本
  • 用户发出修改请求后,仅重写该选区
  • 将选区结果合并为新版本 artifact

13.3 代码选区需求

  • 支持在代码编辑器中选择一段代码
  • 记录 start/end index 或行列信息
  • AI 只返回替换片段
  • 前端或后端负责将新片段拼接回完整代码

13.4 实现建议

首版建议:

  • 文本:前端记录纯文本字符位置
  • 代码:使用 CodeMirror selection 信息

不建议首版就做复杂块级富文本局部编辑。

13.5 风险

  • Markdown 渲染态与源码态位置映射复杂
  • 富文本块级位置难维护
  • 流式更新中选区同步容易错位

13.6 首版折中方案

首版文本只基于 fullMarkdown 纯文本改写,不做 BlockNote 富文本块定位。

13.7 验收标准

  • 文本局部改写成功
  • 代码局部改写成功
  • 原内容未改动部分保持不变
  • 新版本正确入历史

14. 阶段八:快捷动作系统

14.1 目标

实现 open-canvas 风格的快捷动作体系。

14.2 首批推荐动作

文本类:

  • 扩写
  • 精简
  • 改正式语气
  • 改口语语气
  • 改阅读难度
  • 翻译

代码类:

  • 加注释
  • 加日志
  • 修复 bug
  • 优化代码
  • 转换语言

14.3 设计方式

快捷动作不要直接写死在 UI,建议配置化:

  • id
  • label
  • type
  • applicable_to
  • prompt_template

14.4 后端设计

快捷动作可通过:

  • 前端传 quick_action_id
  • 后端路由节点根据动作 id 选择 prompt

14.5 验收标准

  • 文本动作可执行
  • 代码动作可执行
  • 结果进入新版本
  • 不同动作提示词可扩展

15. 阶段九:模型配置统一与本地模型支持

15.1 目标

让 Canvas 模式支持和主系统统一的模型选择,并且能自由配置本地大模型。

15.2 原则

  • 后端 config.yaml 为真源
  • 前端只展示后端暴露的模型信息
  • 不维护一份脱离后端的前端常量模型表

15.3 本地模型支持范围

建议优先支持两类:

  • Ollama
  • OpenAI-compatible 本地服务
    • LM Studio
    • vLLM
    • LocalAI
    • one-api 风格代理

15.4 后端配置建议

后端模型配置应至少支持:

  • name
  • display_name
  • use
  • model
  • api_key
  • base_url
  • supports_vision
  • supports_thinking
  • supports_tool_calling
  • is_local
  • canvas_capabilities

15.5 Canvas 模式额外要求

由于不是所有模型都适合 Canvas 改写任务,建议增加能力标识:

  • supports_canvas_generation
  • supports_canvas_rewrite
  • supports_canvas_code_edit
  • supports_streaming_text
  • supports_streaming_tool_calls

15.6 与 open-canvas 的关系

可以借鉴其命名习惯和能力分层,但不建议直接依赖其 packages/shared/src/models.ts 作为配置源。

15.7 验收标准

  • 前端模型选择器可显示后端返回模型
  • 可切换本地模型
  • Canvas 模式能用本地模型生成和改写

16. 阶段十:Web 搜索增强

16.1 目标

实现类似 open-canvas 的可选 Web 搜索增强。

16.2 需求

  • UI 提供 Web 搜索开关
  • 后端在需要时走搜索节点
  • 搜索结果写入线程状态
  • 结果可在画布旁侧栏展示

16.3 首版建议

只做:

  • 开关
  • 搜索结果列表
  • 搜索结果用于生成 artifact

暂不做复杂网页抓取编辑链路。

16.4 验收标准

  • 打开搜索后可返回搜索结果
  • 搜索结果可参与 artifact 生成
  • 结果展示不阻塞主画布

17. 阶段十一:持久化、导出与文件产物联动

17.1 目标

让 Canvas 文档与 DeerFlow 原有文件能力协同。

17.2 需求

  • artifact 持久化在线程 state 中
  • 可手动导出为文件
  • 可生成真实 HTML/Markdown/代码文件到现有 outputs
  • Canvas artifact 与 artifacts: string[] 可双向关联

17.3 推荐能力

  • 导出 Markdown
  • 导出代码文件
  • 另存为 artifact file
  • 从 artifact file 回填到 Canvas

17.4 验收标准

  • 当前版本可导出
  • 导出文件可在现有文件面板查看
  • 文件型 artifact 和 Canvas artifact 能共存

18. 推荐开发顺序

建议严格按以下顺序推进:

  1. 路由和目录骨架
  2. Canvas 页面布局
  3. 前端 artifact 数据模型
  4. 后端线程状态扩展
  5. 新建 Canvas Agent 图
  6. 前后端流式同步
  7. 整体生成与整体改写
  8. 局部选区改写
  9. 快捷动作
  10. 本地模型支持完善
  11. Web 搜索增强
  12. 导出与文件联动

不要先做局部改写和快捷动作,否则前面的状态与路由契约不稳定,返工会很多。


19. 里程碑定义

M1:页面可进入

  • 路由接通
  • 双栏布局完成
  • 本地 mock artifact 可渲染

M2:后端状态打通

  • 线程可保存结构化 artifact
  • 页面刷新后能恢复

M3:AI 生成可用

  • 可新建文本/代码 artifact
  • 可整体改写
  • 可产生版本历史

M4:核心体验可用

  • 选区改写可用
  • 快捷动作可用
  • 模型切换可用

M5:增强能力完整

  • 本地模型支持完善
  • Web 搜索增强
  • 导出和文件联动

20. 风险与难点

20.1 最大难点

  • 结构化 artifact 状态从无到有
  • 局部选区改写的精确性
  • 流式状态与版本管理的一致性
  • 不破坏现有 DeerFlow 文件型 artifact 体系

20.2 技术风险

  • 线程 state JSON 结构过大
  • 大模型对局部改写指令遵循不稳定
  • 本地模型 tool calling 与流式能力差异大
  • 文本渲染态与源码态位置映射复杂

20.3 规避建议

  • 首版只支持 Markdown 源码态编辑,不做复杂富文本编辑
  • 首版只支持文本和代码两种 artifact 类型
  • 首版先做整体生成和整体改写,再做局部改写
  • 本地模型先支持“能生成、能重写”的最小能力,不强求与顶级闭源模型完全同效

21. 验收总清单

21.1 前端

  • 有独立 Canvas 路由
  • 有专用目录和模块边界
  • 双栏布局可用
  • 文本和代码两类 artifact 可渲染
  • 历史版本可切换
  • 选区改写可交互
  • 快捷动作可触发
  • 模型可切换

21.2 后端

  • 线程状态支持 artifact
  • 新增 canvas_agent 或等价模式
  • 生成、重写、局部改写可用
  • 流式返回稳定
  • 模型列表接口支持 Canvas 能力元数据

21.3 本地模型

  • 可配置 Ollama
  • 可配置 OpenAI-compatible 本地服务
  • 前端可见并可切换
  • 至少能完成文本生成和整体改写

22. 推荐首版最小可交付范围

如果要控制风险,建议首版只交付以下内容:

  • 新增 canvas/* 路由
  • 双栏布局
  • 结构化 artifact
  • canvas_agent
  • 文本/代码 artifact 新建
  • 整体生成
  • 整体改写
  • 历史版本切换
  • 后端模型动态加载
  • Ollama 或本地 OpenAI-compatible 至少一种可用

先不要把以下内容放进首版强制目标:

  • 富文本块级精确编辑
  • 全量快捷动作
  • 复杂 Web 搜索增强
  • 多 artifact 并行管理

23. 后续实施建议

建议下一步基于本文档继续输出两份落地文档:

23.1 前端实施清单

逐文件列出:

  • 要新建哪些文件
  • 哪些组件可复用
  • 哪些页面要接入路由
  • 哪些状态要从现有 hooks 抽离

23.2 后端实施清单

逐模块列出:

  • 要改哪些 Python 文件
  • 新增哪些状态字段
  • 新增哪些 Agent 节点
  • 哪些 API 需要扩展

24. 结论

这个需求很大,但完全可拆。

正确做法不是“先抄 UI”,而是按下面的主线推进:

  • 先建前端 Canvas 子系统
  • 再建结构化 artifact 状态
  • 再建 Canvas Agent 图
  • 再补局部改写和快捷动作
  • 最后统一本地模型能力

只要按本文档阶段推进,这个需求是可以落地的,而且能和你现在的 DeerFlow 架构保持长期兼容。