1374 lines
27 KiB
Markdown
1374 lines
27 KiB
Markdown
# Open Canvas 前端实施清单
|
||
|
||
## 1. 文档目标
|
||
|
||
本文档是 [openCanvas.md](./openCanvas.md) 的前端落地版清单。
|
||
|
||
目标是把 Canvas 模式拆成可以直接开发的前端任务,覆盖:
|
||
|
||
- 路由接入
|
||
- 目录结构
|
||
- 页面布局
|
||
- 状态管理
|
||
- 组件拆分
|
||
- 接口适配
|
||
- 流式更新
|
||
- 版本管理
|
||
- 局部改写
|
||
- 模型选择
|
||
- 验收标准
|
||
|
||
本文档默认后端会配合新增结构化 `artifact` 字段与 `canvas_agent`。
|
||
|
||
---
|
||
|
||
## 2. 实施原则
|
||
|
||
### 2.1 总原则
|
||
|
||
- 不破坏现有 `workspace` 聊天页面
|
||
- 尽量复用现有基础设施
|
||
- 先做骨架,再接数据,再接智能行为
|
||
- 每一步都能跑、能看、能验收
|
||
|
||
### 2.2 可复用的现有能力
|
||
|
||
当前项目前端已有以下基础设施,可尽量复用:
|
||
|
||
- `react-router-dom` 路由体系
|
||
- `WorkspaceLayout` 工作区布局
|
||
- `@langchain/langgraph-sdk` 客户端
|
||
- `useThreadStream` 的流式线程模式
|
||
- 模型列表接口 `/api/models`
|
||
- 现有认证头注入机制
|
||
- `sonner` 提示
|
||
- `react-resizable-panels` 双栏/拖拽布局
|
||
- `CodeMirror` 代码编辑器
|
||
|
||
### 2.3 新增能力的边界
|
||
|
||
Canvas 模式前端是一个“新子系统”,但不建议做成完全独立的第二套应用。
|
||
|
||
建议方式:
|
||
|
||
- 复用现有壳层和 API 客户端
|
||
- 新建 `src/open-canvas` 目录承载新功能
|
||
- 将 Canvas 模式接到现有 Page 层路由里
|
||
|
||
---
|
||
|
||
## 3. 目标目录结构
|
||
|
||
建议新增如下目录:
|
||
|
||
```text
|
||
frontend-web/src/open-canvas/
|
||
api/
|
||
client.ts
|
||
models.ts
|
||
threads.ts
|
||
runs.ts
|
||
components/
|
||
layout/
|
||
CanvasShell.tsx
|
||
CanvasHeader.tsx
|
||
CanvasResizableLayout.tsx
|
||
chat/
|
||
CanvasChatPanel.tsx
|
||
CanvasMessageList.tsx
|
||
CanvasInputBox.tsx
|
||
CanvasWelcome.tsx
|
||
artifact/
|
||
CanvasArtifactPanel.tsx
|
||
CanvasArtifactRenderer.tsx
|
||
CanvasArtifactHeader.tsx
|
||
CanvasArtifactVersionNav.tsx
|
||
CanvasEmptyState.tsx
|
||
TextArtifactRenderer.tsx
|
||
CodeArtifactRenderer.tsx
|
||
selectors/
|
||
CanvasModelSelector.tsx
|
||
CanvasModeSelector.tsx
|
||
quick-actions/
|
||
QuickActionBar.tsx
|
||
QuickActionButton.tsx
|
||
web-search/
|
||
CanvasWebSearchPanel.tsx
|
||
contexts/
|
||
CanvasThreadContext.tsx
|
||
CanvasGraphContext.tsx
|
||
CanvasUIContext.tsx
|
||
hooks/
|
||
useCanvasThread.ts
|
||
useCanvasStream.ts
|
||
useCanvasArtifact.ts
|
||
useCanvasSelection.ts
|
||
useCanvasQuickActions.ts
|
||
pages/
|
||
CanvasHomePage.tsx
|
||
CanvasThreadPage.tsx
|
||
routes/
|
||
OpenCanvasRoutes.tsx
|
||
types/
|
||
artifact.ts
|
||
thread.ts
|
||
model.ts
|
||
selection.ts
|
||
quick-action.ts
|
||
utils/
|
||
artifact.ts
|
||
selection.ts
|
||
thread.ts
|
||
stream.ts
|
||
quick-actions.ts
|
||
constants/
|
||
index.ts
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 开发阶段总览
|
||
|
||
前端建议分为 10 个实施阶段:
|
||
|
||
1. 路由与目录骨架
|
||
2. Canvas 页面布局
|
||
3. 类型与状态协议
|
||
4. API 适配层
|
||
5. 线程和流式状态接入
|
||
6. Artifact 渲染与版本管理
|
||
7. 快速开始与空状态
|
||
8. 局部选区改写交互
|
||
9. 快捷动作系统
|
||
10. 模型选择与增强能力接入
|
||
|
||
建议每个阶段完成后都做一次可视化验收。
|
||
|
||
---
|
||
|
||
## 5. 阶段一:路由与目录骨架
|
||
|
||
### 5.1 任务目标
|
||
|
||
把 Canvas 模式先挂到系统里,确保页面可进入。
|
||
|
||
### 5.2 任务清单
|
||
|
||
- 新建 `src/open-canvas/` 目录
|
||
- 新建 `src/open-canvas/routes/OpenCanvasRoutes.tsx`
|
||
- 新建 `src/open-canvas/pages/CanvasHomePage.tsx`
|
||
- 新建 `src/open-canvas/pages/CanvasThreadPage.tsx`
|
||
- 修改 [PageRoutes.tsx](../src/pages/PageRoutes.tsx)
|
||
|
||
### 5.3 路由建议
|
||
|
||
建议新增:
|
||
|
||
- `/page/canvas`
|
||
- `/page/canvas/:thread_id`
|
||
|
||
建议在 `PageLayout` 内部新增:
|
||
|
||
- `path="canvas/*"`
|
||
|
||
子路由建议:
|
||
|
||
- `index -> CanvasHomePage`
|
||
- `:thread_id -> CanvasThreadPage`
|
||
- `new -> 跳转到 CanvasHomePage 或创建临时线程态`
|
||
|
||
### 5.4 页面行为要求
|
||
|
||
`CanvasHomePage`:
|
||
|
||
- 展示 Canvas 欢迎页
|
||
- 展示快速开始入口
|
||
- 可进入新建文本或代码模式
|
||
|
||
`CanvasThreadPage`:
|
||
|
||
- 只负责线程级页面装配
|
||
- 挂载所有 Canvas 上下文提供器
|
||
- 渲染主布局组件
|
||
|
||
### 5.5 验收标准
|
||
|
||
- 访问 `/page/canvas` 正常
|
||
- 访问 `/page/canvas/xxx` 正常
|
||
- 不影响 `/page/workspace/*`
|
||
- 页面为独立功能入口
|
||
|
||
---
|
||
|
||
## 6. 阶段二:Canvas 页面布局
|
||
|
||
### 6.1 任务目标
|
||
|
||
先搭出稳定的“左聊天右画布”骨架。
|
||
|
||
### 6.2 任务清单
|
||
|
||
- 新建 `layout/CanvasShell.tsx`
|
||
- 新建 `layout/CanvasHeader.tsx`
|
||
- 新建 `layout/CanvasResizableLayout.tsx`
|
||
- 新建 `chat/CanvasChatPanel.tsx`
|
||
- 新建 `artifact/CanvasArtifactPanel.tsx`
|
||
- 新建 `artifact/CanvasEmptyState.tsx`
|
||
|
||
### 6.3 布局要求
|
||
|
||
推荐布局:
|
||
|
||
- 顶部:Canvas 标题栏
|
||
- 左侧:聊天面板
|
||
- 右侧:artifact 面板
|
||
- 可选右抽屉:Web 搜索结果
|
||
|
||
### 6.4 建议复用
|
||
|
||
可以优先复用:
|
||
|
||
- `react-resizable-panels`
|
||
- 现有按钮、分隔线、Tabs、Tooltip 等 UI 组件
|
||
|
||
### 6.5 初始状态要求
|
||
|
||
无 thread 或 thread 中无 artifact 时:
|
||
|
||
- 右侧显示空状态
|
||
- 左侧显示欢迎语和快速开始
|
||
|
||
### 6.6 验收标准
|
||
|
||
- 双栏布局稳定
|
||
- 可拖拽调整宽度
|
||
- 空状态显示正常
|
||
- 适配桌面优先,移动端先做降级布局
|
||
|
||
---
|
||
|
||
## 7. 阶段三:类型与状态协议
|
||
|
||
### 7.1 任务目标
|
||
|
||
先把前端需要消费和管理的数据类型定下来。
|
||
|
||
### 7.2 任务清单
|
||
|
||
- 新建 `types/artifact.ts`
|
||
- 新建 `types/thread.ts`
|
||
- 新建 `types/model.ts`
|
||
- 新建 `types/selection.ts`
|
||
- 新建 `types/quick-action.ts`
|
||
|
||
### 7.3 必要类型
|
||
|
||
#### artifact.ts
|
||
|
||
- `CanvasArtifact`
|
||
- `CanvasArtifactText`
|
||
- `CanvasArtifactCode`
|
||
- `CanvasArtifactContent`
|
||
|
||
#### selection.ts
|
||
|
||
- `CanvasTextSelection`
|
||
- `CanvasCodeSelection`
|
||
- `CanvasSelectionState`
|
||
|
||
#### thread.ts
|
||
|
||
- `CanvasThreadValues`
|
||
- `CanvasThreadMetadata`
|
||
- `CanvasThread`
|
||
|
||
### 7.4 建议结构
|
||
|
||
```ts
|
||
export type CanvasArtifact = {
|
||
currentIndex: number;
|
||
contents: CanvasArtifactContent[];
|
||
};
|
||
|
||
export type CanvasArtifactText = {
|
||
index: number;
|
||
type: "text";
|
||
title: string;
|
||
fullMarkdown: string;
|
||
};
|
||
|
||
export type CanvasArtifactCode = {
|
||
index: number;
|
||
type: "code";
|
||
title: string;
|
||
language: string;
|
||
code: string;
|
||
};
|
||
```
|
||
|
||
### 7.5 线程值类型建议
|
||
|
||
```ts
|
||
export type CanvasThreadValues = {
|
||
title?: string;
|
||
messages?: Message[];
|
||
artifact?: CanvasArtifact;
|
||
web_search_results?: unknown[];
|
||
todos?: unknown[];
|
||
};
|
||
```
|
||
|
||
### 7.6 验收标准
|
||
|
||
- 所有 Canvas 组件只依赖 `open-canvas/types`
|
||
- 不把类型散落到页面或组件内部
|
||
- 前后端协议字段统一命名
|
||
|
||
---
|
||
|
||
## 8. 阶段四:前端 Context 设计
|
||
|
||
### 8.1 任务目标
|
||
|
||
把 Canvas 的状态拆成职责清晰的三层上下文。
|
||
|
||
### 8.2 任务清单
|
||
|
||
- 新建 `CanvasThreadContext.tsx`
|
||
- 新建 `CanvasGraphContext.tsx`
|
||
- 新建 `CanvasUIContext.tsx`
|
||
|
||
### 8.3 职责划分
|
||
|
||
#### CanvasThreadContext
|
||
|
||
负责:
|
||
|
||
- 当前 thread id
|
||
- thread 基础信息
|
||
- thread 创建/切换
|
||
- 模型名称
|
||
- 模型配置
|
||
|
||
#### CanvasGraphContext
|
||
|
||
负责:
|
||
|
||
- messages
|
||
- artifact
|
||
- runId
|
||
- streaming 状态
|
||
- error 状态
|
||
- 发送消息
|
||
- 停止生成
|
||
- 切换版本
|
||
- 更新 artifact 内容
|
||
|
||
#### CanvasUIContext
|
||
|
||
负责:
|
||
|
||
- 面板折叠状态
|
||
- 是否正在编辑
|
||
- 当前选区
|
||
- Web 搜索面板开关
|
||
- 快捷动作面板开关
|
||
|
||
### 8.4 验收标准
|
||
|
||
- 页面组件不直接持有大量跨层 useState
|
||
- 聊天状态和 UI 状态分离
|
||
- 线程切换时可安全重置状态
|
||
|
||
---
|
||
|
||
## 9. 阶段五:API 适配层
|
||
|
||
### 9.1 任务目标
|
||
|
||
为 Canvas 模式建立专用的前端 API 包装层。
|
||
|
||
### 9.2 任务清单
|
||
|
||
- 新建 `api/client.ts`
|
||
- 新建 `api/models.ts`
|
||
- 新建 `api/threads.ts`
|
||
- 新建 `api/runs.ts`
|
||
|
||
### 9.3 设计要求
|
||
|
||
不要让页面组件直接到处调用现有 `getAPIClient()` 或裸 `fetch`。
|
||
|
||
建议统一在 `src/open-canvas/api/` 中封装。
|
||
|
||
### 9.4 需要封装的能力
|
||
|
||
#### models.ts
|
||
|
||
- `loadCanvasModels()`
|
||
- 对现有 `/api/models` 结果做标准化
|
||
|
||
#### threads.ts
|
||
|
||
- `createCanvasThread()`
|
||
- `getCanvasThread(threadId)`
|
||
- `updateCanvasThreadMetadata(threadId, metadata)`
|
||
- `updateCanvasThreadState(threadId, values)`
|
||
|
||
#### runs.ts
|
||
|
||
- `streamCanvasRun(...)`
|
||
- `stopCanvasRun(...)`
|
||
|
||
### 9.5 与现有 API 的关系
|
||
|
||
底层可以复用:
|
||
|
||
- `src/core/api/api-client.ts`
|
||
- `src/core/api/fetch-client.ts`
|
||
|
||
但上层调用应走 Canvas 专用 API。
|
||
|
||
### 9.6 验收标准
|
||
|
||
- 页面层不直接拼接 URL
|
||
- Canvas API 调用集中管理
|
||
- 后续改协议时只动一层
|
||
|
||
---
|
||
|
||
## 10. 阶段六:线程与流式状态接入
|
||
|
||
### 10.1 任务目标
|
||
|
||
让 Canvas 页面能像现有 ChatPage 一样收发消息并接流。
|
||
|
||
### 10.2 任务清单
|
||
|
||
- 新建 `hooks/useCanvasThread.ts`
|
||
- 新建 `hooks/useCanvasStream.ts`
|
||
- 新建 `utils/stream.ts`
|
||
|
||
### 10.3 设计建议
|
||
|
||
可以参考现有:
|
||
|
||
- [ChatPage.tsx](../src/pages/ChatPage.tsx)
|
||
- [threads/hooks.ts](../src/core/threads/hooks.ts)
|
||
|
||
但不要直接把现有 `ChatPage` 复制一份。
|
||
|
||
### 10.4 `useCanvasThread` 负责
|
||
|
||
- 当前 thread id 管理
|
||
- 新建/切换 thread
|
||
- 从 URL 参数恢复 thread
|
||
|
||
### 10.5 `useCanvasStream` 负责
|
||
|
||
- 发送消息
|
||
- 停止生成
|
||
- 处理流式事件
|
||
- 更新 `messages`
|
||
- 更新 `artifact`
|
||
- 更新 `runId`
|
||
|
||
### 10.6 流式更新要求
|
||
|
||
首版可以假设后端在 `values` 或 `updates` 中返回:
|
||
|
||
- `messages`
|
||
- `artifact`
|
||
|
||
前端需要:
|
||
|
||
- 新消息追加
|
||
- artifact 覆盖或增量更新
|
||
- 流结束后保持最终状态
|
||
|
||
### 10.7 验收标准
|
||
|
||
- 能发消息
|
||
- 能收到消息
|
||
- 能实时更新 artifact
|
||
- 停止按钮可用
|
||
|
||
---
|
||
|
||
## 11. 阶段七:Artifact 渲染器
|
||
|
||
### 11.1 任务目标
|
||
|
||
实现文本/代码两类 artifact 的基础渲染与切换。
|
||
|
||
### 11.2 任务清单
|
||
|
||
- 新建 `artifact/CanvasArtifactRenderer.tsx`
|
||
- 新建 `artifact/CanvasArtifactHeader.tsx`
|
||
- 新建 `artifact/CanvasArtifactVersionNav.tsx`
|
||
- 新建 `artifact/TextArtifactRenderer.tsx`
|
||
- 新建 `artifact/CodeArtifactRenderer.tsx`
|
||
|
||
### 11.3 组件职责
|
||
|
||
#### CanvasArtifactRenderer
|
||
|
||
- 判断当前 artifact 是否存在
|
||
- 判断当前内容是文本还是代码
|
||
- 分发到具体渲染器
|
||
|
||
#### CanvasArtifactHeader
|
||
|
||
- 显示标题
|
||
- 显示保存状态
|
||
- 显示版本导航
|
||
|
||
#### CanvasArtifactVersionNav
|
||
|
||
- 上一个版本
|
||
- 下一个版本
|
||
- 当前版本号
|
||
|
||
#### TextArtifactRenderer
|
||
|
||
- 渲染 markdown 内容
|
||
- 支持编辑模式
|
||
- 支持文本选区
|
||
|
||
#### CodeArtifactRenderer
|
||
|
||
- 使用 CodeMirror
|
||
- 支持语言模式切换
|
||
- 支持代码选区
|
||
|
||
### 11.4 首版策略
|
||
|
||
文本首版建议:
|
||
|
||
- 编辑态用 textarea 或现有 markdown 编辑器
|
||
- 展示态用现有 markdown renderer
|
||
|
||
代码首版建议:
|
||
|
||
- 直接复用现有 CodeMirror 基础能力
|
||
|
||
### 11.5 验收标准
|
||
|
||
- 文本 artifact 可看可编辑
|
||
- 代码 artifact 可看可编辑
|
||
- 版本切换正确
|
||
- 标题与当前版本一致
|
||
|
||
---
|
||
|
||
## 12. 阶段八:快速开始与空状态
|
||
|
||
### 12.1 任务目标
|
||
|
||
让用户在没有任何 artifact 时也能顺畅开始。
|
||
|
||
### 12.2 任务清单
|
||
|
||
- 新建 `chat/CanvasWelcome.tsx`
|
||
- 在 `CanvasHomePage` 中增加快速开始面板
|
||
- 在 `CanvasThreadPage` 空状态时提供快速开始
|
||
|
||
### 12.3 快速开始项建议
|
||
|
||
- 空白文本
|
||
- 空白代码
|
||
- React 组件模板
|
||
- HTML 页面模板
|
||
- Python 脚本模板
|
||
|
||
### 12.4 行为要求
|
||
|
||
点击后:
|
||
|
||
- 创建本地前端 artifact 草稿
|
||
- 必要时自动创建 thread
|
||
- 自动进入编辑态
|
||
|
||
### 12.5 验收标准
|
||
|
||
- 不发消息也能先建立 artifact
|
||
- 新建文本/代码入口可用
|
||
- 初始编辑体验完整
|
||
|
||
---
|
||
|
||
## 13. 阶段九:Artifact 版本管理
|
||
|
||
### 13.1 任务目标
|
||
|
||
让每次 AI 生成或修改都成为一个新版本。
|
||
|
||
### 13.2 任务清单
|
||
|
||
- 新建 `hooks/useCanvasArtifact.ts`
|
||
- 新建 `utils/artifact.ts`
|
||
|
||
### 13.3 必要能力
|
||
|
||
- 获取当前版本内容
|
||
- 切换版本
|
||
- 更新当前版本内容
|
||
- 追加新版本
|
||
- 判断 artifact 是否为空
|
||
|
||
### 13.4 推荐工具函数
|
||
|
||
- `getCurrentArtifactContent(artifact)`
|
||
- `setCurrentArtifactIndex(artifact, index)`
|
||
- `appendArtifactVersion(artifact, content)`
|
||
- `replaceCurrentArtifactContent(artifact, content)`
|
||
- `isTextArtifact(content)`
|
||
- `isCodeArtifact(content)`
|
||
|
||
### 13.5 注意事项
|
||
|
||
- 前端切版本不能直接修改原对象引用
|
||
- 每次更新要创建新对象,避免渲染异常
|
||
|
||
### 13.6 验收标准
|
||
|
||
- AI 更新后版本数增加
|
||
- 手动切换历史版本稳定
|
||
- 当前版本高亮正确
|
||
|
||
---
|
||
|
||
## 14. 阶段十:局部选区交互
|
||
|
||
### 14.1 任务目标
|
||
|
||
实现局部改写所需的前端选区采集与展示。
|
||
|
||
### 14.2 任务清单
|
||
|
||
- 新建 `hooks/useCanvasSelection.ts`
|
||
- 新建 `utils/selection.ts`
|
||
|
||
### 14.3 文本选区需求
|
||
|
||
- 获取选中起止位置
|
||
- 获取选中文本
|
||
- 在 UI 上显示“已选中某段内容”
|
||
- 支持清除选区
|
||
|
||
### 14.4 代码选区需求
|
||
|
||
- 获取 CodeMirror 选区
|
||
- 保存选中代码内容
|
||
- 保存 start/end 或行列信息
|
||
|
||
### 14.5 交互建议
|
||
|
||
可以在选区出现后展示浮层或工具条:
|
||
|
||
- 改写
|
||
- 精简
|
||
- 扩写
|
||
- 解释
|
||
|
||
首版先只保留:
|
||
|
||
- “对所选内容进行修改” 的统一入口
|
||
|
||
### 14.6 验收标准
|
||
|
||
- 文本选区可读
|
||
- 代码选区可读
|
||
- 选区状态可清空
|
||
- 切换版本或 thread 时选区自动重置
|
||
|
||
---
|
||
|
||
## 15. 阶段十一:聊天面板适配
|
||
|
||
### 15.1 任务目标
|
||
|
||
实现 Canvas 模式专用聊天面板,不直接塞回现有 ChatBox。
|
||
|
||
### 15.2 任务清单
|
||
|
||
- 新建 `chat/CanvasMessageList.tsx`
|
||
- 新建 `chat/CanvasInputBox.tsx`
|
||
- 新建 `chat/CanvasChatPanel.tsx`
|
||
|
||
### 15.3 设计建议
|
||
|
||
可以参考现有 ChatPage 的结构,但建议把 Canvas 模式聊天区做成更轻量版本。
|
||
|
||
### 15.4 必要功能
|
||
|
||
- 展示消息列表
|
||
- 展示生成中状态
|
||
- 提交输入
|
||
- 停止生成
|
||
- 显示模型选择器
|
||
- 显示 Web 搜索开关
|
||
|
||
### 15.5 可以复用
|
||
|
||
- 现有消息渲染组件中的部分能力
|
||
- 现有 InputBox 的一部分交互逻辑
|
||
|
||
### 15.6 不建议直接复用
|
||
|
||
- 当前工作区的文件 artifact 面板耦合
|
||
- 当前以文件产物为中心的 ChatBox 结构
|
||
|
||
### 15.7 验收标准
|
||
|
||
- Canvas 聊天区独立可用
|
||
- 能与 artifact 面板联动
|
||
- 布局不受现有文件 artifact 影响
|
||
|
||
---
|
||
|
||
## 16. 阶段十二:模型选择器
|
||
|
||
### 16.1 任务目标
|
||
|
||
让 Canvas 模式可以使用 DeerFlow 的动态模型列表。
|
||
|
||
### 16.2 任务清单
|
||
|
||
- 新建 `selectors/CanvasModelSelector.tsx`
|
||
- 在 `api/models.ts` 中做标准化
|
||
|
||
### 16.3 UI 要求
|
||
|
||
- 显示模型名
|
||
- 显示是否本地模型
|
||
- 显示是否支持视觉/推理/Canvas
|
||
|
||
### 16.4 状态要求
|
||
|
||
- 当前 thread 记录 `model_name`
|
||
- 必要时记录 `model_config`
|
||
- 切换 thread 时能恢复模型
|
||
|
||
### 16.5 首版能力
|
||
|
||
首版可以只做:
|
||
|
||
- 下拉选择模型
|
||
- 将模型信息写入 thread metadata 或 run configurable
|
||
|
||
### 16.6 验收标准
|
||
|
||
- 模型列表正确展示
|
||
- 切换模型后发消息使用新模型
|
||
- 本地模型与云模型能在 UI 中区分
|
||
|
||
---
|
||
|
||
## 17. 阶段十三:快捷动作栏
|
||
|
||
### 17.1 任务目标
|
||
|
||
实现 artifact 上方或下方的快捷动作入口。
|
||
|
||
### 17.2 任务清单
|
||
|
||
- 新建 `quick-actions/QuickActionBar.tsx`
|
||
- 新建 `quick-actions/QuickActionButton.tsx`
|
||
- 新建 `hooks/useCanvasQuickActions.ts`
|
||
- 新建 `utils/quick-actions.ts`
|
||
|
||
### 17.3 首版动作建议
|
||
|
||
文本类:
|
||
|
||
- 扩写
|
||
- 精简
|
||
- 改正式
|
||
- 改口语
|
||
|
||
代码类:
|
||
|
||
- 加注释
|
||
- 加日志
|
||
- 修 bug
|
||
|
||
### 17.4 行为要求
|
||
|
||
点击动作后:
|
||
|
||
- 写入 `quick_action_id`
|
||
- 触发一次 Canvas run
|
||
- 生成新的 artifact 版本
|
||
|
||
### 17.5 验收标准
|
||
|
||
- 动作栏根据 artifact 类型动态变化
|
||
- 动作点击后有效果
|
||
- 新版本正确生成
|
||
|
||
---
|
||
|
||
## 18. 阶段十四:Web 搜索面板
|
||
|
||
### 18.1 任务目标
|
||
|
||
为后续搜索增强预留 UI 和交互位置。
|
||
|
||
### 18.2 任务清单
|
||
|
||
- 新建 `web-search/CanvasWebSearchPanel.tsx`
|
||
- 在 `CanvasUIContext` 中增加开关状态
|
||
|
||
### 18.3 首版要求
|
||
|
||
- 只做抽屉面板
|
||
- 可展示结构化搜索结果列表
|
||
- 可开关显示
|
||
|
||
### 18.4 二期能力
|
||
|
||
- 支持点击来源预览
|
||
- 支持从结果插入上下文
|
||
|
||
### 18.5 验收标准
|
||
|
||
- 面板开关正常
|
||
- 搜索结果区域可承载数据
|
||
|
||
---
|
||
|
||
## 19. 阶段十五:页面装配
|
||
|
||
### 19.1 任务目标
|
||
|
||
将所有子模块整合到页面中。
|
||
|
||
### 19.2 任务清单
|
||
|
||
`CanvasHomePage.tsx`:
|
||
|
||
- 欢迎页
|
||
- 快速开始
|
||
- 最近 Canvas 线程入口
|
||
|
||
`CanvasThreadPage.tsx`:
|
||
|
||
- 解析 route params
|
||
- 挂载 `CanvasThreadContext`
|
||
- 挂载 `CanvasGraphContext`
|
||
- 挂载 `CanvasUIContext`
|
||
- 渲染 `CanvasShell`
|
||
|
||
### 19.3 结构建议
|
||
|
||
```tsx
|
||
<CanvasThreadProvider>
|
||
<CanvasGraphProvider>
|
||
<CanvasUIProvider>
|
||
<CanvasShell />
|
||
</CanvasUIProvider>
|
||
</CanvasGraphProvider>
|
||
</CanvasThreadProvider>
|
||
```
|
||
|
||
### 19.4 验收标准
|
||
|
||
- 页面层只负责装配,不承载复杂业务逻辑
|
||
- 子组件依赖上下文而不是层层 props drilling
|
||
|
||
---
|
||
|
||
## 20. 推荐逐文件实施顺序
|
||
|
||
建议按这个顺序建文件:
|
||
|
||
1. `routes/OpenCanvasRoutes.tsx`
|
||
2. `pages/CanvasHomePage.tsx`
|
||
3. `pages/CanvasThreadPage.tsx`
|
||
4. `types/*`
|
||
5. `contexts/CanvasThreadContext.tsx`
|
||
6. `contexts/CanvasUIContext.tsx`
|
||
7. `contexts/CanvasGraphContext.tsx`
|
||
8. `layout/CanvasShell.tsx`
|
||
9. `layout/CanvasResizableLayout.tsx`
|
||
10. `artifact/CanvasEmptyState.tsx`
|
||
11. `artifact/CanvasArtifactRenderer.tsx`
|
||
12. `artifact/TextArtifactRenderer.tsx`
|
||
13. `artifact/CodeArtifactRenderer.tsx`
|
||
14. `chat/CanvasChatPanel.tsx`
|
||
15. `chat/CanvasInputBox.tsx`
|
||
16. `api/*`
|
||
17. `hooks/useCanvasStream.ts`
|
||
18. `hooks/useCanvasSelection.ts`
|
||
19. `quick-actions/*`
|
||
20. `web-search/*`
|
||
|
||
---
|
||
|
||
## 21. 开发任务拆分建议
|
||
|
||
如果多人协作,建议这样拆:
|
||
|
||
### A 组:页面与路由
|
||
|
||
- 路由接入
|
||
- 页面骨架
|
||
- 主布局
|
||
|
||
### B 组:artifact 视图
|
||
|
||
- artifact 类型
|
||
- 渲染器
|
||
- 版本导航
|
||
- 代码/文本编辑器
|
||
|
||
### C 组:聊天与流式
|
||
|
||
- thread 管理
|
||
- stream 接入
|
||
- 消息面板
|
||
- 模型切换
|
||
|
||
### D 组:增强交互
|
||
|
||
- 选区
|
||
- 快捷动作
|
||
- 搜索面板
|
||
|
||
---
|
||
|
||
## 22. 每阶段验收清单
|
||
|
||
### 22.1 阶段一到三
|
||
|
||
- 路由正常
|
||
- 空页面正常
|
||
- 类型编译通过
|
||
- 目录结构清晰
|
||
|
||
### 22.2 阶段四到六
|
||
|
||
- thread 可创建/读取
|
||
- 消息可发送
|
||
- artifact 可展示
|
||
- 流式结果可更新
|
||
|
||
### 22.3 阶段七到九
|
||
|
||
- 文本/代码 artifact 渲染正确
|
||
- 版本导航正确
|
||
- 快速开始可用
|
||
- 模型选择可用
|
||
|
||
### 22.4 阶段十到十四
|
||
|
||
- 局部选区可采集
|
||
- 快捷动作可触发
|
||
- 搜索面板可显示
|
||
- 各功能互不冲突
|
||
|
||
---
|
||
|
||
## 23. 风险点与规避方式
|
||
|
||
### 23.1 不要直接复制现有 ChatPage
|
||
|
||
原因:
|
||
|
||
- 现有页面与文件 artifact 耦合较重
|
||
- Canvas 需要结构化 artifact 而不是文件列表
|
||
|
||
### 23.2 不要把所有状态都放一个 Context
|
||
|
||
原因:
|
||
|
||
- 更新频率高
|
||
- 容易导致全树重渲染
|
||
|
||
### 23.3 不要先做复杂富文本
|
||
|
||
原因:
|
||
|
||
- 选区映射复杂
|
||
- 首版容易卡在编辑器实现而不是业务链路
|
||
|
||
建议先以:
|
||
|
||
- `fullMarkdown`
|
||
- `textarea/markdown renderer`
|
||
|
||
作为最小闭环。
|
||
|
||
### 23.4 不要前端硬编码模型表
|
||
|
||
原因:
|
||
|
||
- 后端才是真源
|
||
- 后期本地模型和自定义 provider 会频繁变化
|
||
|
||
---
|
||
|
||
## 24. 首版最小可交付范围
|
||
|
||
前端首版建议只交付这些:
|
||
|
||
- `canvas/*` 路由
|
||
- Canvas 双栏布局
|
||
- 文本/代码 artifact 渲染
|
||
- 模型选择器
|
||
- 流式聊天
|
||
- artifact 版本切换
|
||
- 快速开始
|
||
|
||
首版先不强制包含:
|
||
|
||
- 复杂文本局部高亮浮层
|
||
- 复杂快捷动作配置中心
|
||
- 高级 Web 搜索结果联动
|
||
|
||
---
|
||
|
||
## 25. 下一步建议
|
||
|
||
完成本文档后,建议继续产出两份更细的执行文件:
|
||
|
||
### 25.1 前端文件创建顺序清单
|
||
|
||
按天或按 PR 颗粒度,列出:
|
||
|
||
- 每一批次新建哪些文件
|
||
- 每一批次修改哪些已有文件
|
||
|
||
### 25.2 前端组件接口文档
|
||
|
||
列出关键组件 props:
|
||
|
||
- `CanvasShell`
|
||
- `CanvasChatPanel`
|
||
- `CanvasArtifactRenderer`
|
||
- `CanvasModelSelector`
|
||
|
||
这样正式开工时会更顺畅。
|
||
---
|
||
|
||
## 26. 参考源码映射
|
||
|
||
前端实施清单建议补充对 `langchain-ai/open-canvas` 源码的“映射式参考”,但不建议把源码大段粘贴进本文档。
|
||
|
||
推荐做法是:
|
||
|
||
- 记录参考文件路径
|
||
- 说明它解决了什么问题
|
||
- 说明在 DeerFlow 前端里应该落到哪个模块
|
||
- 只摘能力点,不摘整段实现
|
||
|
||
这样做的原因:
|
||
|
||
- 文档更清晰
|
||
- 不会把 Next.js 运行时细节误当成可直接迁移代码
|
||
- 后续维护更轻
|
||
|
||
### 26.1 推荐参考文件总览
|
||
|
||
以下文件最值得作为前端实现参考:
|
||
|
||
- `apps/web/src/contexts/GraphContext.tsx`
|
||
- `apps/web/src/components/canvas/canvas.tsx`
|
||
- `apps/web/src/components/artifacts/ArtifactRenderer.tsx`
|
||
- `apps/web/src/components/artifacts/TextRenderer.tsx`
|
||
- `apps/web/src/components/artifacts/CodeRenderer.tsx`
|
||
- `apps/web/src/contexts/ThreadProvider.tsx`
|
||
- `apps/web/src/contexts/AssistantContext.tsx`
|
||
- `apps/web/src/hooks/useRuns.tsx`
|
||
- `apps/web/src/types.ts`
|
||
- `packages/shared/src/types.ts`
|
||
- `packages/shared/src/models.ts`
|
||
- `packages/shared/src/utils/artifacts.ts`
|
||
|
||
### 26.2 逐文件映射建议
|
||
|
||
#### `apps/web/src/contexts/GraphContext.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 这是 open-canvas 前端最核心的状态管理文件之一
|
||
- 管理消息、artifact、流式状态、保存状态、版本切换、局部更新
|
||
- 处理流中 artifact 更新和 thread 切换
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/contexts/CanvasGraphContext.tsx`
|
||
- `src/open-canvas/hooks/useCanvasStream.ts`
|
||
- `src/open-canvas/utils/stream.ts`
|
||
- `src/open-canvas/utils/artifact.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- artifact 如何作为线程主状态存在
|
||
- 流式过程中如何同步 messages 与 artifact
|
||
- 切换 thread 时如何恢复状态
|
||
- 如何维护“当前版本”和“已保存状态”
|
||
|
||
不建议直接照搬的部分:
|
||
|
||
- 与 Next.js、`nuqs`、open-canvas 内部 hook 耦合的代码
|
||
- 与其后端返回格式强绑定的处理逻辑
|
||
|
||
#### `apps/web/src/components/canvas/canvas.tsx`
|
||
|
||
参考价值:
|
||
|
||
- Open Canvas 的主页面装配组件
|
||
- 管理左聊天右画布布局
|
||
- 定义快速开始逻辑
|
||
- 管理 chat collapsed、artifact 初始创建
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/components/layout/CanvasShell.tsx`
|
||
- `src/open-canvas/components/layout/CanvasResizableLayout.tsx`
|
||
- `src/open-canvas/pages/CanvasThreadPage.tsx`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 快速开始时如何创建文本或代码 artifact
|
||
- 左右双栏如何组织
|
||
- 页面级状态和上下文边界怎么划分
|
||
|
||
不建议直接照搬的部分:
|
||
|
||
- Next 路由参数逻辑
|
||
- 与 open-canvas ThreadProvider 强耦合的状态恢复代码
|
||
|
||
#### `apps/web/src/components/artifacts/ArtifactRenderer.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 负责 artifact 总渲染分发
|
||
- 根据当前版本内容选择文本或代码渲染器
|
||
- 负责版本导航和选区交互挂钩
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/components/artifact/CanvasArtifactRenderer.tsx`
|
||
- `src/open-canvas/components/artifact/CanvasArtifactHeader.tsx`
|
||
- `src/open-canvas/components/artifact/CanvasArtifactVersionNav.tsx`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 当前 artifact 的统一入口组件结构
|
||
- 版本导航和正文渲染如何组合
|
||
- 文本/代码视图如何统一被包装
|
||
|
||
#### `apps/web/src/components/artifacts/TextRenderer.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 负责文本 artifact 的渲染与编辑
|
||
- 处理 markdown 内容、更新、局部交互
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/components/artifact/TextArtifactRenderer.tsx`
|
||
- `src/open-canvas/hooks/useCanvasSelection.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 文本 artifact 的编辑态与展示态切换
|
||
- 当前版本内容如何回写到状态
|
||
- 局部选区的挂接点
|
||
|
||
实现上的取舍建议:
|
||
|
||
- DeerFlow 首版不要追求和 open-canvas 一样复杂的富文本块级编辑
|
||
- 建议先用 `fullMarkdown` + markdown renderer + 简单编辑态完成闭环
|
||
|
||
#### `apps/web/src/components/artifacts/CodeRenderer.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 负责代码 artifact 的渲染与编辑
|
||
- 与 CodeMirror 集成
|
||
- 管理代码内容更新
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/components/artifact/CodeArtifactRenderer.tsx`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 代码 artifact 如何绑定语言
|
||
- 代码编辑结果如何同步回 artifact 状态
|
||
- 局部代码选区的接入位置
|
||
|
||
#### `apps/web/src/contexts/ThreadProvider.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 负责 thread 与模型相关状态
|
||
- 管理 thread 切换和 thread 级配置
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/contexts/CanvasThreadContext.tsx`
|
||
- `src/open-canvas/hooks/useCanvasThread.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 当前 thread id 的管理方式
|
||
- thread metadata 与 model state 的关系
|
||
- 页面恢复 thread 时的上下文同步
|
||
|
||
#### `apps/web/src/contexts/AssistantContext.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 管理 assistant 选择
|
||
- 管理与 assistant 相关的 thread 行为
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- DeerFlow 首版可以弱化这部分
|
||
- 如果首版只有 `canvas_agent` 一个固定 assistant,可只保留最小 assistant 绑定能力
|
||
|
||
重点借鉴内容:
|
||
|
||
- thread 与 assistant 的耦合方式
|
||
|
||
#### `apps/web/src/hooks/useRuns.tsx`
|
||
|
||
参考价值:
|
||
|
||
- 管理 run 相关行为
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/api/runs.ts`
|
||
- `src/open-canvas/hooks/useCanvasStream.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- run 行为与页面状态的解耦方式
|
||
|
||
#### `apps/web/src/types.ts`
|
||
|
||
参考价值:
|
||
|
||
- 保存了一部分 artifact 和消息类型定义
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/types/artifact.ts`
|
||
- `src/open-canvas/types/thread.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- artifact 的前端表达方式
|
||
|
||
注意:
|
||
|
||
- 更建议以 `packages/shared/src/types.ts` 为主参考,而不是这个文件
|
||
- 因为 `src/types.ts` 里同时包含了部分历史兼容结构
|
||
|
||
#### `packages/shared/src/types.ts`
|
||
|
||
参考价值:
|
||
|
||
- 这是 open-canvas 中最重要的共享类型来源之一
|
||
- 定义了 `ArtifactV3`、代码/文本内容、选择区和其他共享结构
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/types/artifact.ts`
|
||
- `src/open-canvas/types/selection.ts`
|
||
- 可作为前后端协议设计的主要参考
|
||
|
||
重点借鉴内容:
|
||
|
||
- `ArtifactV3` 结构
|
||
- 文本/代码 artifact 类型边界
|
||
- 与版本管理有关的字段组织方式
|
||
|
||
建议:
|
||
|
||
- DeerFlow 可以参考其字段设计
|
||
- 但不要机械复制所有字段,保留适合当前项目的最小集
|
||
|
||
#### `packages/shared/src/models.ts`
|
||
|
||
参考价值:
|
||
|
||
- 展示了 open-canvas 如何组织前端模型列表和模型能力
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/types/model.ts`
|
||
- `src/open-canvas/api/models.ts`
|
||
- `src/open-canvas/components/selectors/CanvasModelSelector.tsx`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 模型展示结构
|
||
- provider 概念
|
||
- 各模型能力标签的前端呈现思路
|
||
|
||
注意:
|
||
|
||
- 不应作为 DeerFlow 的模型配置真源
|
||
- DeerFlow 必须以自己后端 `/api/models` 为真源
|
||
|
||
#### `packages/shared/src/utils/artifacts.ts`
|
||
|
||
参考价值:
|
||
|
||
- 里面有 artifact 类型判断和内容获取工具
|
||
|
||
DeerFlow 对应落点:
|
||
|
||
- `src/open-canvas/utils/artifact.ts`
|
||
|
||
重点借鉴内容:
|
||
|
||
- 获取当前版本内容
|
||
- 判断当前 artifact 是文本还是代码
|
||
- 为渲染器和快捷动作提供统一入口
|
||
|
||
### 26.3 可以直接参考但不要直接迁移的部分
|
||
|
||
以下内容可以借鉴思路,但不建议直接搬代码:
|
||
|
||
- Next.js 路由和页面结构
|
||
- `src/app/api/*` 目录中的 API Route
|
||
- Supabase SSR 和服务端 session 相关代码
|
||
- `next/navigation` 相关逻辑
|
||
- `middleware.ts`
|
||
|
||
原因:
|
||
|
||
- DeerFlow 前端是 `React 19 + Vite + react-router-dom`
|
||
- 这些代码依赖 Next.js 运行时
|
||
|
||
### 26.4 建议的使用方式
|
||
|
||
开发时推荐这样使用参考源码:
|
||
|
||
1. 先按本文档实现 DeerFlow 自己的模块边界
|
||
2. 遇到某个具体功能点时,再去查对应 open-canvas 文件
|
||
3. 提炼实现思路,重写到 DeerFlow 的目录结构中
|
||
4. 不要复制包含 Next.js 运行时依赖的代码
|
||
|
||
### 26.5 推荐补充动作
|
||
|
||
如果后面要正式进入实现阶段,建议再单独新增一份源码映射文档,例如:
|
||
|
||
- `frontend-web/docs/openCanvas-source-map.md`
|
||
|
||
里面可以更细地记录:
|
||
|
||
- open-canvas 文件路径
|
||
- DeerFlow 对应目标文件
|
||
- 迁移策略
|
||
- 是否可直接借鉴
|
||
- 是否需要重写
|