Files
deerflow-code/frontend-web/docs/openCanvas-backend-checklist.md
T
2026-05-15 10:42:44 +08:00

19 KiB

Open Canvas 后端实施清单

1. 文档目标

本文档是 openCanvas.md 的后端落地版清单。

目标是把 Canvas 模式在当前 DeerFlow 后端中的实施工作拆成可以直接排期和执行的任务,覆盖:

  • 线程状态扩展
  • canvas_agent 设计
  • LangGraph 节点拆分
  • Gateway API 扩展
  • 流式输出契约
  • 模型配置与本地模型支持
  • 结构化 artifact 的持久化
  • 测试与验收顺序

本文档默认前端会新增独立的 Canvas 子系统,并通过现有 LangGraph 线程和 Gateway API 与后端通信。


2. 实施原则

2.1 总原则

  • 不破坏现有 lead_agent
  • 不破坏现有 artifacts: list[str] 文件产物体系
  • 优先增量扩展,不做推倒重构
  • 先打通状态和协议,再实现复杂 AI 行为
  • 先支持文本/代码双类型,再逐步扩展快捷动作

2.2 推荐路线

推荐采用“新增独立 canvas_agent”方案,而不是把所有 Canvas 行为塞进现有 lead_agent。

推荐原因:

  • 风险更低
  • 图逻辑更清晰
  • 更容易对齐 open-canvas 的状态结构
  • 不影响现有 DeerFlow 普通聊天与文件产物模式

2.3 后端目标边界

本次后端实施重点是:

  • 新增 Canvas 专用线程状态字段
  • 新增 Canvas Agent 图
  • 新增前端需要的模型能力元数据
  • 支持结构化 artifact 在线程状态中读写

本次不要求:

  • 完整复刻 open-canvas 的所有 TS 图结构
  • 完整复刻 Supabase 相关逻辑
  • 把所有模型 provider 完全抽象成统一能力中台

3. 现有后端基础能力盘点

当前 DeerFlow 后端已经具备非常好的基础设施:

  • LangGraph 线程与流式交互
  • FastAPI Gateway
  • 模型动态配置
  • 本地线程状态管理
  • Sandbox/工具体系
  • 上传与文件 artifact 访问
  • Memory 与标题生成

因此 Canvas 模式并不是“从 0 开始做 Agent 平台”,而是“在现有平台上新增一类结构化创作模式”。


4. 目标代码落点

建议优先关注以下目录:

offline-backend-20260512/backend/
  app/gateway/
    routers/
    deps.py
    app.py
  packages/harness/deerflow/
    agents/
      factory.py
      thread_state.py
      lead_agent/
      middlewares/
    runtime/
    config/
    tools/

建议为 Canvas 新增或扩展以下区域:

packages/harness/deerflow/
  agents/
    canvas_agent/
      __init__.py
      agent.py
      prompt.py
      state.py
      nodes/
        route_user_intent.py
        generate_artifact.py
        rewrite_artifact.py
        update_highlighted_text.py
        update_highlighted_code.py
        generate_followup.py
        quick_actions.py
        web_search.py

如果不想把节点拆得太细,首版也可以把部分逻辑先收在 agent.py 里,但建议至少把 state.py 和 prompt.py 独立出来。


5. 开发阶段总览

后端建议分为 11 个阶段:

  1. 线程状态扩展
  2. 结构化 artifact 协议定义
  3. canvas_agent 接入到 Agent 工厂
  4. Canvas 图的最小节点实现
  5. Gateway/线程接口兼容
  6. 流式状态输出适配
  7. 模型能力元数据扩展
  8. 本地模型兼容与配置统一
  9. 快捷动作与局部改写
  10. Web 搜索增强
  11. 测试、回归、验收

6. 阶段一:线程状态扩展

6.1 任务目标

让 DeerFlow 的线程状态能原生保存 Canvas 所需的结构化信息。

6.2 任务清单

  • 扩展 thread_state.py
  • 定义 Canvas 相关 TypedDict 或 dataclass 结构
  • 确保状态字段可序列化
  • 不影响现有 messages/title/artifacts/todos 逻辑

6.3 建议新增字段

在现有 ThreadState 上新增:

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

6.4 建议数据形态

可先采用 JSON-safe dict 结构,而不是在状态层引入过重的复杂对象。

建议:

class CanvasArtifactText(TypedDict):
    index: int
    type: Literal["text"]
    title: str
    fullMarkdown: str

class CanvasArtifactCode(TypedDict):
    index: int
    type: Literal["code"]
    title: str
    language: str
    code: str

class CanvasArtifact(TypedDict):
    currentIndex: int
    contents: list[CanvasArtifactText | CanvasArtifactCode]

6.5 与现有 artifacts 的关系

必须保留现有:

  • artifacts: list[str]

新增:

  • artifact: dict | None

含义区分:

  • artifacts 表示文件型产物列表
  • artifact 表示 Canvas 当前主文档

6.6 验收标准

  • 旧线程无 artifact 时不报错
  • 新线程可写入 artifact
  • 线程状态能被 FastAPI 和 LangGraph 正确序列化

7. 阶段二:结构化 Artifact 协议定义

7.1 任务目标

统一前后端对 Canvas artifact 的字段约定。

7.2 任务清单

  • 在后端建立一份明确的 artifact 协议定义
  • 明确字段命名、类型、兼容策略
  • 明确版本管理规则

7.3 协议要求

必须支持:

  • 文本 artifact
  • 代码 artifact
  • 标题
  • 当前版本索引
  • 历史版本列表
  • 后续支持局部改写

7.4 版本规则

  • 每次 AI 整体生成,生成 contents[0]
  • 每次 AI 重写,追加一个新版本
  • currentIndex 指向当前版本
  • 历史版本默认只保留在线程状态中,不额外落库

7.5 建议约束

  • index 从 1 开始
  • currentIndex 必须落在 contents 范围内
  • type 只允许 "text" 或 "code"

7.6 验收标准

  • 前后端字段完全一致
  • 状态协议有明确默认值和边界规则

8. 阶段三:接入 canvas_agent

8.1 任务目标

在现有 Agent 体系中注册一个独立的 Canvas Agent。

8.2 任务清单

  • 新建 packages/harness/deerflow/agents/canvas_agent/
  • 新建 agent.py
  • 新建 prompt.py
  • 新建 state.py
  • 修改 factory.py

8.3 注册方式建议

建议将 canvas_agent 作为一个显式 assistant id 暴露给 LangGraph 运行时。

前端调用时:

  • assistant_id=canvas_agent

8.4 Agent 设计原则

  • Canvas Agent 不负责 DeerFlow 全部工具生态
  • 首版专注于:
    • 生成文档
    • 重写文档
    • 局部改写
    • 跟进回复

8.5 工具策略

首版建议:

  • 不强依赖 shell/sandbox
  • 不强依赖 present_files
  • 先把生成与改写链路做好

后续可以根据需要接入文件导出能力。

8.6 验收标准

  • canvas_agent 可被识别
  • 前端能以 assistant id 调用它
  • 不影响 lead_agent

9. 阶段四:Canvas 状态与图定义

9.1 任务目标

为 Canvas Agent 定义清晰、最小但可扩展的状态结构。

9.2 任务清单

  • 新建 canvas_agent/state.py
  • 定义图状态
  • 约束与 ThreadState 的映射方式

9.3 建议状态字段

  • messages
  • _messages 或等价内部消息
  • artifact
  • highlighted_text
  • highlighted_code
  • quick_action_id
  • web_search_enabled
  • web_search_results
  • next

9.4 状态设计建议

优先复用 LangGraph 原生消息 reducer。

对结构化字段,尽量采用:

  • 可整体替换
  • 易序列化
  • 无 Python 特殊对象依赖

9.5 验收标准

  • 状态能驱动 Canvas 节点运行
  • 状态可被序列化回线程

10. 阶段五:Canvas 图最小节点闭环

10.1 任务目标

先实现最小闭环,不要一开始就追求 open-canvas 全量功能。

10.2 首版最小节点

建议至少实现:

  • route_user_intent
  • reply_general_input
  • generate_artifact
  • rewrite_artifact
  • generate_followup

10.3 节点职责

route_user_intent

判断用户当前意图:

  • 普通聊天
  • 新建 artifact
  • 重写当前 artifact

reply_general_input

仅返回普通消息,不更新 artifact。

generate_artifact

根据用户需求生成第一版 artifact。

rewrite_artifact

根据当前 artifact 和用户请求生成新版本。

generate_followup

在 artifact 更新后补一条自然语言消息。

10.4 输出要求

必须至少更新:

  • messages
  • artifact

10.5 验收标准

  • 无 artifact 时能生成新 artifact
  • 有 artifact 时能整体重写
  • 重写后版本数增加

11. 阶段六:Prompt 设计与模型调用封装

11.1 任务目标

把 Canvas 模式的 prompt 和模型调用逻辑集中管理。

11.2 任务清单

  • 在 canvas_agent/prompt.py 中集中定义 prompt 常量
  • 在 canvas_agent/agent.py 或节点工具模块中封装模型调用

11.3 最少需要的 prompt

  • 新建 artifact prompt
  • 整体重写 artifact prompt
  • 路由判断 prompt
  • followup prompt

11.4 设计建议

提示词必须显式约束:

  • 输出完整文档还是局部片段
  • 是否允许修改类型
  • 是否允许修改标题
  • 对文本和代码的输出格式要求

11.5 模型调用封装建议

不要在每个节点里重复拼模型配置。

建议提供统一函数:

  • get_canvas_model(...)
  • invoke_canvas_model(...)

11.6 验收标准

  • prompt 集中管理
  • 节点中模型调用逻辑可复用

12. 阶段七:Gateway 线程接口兼容

12.1 任务目标

让前端读取线程状态时能拿到结构化 artifact。

12.2 任务清单

  • 检查 threads.py
  • 扩展线程 state 响应的 values
  • 确保 artifact 字段会被安全返回

12.3 要求

  • GET /api/threads/{id}
  • 线程历史
  • 状态读取接口

都要兼容 artifact

12.4 注意事项

  • 历史 checkpoint 可能没有 artifact
  • 旧线程必须兼容
  • 结构化字段不能被错误裁剪

12.5 验收标准

  • 前端取线程时能拿到 artifact
  • 刷新页面后 Canvas 内容能恢复

13. 阶段八:流式输出适配

13.1 任务目标

让 Canvas 模式的 artifact 能通过 LangGraph 流实时更新。

13.2 任务清单

  • 检查运行时序列化逻辑
  • 确保 artifact 在流事件中可见
  • 明确前端消费 values 还是 updates

13.3 输出建议

首版允许采用较简单策略:

  • 每次节点完成后输出完整 artifact

不强制首版做精细的 token 级 artifact 局部流。

13.4 原因

完整对象覆盖更新:

  • 容易实现
  • 容易调试
  • 前后端一致性更好

13.5 二期方向

后续再考虑:

  • 局部 chunk 更新
  • 文本与代码差异化流式拼接

13.6 验收标准

  • 前端发送请求时,artifact 能跟随 run 更新
  • 流结束后状态与线程最终值一致

14. 阶段九:模型接口扩展

14.1 任务目标

让前端能拿到适合 Canvas 模式的模型能力信息。

14.2 任务清单

14.3 现有字段之外建议新增

  • provider
  • supports_vision
  • supports_tool_calling
  • supports_canvas_generation
  • supports_canvas_rewrite
  • supports_canvas_code_edit
  • supports_streaming_text
  • supports_streaming_tool_calls
  • is_local
  • base_url

14.4 注意事项

不是所有字段都必须从配置文件显式写出。

可以采用:

  • 配置直出
  • provider 推断
  • 默认值补齐

14.5 验收标准

  • 前端模型选择器能获取足够元数据
  • 本地模型和云模型能区分

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

15.1 任务目标

支持像 open-canvas 一样自由配置本地模型,但配置真源在 DeerFlow。

15.2 原则

  • 以 config.yaml 为唯一真源
  • 前端不依赖 open-canvas 的 TS 模型表
  • 后端负责把配置转换成前端可消费的能力描述

15.3 首批支持范围

推荐先支持:

  • Ollama
  • OpenAI-compatible 本地服务

例如:

  • LM Studio
  • vLLM
  • LocalAI
  • One API/OpenAI 兼容代理

15.4 配置要求

建议模型配置支持以下字段:

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

15.5 Canvas 额外能力字段

建议再增加:

  • supports_canvas_generation
  • supports_canvas_rewrite
  • supports_canvas_code_edit

15.6 验收标准

  • 配置本地模型后 /api/models 可见
  • canvas_agent 可调用本地模型
  • 至少文本生成和整体改写可用

16. 阶段十一:整体重写节点完善

16.1 任务目标

让已有 artifact 能被稳定整体重写并产生新版本。

16.2 任务清单

  • 实现 rewrite_artifact
  • 明确文本与代码两种重写路径
  • 维护标题和类型变更规则

16.3 规则建议

  • 默认保持当前类型
  • 用户明确要求时才允许改类型
  • 默认保持标题
  • 用户明确换主题时可更新标题

16.4 结果写入规则

  • 新版本追加到 contents
  • currentIndex 指向新版本

16.5 验收标准

  • 文本 artifact 整体重写正常
  • 代码 artifact 整体重写正常
  • 历史版本保留

17. 阶段十二:局部改写节点

17.1 任务目标

支持文本和代码的局部选区修改。

17.2 任务清单

  • 新增 update_highlighted_text.py
  • 新增 update_highlighted_code.py
  • 在状态中消费选区信息

17.3 文本局部改写要求

输入:

  • 当前 fullMarkdown
  • 选区起止
  • 选中原文
  • 用户修改指令

输出:

  • 只返回替换片段或返回完整合并后文本

17.4 首版建议

首版优先采用“后端返回完整合并后文本”策略。

原因:

  • 前端逻辑更轻
  • 状态更一致

17.5 代码局部改写要求

输入:

  • 当前代码全文
  • 选区代码片段
  • 选区边界
  • 用户修改指令

输出:

  • 新的完整代码文本

17.6 验收标准

  • 文本局部改写成功
  • 代码局部改写成功
  • 未选中区域不被误改

18. 阶段十三:快捷动作节点

18.1 任务目标

支持前端动作栏触发不同的重写行为。

18.2 任务清单

  • 新增 quick_actions.py
  • 定义动作 id 到 prompt 的映射
  • 在路由节点中识别 quick_action_id

18.3 首版动作建议

文本:

  • expand
  • shorten
  • formalize
  • casualize

代码:

  • add_comments
  • add_logs
  • fix_bugs

18.4 实现建议

动作不要散落在各节点里硬编码。

建议集中成映射表:

  • action_id -> prompt builder

18.5 验收标准

  • 指定动作可触发不同结果
  • 动作执行后生成新版本

19. 阶段十四:Web 搜索增强

19.1 任务目标

支持 Canvas 模式在需要时引入搜索结果。

19.2 任务清单

  • 新增 web_search.py
  • 消费 web_search_enabled
  • 将搜索结果写入 web_search_results

19.3 首版策略

首版只做:

  • 打开开关后,生成/重写前先搜索
  • 把结果摘要注入 prompt

先不做复杂页面抓取多轮链路。

19.4 验收标准

  • 开关打开时能引入搜索结果
  • 结果可回传前端展示

20. 阶段十五:线程创建与 metadata 策略

20.1 任务目标

让 Canvas 线程在创建和恢复时保留必要上下文。

20.2 任务清单

  • 约定前端创建 Canvas thread 时写入 metadata
  • 后端在 thread search / get 中保留这些 metadata

20.3 推荐 metadata

  • ui_mode: "canvas"
  • agent_id: "canvas_agent"
  • model_name
  • canvas_type 可选

20.4 验收标准

  • Canvas thread 与普通 thread 可区分
  • 恢复线程时前端可据 metadata 恢复 UI

21. 阶段十六:Gateway 扩展接口评估

21.1 任务目标

判断是否需要新增 Canvas 专用 REST API。

21.2 原则

能复用现有线程状态与 LangGraph 流,就不要新增太多新接口。

21.3 可以先不新增的接口

  • Canvas artifact 专用 CRUD
  • Canvas 快捷动作专用接口

这些都可以先通过:

  • 线程 state
  • runs.stream

完成。

21.4 可能需要新增的接口

二期如果需要,可增加:

  • GET /api/canvas/models
  • POST /api/canvas/export
  • POST /api/canvas/convert-to-file

21.5 验收标准

  • 首版尽量少增接口
  • 协议尽量复用现有线程与 run 模型

22. 阶段十七:持久化与导出联动

22.1 任务目标

让 Canvas 文档能和现有文件 artifact 体系联动。

22.2 任务清单

  • 规划导出接口
  • 规划 artifact 转文件逻辑
  • 规划从 Canvas 生成 outputs 文件

22.3 推荐能力

  • 保存为 .md
  • 保存为代码文件
  • 将导出文件加入现有 artifacts: list[str]

22.4 首版建议

这部分不是最早阶段必须做的。

建议等核心 Canvas 生成与重写稳定后再接。

22.5 验收标准

  • 导出文件能出现在现有 artifact 文件体系中

23. 测试清单

23.1 单元测试建议

优先覆盖:

  • artifact 协议校验
  • 版本追加逻辑
  • 标题/类型变更规则
  • 文本局部改写拼接逻辑
  • 代码局部改写拼接逻辑

23.2 集成测试建议

应覆盖:

  • 创建 Canvas thread
  • 首次生成 artifact
  • 整体重写
  • 局部改写
  • 模型切换
  • 本地模型调用

23.3 回归测试重点

重点检查现有功能未被破坏:

  • 普通 lead_agent 对话
  • 文件型 artifacts
  • uploads
  • memory
  • scheduled tasks

23.4 验收标准

  • Canvas 新功能通过
  • 现有 DeerFlow 核心路径无回归

24. 推荐开发顺序

强烈建议按以下顺序推进:

  1. 线程状态扩展
  2. artifact 协议定稿
  3. canvas_agent 注册
  4. 最小图闭环
  5. 线程读取与流式返回
  6. 模型接口扩展
  7. 整体生成与整体改写
  8. 局部改写
  9. 快捷动作
  10. 本地模型增强
  11. Web 搜索增强
  12. 导出联动

不要一开始就做:

  • 快捷动作全集
  • 局部 token 级流式 artifact 更新
  • 复杂导出体系

25. 多人协作拆分建议

A 组:状态与线程

  • thread_state.py
  • 线程协议
  • Gateway 线程兼容

B 组:Canvas Agent 图

  • canvas_agent
  • prompt
  • route/generate/rewrite/followup

C 组:模型与配置

  • /api/models
  • 本地模型配置
  • provider 兼容

D 组:增强能力

  • 局部改写
  • 快捷动作
  • Web 搜索

26. 首版最小可交付范围

后端首版建议只交付这些:

  • 扩展线程状态支持 artifact
  • 新增 canvas_agent
  • 支持文本/代码 artifact 首次生成
  • 支持整体重写
  • 支持版本历史
  • 扩展 /api/models 返回 Canvas 能力元数据
  • 支持至少一种本地模型接入

首版先不强制:

  • 局部高亮改写
  • 全量快捷动作
  • 搜索增强
  • 导出文件联动

27. 总验收标准

27.1 功能层

  • 无 artifact 时可生成新文档
  • 有 artifact 时可整体重写
  • 版本历史可保留
  • 前端刷新后可恢复

27.2 协议层

  • artifact 字段稳定
  • 流式与最终线程状态一致
  • 模型能力字段可用于前端判断

27.3 兼容层

  • 不破坏 lead_agent
  • 不破坏现有 artifacts: list[str]
  • 不破坏现有 Gateway 核心接口

28. 下一步建议

完成本文档后,建议继续补两份工程文档:

28.1 Canvas 状态协议文档

明确:

  • artifact
  • highlighted_text
  • highlighted_code
  • quick_action_id
  • web_search_results

的最终 JSON 格式。

28.2 Canvas Agent 节点接口文档

逐节点定义:

  • 输入字段
  • 输出字段
  • prompt 责任
  • 错误处理

这样进入实际编码时会更顺畅。