--- title: "feat: AgentKit Platform Experience Upgrade" status: active created: 2026-06-13 plan-type: feat depth: deep origin: docs/brainstorms/2026-06-13-agentkit-platform-experience-upgrade-requirements.md --- # feat: AgentKit Platform Experience Upgrade ## Summary 对 Fischer AgentKit 进行平台级体验升级,四线并行推进:布局重构为左对话+右双栏、对话体验深化(首 Token 即渲染+消息格式增强+@-mention 四类引用)、响应速度核心优化、暗色主题与交互增强、Computer Use MVP——分三个冲击波迭代交付。 ## Problem Frame AgentKit 后端能力丰富(ReAct、Skill、Pipeline、记忆、自进化、多 Agent 市场),但 GUI 仍处于"功能可用但体验粗糙"状态。核心痛点:对话空间被压缩到 1/4 屏幕、消息纯文本无高亮、首 Token 延迟 5-10 秒、无暗色主题、无交互反馈、Computer Use 为占位。需求文档(见 origin)定义了 25 个需求(R1-R25),本计划定义如何实现。 --- ## Key Technical Decisions **KTD-1: 布局重构通过调整 SplitPane 嵌套实现,子视图零修改。** 当前 AgentLayout 使用三层 SplitPane(水平→左垂直+右垂直),重构为两层(水平→右垂直),ChatView 直接作为水平 SplitPane 的 first slot。QuadrantPanel 和 SplitPane 组件不变,只改 AgentLayout 的嵌套结构和路由映射。(see origin: R1) **KTD-2: 消息格式增强基于 MarkdownIt 插件扩展 + DOMPurify 白名单扩展。** 当前 ChatMessage 已使用 MarkdownIt 渲染,添加 `markdown-it-highlightjs` 插件实现代码高亮,自定义 `tool_call` 和 `file_preview` 块级渲染器实现工具调用卡片和文件预览。关键:当前 DOMPurify 的 `ALLOWED_TAGS` 白名单不包含 `div`、`img`、`button`,自定义渲染器输出的 HTML 元素会被过滤,必须扩展白名单。不引入新的 Markdown 渲染引擎。(see origin: R8, R9, R10) **KTD-3: @-mention 通过扩展 WebSocket 消息协议实现。** 在现有 `WsClientMessage` 的 `sources` 字段基础上扩展,引用项编码为 `{type: "mention", mention_type: "file"|"skill"|"workflow"|"agent", id: string, label: string}`,后端解析后注入 Agent 上下文。新增 `/api/v1/portal/mention-suggest` REST 端点提供 autocomplete 数据。(see origin: R13, R14) **KTD-4: Computer Use MVP 使用 pyautogui + screencapture 实现截屏和点击。** 替换 `DockerComputerUseSession` 的 stub 为 `LocalComputerUseSession`,macOS 使用 `screencapture` 截屏 + `pyautogui` 执行点击/输入操作,Linux 使用 `xdotool` + `scrot`。不依赖 Docker 容器化。前端新增 ComputerUseView 实际界面替代占位页。(see origin: R19, R20) **KTD-5: 暗色主题通过 `[data-theme="dark"]` CSS 选择器覆盖 + 响应式 Ant Design token。** 在现有 `tokens.css` 中添加 `[data-theme="dark"]` 块覆盖同名 CSS 变量,新增 `stores/theme.ts` 管理主题状态和 localStorage 持久化。关键:`styles/theme.ts` 的 `readToken()` 是模块加载时一次性执行的,切换主题后需重新调用生成新的 `themeConfig` 并传给 ConfigProvider,否则 Ant Design 组件不跟随暗色主题。(see origin: R11) **KTD-6: 响应速度优化 U1-U4 已实现,仅补充 portal.py 的 ReActEngine 复用。** `HeuristicClassifier`、`_classify_merged`、`parallel_tools`、`AsyncWriteQueue` 均已在代码中。`chat.py` 已有 ReActEngine 复用逻辑,但 `portal.py` 每次创建新实例,需对齐。(see origin: R5, R6, R7) --- ## High-Level Technical Design ### 迭代 1 架构:对话体验质变 ```mermaid flowchart TB subgraph Frontend AL[AgentLayout] --> SP_H[SplitPane horizontal 55:45] SP_H --> CV[ChatView 全高] SP_H --> SP_V[SplitPane vertical 60:40] SP_V --> QP_TR[QuadrantPanel 右上] SP_V --> QP_BR[QuadrantPanel 右下] CV --> CI[ChatInput] CV --> CM[ChatMessage] CM --> MD[MarkdownIt + highlightjs] CM --> TC[ToolCallCard 渲染器] CM --> FP[FilePreview 渲染器] CI --> WS[WebSocket] end subgraph Backend WS --> PORTAL[portal.py] PORTAL --> HC[HeuristicClassifier 已实现] PORTAL --> MERGE[_classify_merged 已实现] PORTAL --> RE[ReActEngine 复用] RE --> STREAM[execute_stream] STREAM --> |token 事件| WS end ``` ### @-mention 数据流(迭代 2) ```mermaid sequenceDiagram participant U as User participant CI as ChatInput participant API as /mention-suggest participant WS as WebSocket participant PORTAL as portal.py participant AGENT as Agent U->>CI: 输入 @ CI->>API: GET /mention-suggest?q=keyword API-->>CI: [{type, id, label, icon}] U->>CI: 选择引用项 CI->>CI: 添加 ContextPill U->>CI: 发送消息 CI->>WS: {type:chat, message, mentions:[...]} WS->>PORTAL: 解析 mentions PORTAL->>PORTAL: 查询引用内容 PORTAL->>AGENT: 注入上下文 AGENT-->>WS: 流式响应 WS-->>CI: 渲染响应 ``` --- ## Requirements Traceability | Requirement | Iteration | Implementation Unit(s) | |-------------|-----------|----------------------| | R1. 左对话+右双栏 | 1 | U1 | | R2. 面板折叠 | 1 | U1 | | R3. 侧边导航图标 | 1 | U2 | | R4. 小屏幕适配 | 1 | U1 | | R5. 启发式分类器 | 1 | 已实现 | | R6. 合并路由调用 | 1 | 已实现 | | R7. 首 Token 即渲染 | 1 | U3 | | R8. 代码块高亮 | 1 | U4 | | R9. 工具调用可视化 | 1 | U5 | | R10. 图片/文件预览 | 1 | U6 | | R11. 暗色主题 | 2 | U7 | | R12. 组件样式统一 | 2 | U8 | | R13. @-mention Autocomplete | 2 | U9 | | R14. @-mention 上下文注入 | 2 | U10 | | R15. @-mention 引用标签 | 2 | U9 | | R16. 过渡动画 | 2 | U11 | | R17. 操作反馈 | 2 | U12 | | R18. 空状态设计 | 2 | U13 | | R19. 截屏查看 | 3 | U14 | | R20. 简单点击操作 | 3 | U14 | | R21. Computer Use 面板 | 3 | U15 | | R22. 并行工具执行 | 3 | 已实现 | | R23. 异步会话写入 | 3 | 已实现 | | R24. 分割线拖拽增强 | 3 | U16 | | R25. 面板折叠缩略预览 | 3 | U17 | --- ## Implementation Units ### 迭代 1:对话体验质变 --- ### U1. AgentLayout 布局重构 **Goal:** 将四象限等分布局重构为左对话+右双栏布局,对话面板占满左半屏。 **Requirements:** R1, R2, R4 **Dependencies:** None **Files:** - `src/agentkit/server/frontend/src/components/layout/AgentLayout.vue` — 重构 SplitPane 嵌套 - `src/agentkit/server/frontend/src/router/index.ts` — 移除 terminal 路由,调整 quadrant 元数据 - `src/agentkit/server/frontend/src/styles/responsive.css` — 调整断点 **Approach:** 1. 移除左侧垂直 SplitPane,ChatView 直接作为水平 SplitPane 的 `#first` slot 2. 保留右侧垂直 SplitPane(右上:代码/工作流/知识库,右下:监控/技能/设置) 3. 水平 SplitPane 默认比例改为 0.55(55:45) 4. 移除 `agent-terminal` 路由定义 5. 调整 responsive.css:≥1280px 完整展示,1024-1280px 右下面板默认折叠,<1024px 提示。**注意:** 当前 responsive.css 的选择器基于四象限布局结构(如 `.split-pane--horizontal > .split-pane__second .split-pane--vertical > .split-pane__second .quadrant-panel`),重构后这些选择器完全失效,必须根据新的两层 SplitPane 结构重写所有象限相关选择器 **Patterns to follow:** 现有 SplitPane 嵌套模式;QuadrantPanel 的 Tab 配置模式;localStorage 持久化 key 命名 `agent-*` **Test scenarios:** - 布局渲染为左对话+右双栏,ChatView 占满左半屏高度 - 左右分割线可拖拽,默认 55:45,范围 20%-80% - 右侧上下分割线可拖拽,默认 60:40 - 分割比例保存到 localStorage,刷新后恢复 - 右上面板折叠后仅显示 Tab 栏(约 38px) - 右下面板折叠后仅显示 Tab 栏 - 两个面板可同时折叠 - 折叠/展开有 200ms ease 过渡动画 - 屏幕宽度 <1024px 显示提示 - 屏幕宽度 1024-1280px 右下面板默认折叠 - terminal 路由不再存在 **Verification:** 手动测试布局在不同屏幕宽度下的表现;折叠/展开动画流畅;localStorage 持久化正常。 --- ### U2. 侧边导航精简为图标模式 **Goal:** 将侧边导航精简为 32px 宽图标导航栏,点击图标切换右侧面板 Tab 并展开。 **Requirements:** R3 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/components/layout/TopNav.vue` — 添加侧边导航切换按钮 - `src/agentkit/server/frontend/src/components/layout/IconNav.vue` — 新建 32px 图标导航组件 - `src/agentkit/server/frontend/src/components/layout/AgentLayout.vue` — 集成 IconNav **Approach:** 1. 新建 `IconNav.vue`:32px 宽图标导航栏,只显示图标(对话、工作流、知识库、技能、监控、设置)。注意:现有 `SideNav.vue` 是遗留的 AppLayout 组件(240px 宽暗色侧边栏),不在 AgentLayout 中使用,不需要修改。 2. 点击图标:调用对应 QuadrantPanel 的 `setActiveTab()` 并展开面板 3. 当前激活图标高亮(使用 `--color-primary` Token) 4. TopNav 添加折叠/展开 SideNav 的按钮 5. SideNav 状态保存到 localStorage **Patterns to follow:** QuadrantPanel 的 `setActiveTab()` 暴露方法;现有 SideNav 的导航项定义模式 **Test scenarios:** - SideNav 宽度为 32px,只显示图标 - 点击对话图标,ChatView 获得焦点 - 点击工作流图标,右上面板切换到 workflow Tab 并展开 - 点击监控图标,右下面板切换到 monitor Tab 并展开 - 当前激活图标高亮 - TopNav 按钮可折叠/展开 SideNav - 折叠状态保存到 localStorage **Verification:** 手动测试图标导航与面板联动;折叠/展开正常。 --- ### U3. 首步骤即渲染 + portal.py ReActEngine 复用 **Goal:** 前端接收到首个流式步骤即开始渲染;后端 portal.py 复用 ReActEngine 实例。 **Requirements:** R7 **Dependencies:** None **Files:** - `src/agentkit/server/frontend/src/stores/chat.ts` — 确认流式渲染逻辑正确处理首个步骤 - `src/agentkit/server/frontend/src/components/chat/ChatMessage.vue` — 确认流式内容渲染无闪烁 - `src/agentkit/server/routes/portal.py` — ReActEngine 复用(对齐 chat.py 模式,覆盖 SSE + WS 两个路径) **Approach:** 1. 前端:当前 `handleWsMessage` 的 `step` 事件在 `event_type === 'final_answer'` 时逐块累加 content,确认首个步骤到达即渲染。注意:后端当前按"步骤"粒度推送(thinking/tool_call/tool_result/final_answer),不是逐 Token 推送。"首 Token 即渲染"在此架构下实际含义是"首步骤即渲染"——`final_answer` 事件的 `data.output` 是文本块,到达即显示。 2. 后端:portal.py 有两处创建 ReActEngine(SSE 路径约第 342 行,WS 路径约第 661 行),均需改为复用 agent 上已绑定的 `_react_engine`(对齐 chat.py 第 197 行的 `getattr(agent, "_react_engine", None)` 模式)。复用时调用 `react_engine.reset()` 重置内部状态。 3. 注意 `agent_pool.py` 的 `create_agent_from_skill()` 已在 agent 上绑定 `agent._react_engine`,portal.py 应优先使用该实例。 **Patterns to follow:** chat.py 的 `getattr(agent, "_react_engine", None)` 复用模式 **Test scenarios:** - 发送简单问候,首 Token 在 1 秒内渲染 - 流式输出逐字显示,无整体延迟 - ReActEngine 在同一会话中复用,不创建新实例 - 会话结束后 ReActEngine 正确重置 - token 事件和 final_answer 事件均触发前端渲染更新 **Verification:** 手动测试对话首 Token 延迟;检查 portal.py 日志确认 ReActEngine 复用。 --- ### U4. 代码块语法高亮 **Goal:** 消息中的代码块自动识别语言并语法高亮,支持复制按钮。 **Requirements:** R8 **Dependencies:** None **Files:** - `src/agentkit/server/frontend/src/components/chat/ChatMessage.vue` — 添加 highlight.js 插件 + 扩展 DOMPurify 白名单 - `src/agentkit/server/frontend/src/styles/` — 代码高亮主题样式 - `src/agentkit/server/frontend/package.json` — 添加 `highlight.js` 依赖 **Approach:** 1. 安装 `highlight.js` 和 `markdown-it-highlightjs`(或手动配置 MarkdownIt 的 highlight 选项) 2. 在 ChatMessage 的 MarkdownIt 实例中配置 highlight 函数使用 highlight.js 3. 代码高亮主题使用 Catppuccin Mocha(与 tokens.css 中的代码主题一致) 4. 添加代码块复制按钮(点击复制代码内容到剪贴板,显示 Toast 反馈) 5. 代码块语言标签显示在右上角 6. **扩展 DOMPurify 白名单**:当前 `ALLOWED_TAGS` 不包含 `code`、`pre`、`span`(highlight.js 生成的标签),需添加这些标签及 `class`、`data-language` 属性 **Patterns to follow:** 现有 MarkdownIt 配置模式;tokens.css 中的代码主题色(`--color-code-*`) **Test scenarios:** - Python 代码块正确高亮(关键字、字符串、注释、函数名) - JavaScript 代码块正确高亮 - 未指定语言的代码块使用自动检测 - 复制按钮点击后内容复制到剪贴板,显示 Toast - 代码块语言标签正确显示 - 流式输出时代码块逐步高亮(不闪烁) **Verification:** 手动测试不同语言代码块的渲染效果。 --- ### U5. 工具调用可视化 **Goal:** 工具调用显示为可折叠的步骤卡片,展示工具名称、参数摘要、执行状态、结果预览。 **Requirements:** R9 **Dependencies:** U3 **Files:** - `src/agentkit/server/frontend/src/components/chat/ChatMessage.vue` — 添加工具调用渲染逻辑 + 扩展 DOMPurify 白名单 - `src/agentkit/server/frontend/src/components/chat/ToolCallCard.vue` — 新建工具调用卡片组件 **Approach:** 1. 创建 `ToolCallCard.vue` 组件:可折叠卡片,显示工具名称(图标+名称)、参数摘要(截断显示)、执行状态(pending/running/completed/error)、结果预览(折叠时显示前 2 行) 2. 在 ChatMessage 中,检测 `step` 事件中的 `tool_call` 和 `tool_result` 事件类型,将配对的工具调用渲染为 ToolCallCard 3. 利用 chat store 中 `streamingSteps` 的数据,匹配工具调用和结果 4. 折叠/展开动画使用现有 `transitions.css` 的 `collapse` 类 5. **扩展 DOMPurify 白名单**:添加 `div`、`button`、`data-tool-call`、`data-tool-result` 等标签和属性,确保 ToolCallCard 的 HTML 不被过滤 **Patterns to follow:** 现有 `streamingSteps` 数据结构;transitions.css 的 collapse 动画;QuadrantPanel 的折叠模式 **Test scenarios:** - 工具调用显示为卡片,包含工具名称和参数摘要 - 执行中状态显示 loading 指示器 - 完成后显示结果预览(前 2 行) - 点击卡片展开查看完整参数和结果 - 多个工具调用按顺序显示 - 折叠/展开有平滑过渡动画 - 错误状态的工具调用显示错误信息 **Verification:** 手动测试触发工具调用的对话,验证卡片渲染和交互。 --- ### U6. 图片和文件预览 **Goal:** 消息中的图片内联显示缩略图,文件显示为可下载卡片。 **Requirements:** R10 **Dependencies:** U4 **Files:** - `src/agentkit/server/frontend/src/components/chat/ChatMessage.vue` — 添加图片/文件渲染逻辑 + 扩展 DOMPurify 白名单 - `src/agentkit/server/frontend/src/components/chat/FilePreview.vue` — 新建文件预览卡片组件 **Approach:** 1. 创建 `FilePreview.vue` 组件:文件名+大小+类型图标+下载按钮 2. 在 ChatMessage 的 MarkdownIt 渲染中,自定义 `image` 渲染规则:内联缩略图,点击放大 3. 检测消息中的文件链接(URL 以常见文件扩展名结尾),渲染为 FilePreview 卡片 4. 图片缩略图使用 CSS `object-fit: contain`,最大高度 200px 5. **扩展 DOMPurify 白名单**:添加 `img` 标签及 `src`、`alt`、`loading` 属性 **Patterns to follow:** 现有 MarkdownIt 自定义渲染器模式;tokens.css 的间距和圆角 Token **Test scenarios:** - 消息中的图片 URL 显示为内联缩略图 - 点击缩略图放大查看 - 文件链接显示为卡片(文件名+大小+类型图标) - 下载按钮点击触发文件下载 - 非图片/文件链接正常渲染为超链接 **Verification:** 手动测试包含图片和文件链接的消息渲染。 --- ### 迭代 2:专业感 + 精准度 --- ### U7. 暗色主题 Token 定义与切换 **Goal:** 在浅色 Token 基础上新增暗色主题 Token 变体,支持一键切换。 **Requirements:** R11 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/styles/tokens.css` — 添加 `[data-theme="dark"]` 块 - `src/agentkit/server/frontend/src/stores/theme.ts` — 新建主题 store - `src/agentkit/server/frontend/src/styles/theme.ts` — 改造 `readToken()` 为可重复调用的函数,支持主题切换时重新生成 `themeConfig` - `src/agentkit/server/frontend/src/components/layout/TopNav.vue` — 添加主题切换按钮 - `src/agentkit/server/frontend/src/App.vue` — 监听主题变化,更新 `data-theme` 属性和 ConfigProvider **Approach:** 1. 在 tokens.css 末尾添加 `[data-theme="dark"]` 选择器块,覆盖所有颜色变量(背景、前景、边框、品牌色、语义色、代码主题色) 2. 暗色配色方案:深色背景 `#1a1a2e` 系列、荧光强调色、终端原生感 3. 创建 `stores/theme.ts`:`currentTheme` ref('light'|'dark'),`toggleTheme()` 方法,localStorage 持久化 4. **改造 `styles/theme.ts`**:当前 `readToken()` 在模块加载时一次性执行,生成静态 `themeConfig`。切换暗色主题后 CSS 变量值变了,但 `themeConfig` 不会重新计算。需将 `themeConfig` 改为响应式:导出 `getThemeConfig()` 函数,App.vue 监听 `currentTheme` 变化时重新调用生成新 config 并传给 ConfigProvider 5. App.vue 监听 `currentTheme` 变化,更新 `document.documentElement.dataset.theme` 和 ConfigProvider 的 `theme` prop 6. TopNav 添加太阳/月亮图标切换按钮 **Patterns to follow:** 现有 tokens.css 的变量命名模式;theme.ts 的 `readToken()` 运行时映射 **Test scenarios:** - 点击切换按钮,界面从浅色切换到暗色 - 所有组件在暗色主题下正常显示(文字可读、对比度足够) - 代码块在暗色主题下使用 Catppuccin Mocha 配色 - 主题偏好保存到 localStorage,刷新后恢复 - 切换过渡平滑(CSS transition on color variables) **Verification:** 手动测试暗色主题下所有页面的显示效果。 --- ### U8. 组件样式统一 **Goal:** 所有组件统一引用 Design Token,消除硬编码值。 **Requirements:** R12 **Dependencies:** U7 **Files:** - `src/agentkit/server/frontend/src/components/layout/SideNav.vue` — 替换硬编码颜色 - `src/agentkit/server/frontend/src/App.vue` — 替换 `!important` 全局覆盖为 Token 驱动 - 各组件 scoped 样式中的硬编码值逐一替换 **Approach:** 1. 全局搜索 `rgba(`、`#` 开头的硬编码颜色值(排除 tokens.css 本身) 2. 逐一替换为对应的 CSS 变量引用 3. App.vue 中的 Ant Design 全局覆盖从 `!important` 改为通过 ConfigProvider token 注入 4. 确保暗色主题下替换后的变量值正确 **Patterns to follow:** tokens.css 的变量命名;theme.ts 的 readToken() 映射 **Test scenarios:** - 零硬编码颜色值(tokens.css 除外) - 浅色和暗色主题下所有组件样式一致 - Ant Design 组件通过 ConfigProvider token 驱动样式 - 无 `!important` 覆盖(特殊情况除外) **Verification:** 代码搜索确认无硬编码颜色值;双主题视觉验证。 --- ### U9. @-mention Autocomplete 前端 **Goal:** 对话输入框中输入 `@` 触发下拉选择器,支持四类引用,选中后显示为 ContextPill。 **Requirements:** R13, R15 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/components/chat/ChatInput.vue` — 添加 @-mention 触发和选择逻辑 - `src/agentkit/server/frontend/src/components/chat/MentionDropdown.vue` — 新建下拉选择器组件 - `src/agentkit/server/frontend/src/api/client.ts` — 添加 mention-suggest API 调用 - `src/agentkit/server/frontend/src/api/types.ts` — 添加 MentionItem 类型定义 + 扩展 WsClientMessage 添加 `mentions` 字段 **Approach:** 1. 定义 `MentionItem` 类型:`{type: 'file'|'skill'|'workflow'|'agent', id: string, label: string, icon?: string, description?: string}` 2. ChatInput 监听输入,检测 `@` 字符触发 MentionDropdown 3. MentionDropdown 调用 `/api/v1/portal/mention-suggest?q=keyword` 获取建议列表 4. 选中后生成 ContextPill 添加到 `contextPills` 数组(复用现有 ContextPillData 接口,扩展 type/id 字段) 5. 发送消息时,将 mentions 数组附加到 WebSocket 消息 6. **R15 覆盖**:ChatMessage 渲染时检测消息的 mentions 元数据,将 @引用渲染为可点击的标签/链接(点击跳转到对应面板或打开详情) **⚠ 前后端协议耦合**:U9 和 U10 必须在同一迭代内同步交付,否则 WebSocket 协议不兼容。 **Patterns to follow:** 现有 ContextPill 数据结构;Ant Design Vue 的 AutoComplete/Select 组件模式 **Test scenarios:** - 输入 `@` 触发下拉选择器 - 输入 `@文件名` 过滤显示匹配的知识库文档 - 输入 `@技能名` 过滤显示匹配的技能 - 输入 `@工作流名` 过滤显示匹配的工作流 - 输入 `@Agent名` 过滤显示匹配的 Agent - 选中引用项后显示为 ContextPill - ContextPill 可点击删除 - 发送消息时 mentions 数组正确附加 **Verification:** 手动测试四类 @-mention 的 autocomplete 和选择流程。 --- ### U10. @-mention 后端上下文注入 **Goal:** 后端解析 @-mention 引用,将对应内容注入 Agent 推理上下文。 **Requirements:** R14 **Dependencies:** U9 **Files:** - `src/agentkit/server/routes/portal.py` — 解析 mentions,注入上下文 - `src/agentkit/server/routes/portal.py` — 新增 `/portal/mention-suggest` 端点 **Approach:** 1. 新增 `GET /api/v1/portal/mention-suggest?q=keyword` 端点,聚合查询知识库文档、技能、工作流、Agent,返回 `MentionItem[]` 2. WebSocket 消息中解析 `mentions` 字段 3. 根据 mention_type 和 id 查询对应内容: - `file` → 从 KnowledgeBase 检索文档片段 - `skill` → 从 SkillRegistry 获取技能描述和工具定义 - `workflow` → 从 WorkflowStore 获取工作流定义 - `agent` → 从 AgentPool 获取 Agent 配置 4. 将引用内容作为结构化上下文注入 system_prompt 或 messages **Patterns to follow:** 现有 portal.py 的路由和 CostAwareRouter 模式;各 Registry 的查询 API **Test scenarios:** - `/mention-suggest?q=test` 返回匹配的文件、技能、工作流、Agent - @文件引用后,Agent 回复中引用了文档内容 - @技能引用后,Agent 使用了指定技能 - @工作流引用后,Agent 了解工作流定义 - @Agent 引用后,Agent 了解目标 Agent 的能力 - 多个 @-mention 同时使用,所有引用内容均注入 - 无效引用(ID 不存在)优雅降级,不阻塞对话 **Verification:** 手动测试各类 @-mention 的上下文注入效果。 --- ### U11. 过渡动画 **Goal:** 为所有交互添加过渡动画。 **Requirements:** R16 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/styles/transitions.css` — 确认/补充动画类 - `src/agentkit/server/frontend/src/components/layout/QuadrantPanel.vue` — Tab 切换淡入淡出 - `src/agentkit/server/frontend/src/components/layout/AgentLayout.vue` — 路由切换动画 - 各列表渲染组件 — 交错渐入 **Approach:** 1. 确认 transitions.css 中已有 fade、collapse、scale、stagger-list 类 2. QuadrantPanel Tab 切换添加 `` 包裹 3. AgentLayout 路由切换添加 `` 4. 列表项使用 `` 5. 所有时长引用 Design Token:`--transition-fast: 150ms`、`--transition-normal: 200ms` **Patterns to follow:** 现有 transitions.css 的动画类定义模式 **Test scenarios:** - 面板折叠/展开有 200ms ease 过渡 - Tab 切换有 150ms 淡入淡出 - 列表项交错渐入(stagger 50ms) - 路由切换有 200ms 淡入淡出 - 动画不阻塞交互(使用 CSS transition 而非 JS 动画) **Verification:** 手动测试各交互动画效果。 --- ### U12. 操作反馈 **Goal:** 为用户操作提供即时反馈。 **Requirements:** R17 **Dependencies:** U7 **Files:** - `src/agentkit/server/frontend/src/components/common/ToastService.ts` — 新建 Toast 服务 - `src/agentkit/server/frontend/src/components/chat/ChatInput.vue` — 按钮点击反馈 - `src/agentkit/server/frontend/src/components/layout/TopNav.vue` — WebSocket 断连横幅 - 各加载状态组件 — 骨架屏替代 a-spin **Approach:** 1. 创建 ToastService:基于 Ant Design Vue 的 `message` 组件,封装 success/error/warning/info 方法 2. 按钮点击添加 `:active` 缩放反馈(CSS `transform: scale(0.97)`) 3. 加载状态:关键区域使用骨架屏(复用 transitions.css 的 `skeleton-pulse` 动画) 4. WebSocket 断连:TopNav 下方显示红色横幅提示,重连后自动消失 **Patterns to follow:** Ant Design Vue message 组件;transitions.css 的 skeleton-pulse 动画 **Test scenarios:** - 操作成功显示绿色 Toast - 操作失败显示红色 Toast - 按钮点击有缩放反馈 - 加载状态显示骨架屏而非 Spin - WebSocket 断连时顶部显示红色横幅 - 重连后横幅自动消失 **Verification:** 手动测试各类操作反馈。 --- ### U13. 空状态设计 **Goal:** 为所有空状态提供品牌化插图和引导文案。 **Requirements:** R18 **Dependencies:** U7 **Files:** - `src/agentkit/server/frontend/src/components/common/EmptyState.vue` — 新建空状态组件 - `src/agentkit/server/frontend/src/views/ChatView.vue` — 对话空状态 - `src/agentkit/server/frontend/src/views/WorkflowView.vue` — 工作流空状态 - `src/agentkit/server/frontend/src/views/EvolutionView.vue` — 监控空状态 - `src/agentkit/server/frontend/src/views/KnowledgeBaseView.vue` — 知识库空状态 - `src/agentkit/server/frontend/src/views/SkillsView.vue` — 技能空状态 **Approach:** 1. 创建 EmptyState.vue 通用组件:接受 `title`、`description`、`icon`、`action` props 2. 各视图在数据为空时渲染 EmptyState,提供引导文案和操作按钮 3. 图标使用 Ant Design Vue 的内置图标,配合品牌色 **Patterns to follow:** Ant Design Vue 的 `a-empty` 组件模式 **Test scenarios:** - 对话空状态显示"开始你的第一次对话"引导 - 工作流空状态显示"创建第一个工作流"引导 - 监控空状态显示数据来源说明 - 知识库空状态显示"上传文档或配置信息源"引导 - 技能空状态显示"注册技能"引导 - 空状态组件在暗色主题下正常显示 **Verification:** 手动测试各视图的空状态显示。 --- ### 迭代 3:能力扩展 --- ### U14. Computer Use MVP 后端(pyautogui + screencapture) **Goal:** 实现本地截屏和点击操作的后端闭环。 **Requirements:** R19, R20 **Dependencies:** None **Files:** - `src/agentkit/tools/computer_use_session.py` — 新增 `LocalComputerUseSession` 类 - `src/agentkit/tools/computer_use.py` — 确保工具注册和降级链正确 **Approach:** 1. 创建 `LocalComputerUseSession` 类,实现 `start()`、`stop()`、`screenshot()`、`execute_action()` 方法 2. `screenshot()` 实现:macOS 使用 `screencapture -x -t png ` 命令截屏,读取文件返回 base64;Linux 使用 `scrot` 或 `xdg-screenshot` 3. `execute_action()` 实现:使用 `pyautogui` 库执行点击(`pyautogui.click(x, y)`)、输入(`pyautogui.typewrite()`)、滚动等操作 4. 注册到 `ComputerUseSessionManager`,作为默认会话类型(替代 Docker stub) 5. 确保降级链正确:Anthropic API → LocalComputerUseSession → Shell 替代建议 6. 添加 `pyautogui` 到项目依赖(`pyproject.toml`) **Patterns to follow:** 现有 `InMemoryComputerUseSession` 的接口模式;ToolRegistry 注册模式 **Test scenarios:** - OpenCLI 会话创建和销毁正常 - 截屏返回有效的 base64 PNG 数据 - 点击操作执行并返回结果 - ComputerUseTool 的降级链正确工作 - 会话管理器正确管理 OpenCLI 会话生命周期 **Verification:** 手动测试通过对话触发截屏和点击操作。 --- ### U15. Computer Use 前端面板 **Goal:** 右上面板新增 Computer Use Tab,展示截屏画面和操作历史。 **Requirements:** R21 **Dependencies:** U14 **Files:** - `src/agentkit/server/frontend/src/views/ComputerUseView.vue` — 替换占位页为实际界面 - `src/agentkit/server/frontend/src/components/layout/AgentLayout.vue` — 右上面板添加 Computer Use Tab - `src/agentkit/server/frontend/src/router/index.ts` — 添加 Computer Use 路由 **Approach:** 1. 重写 ComputerUseView.vue:截屏画面显示区域(支持缩放和滚动)、操作历史列表、手动截屏按钮 2. 截屏画面通过 WebSocket 接收 base64 图片数据,渲染为 `` 标签 3. 操作历史显示时间戳、操作类型、坐标/参数、结果摘要 4. 手动截屏按钮触发后端截屏命令 5. 右上面板 QuadrantPanel 添加 Computer Use Tab **Patterns to follow:** 现有 QuadrantPanel Tab 配置模式;WebSocket 消息处理模式 **Test scenarios:** - Computer Use Tab 在右上面板显示 - 截屏画面正确渲染 - 截屏画面支持缩放和滚动 - 操作历史按时间倒序显示 - 手动截屏按钮触发截屏 - 暗色主题下正常显示 **Verification:** 手动测试 Computer Use 面板的截屏显示和操作历史。 --- ### U16. 分割线拖拽增强 **Goal:** 拖拽分割线时高亮显示,显示当前比例百分比。 **Requirements:** R24 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/components/layout/SplitPane.vue` — 添加拖拽高亮和比例显示 **Approach:** 1. 拖拽时 handle 元素添加高亮样式(加宽 + 品牌色背景) 2. 拖拽时显示比例百分比标签(如 "55%"),定位在 handle 旁边 3. 使用 CSS transition 确保高亮和标签的显示/隐藏平滑 **Patterns to follow:** 现有 SplitPane 的拖拽逻辑和 handle 样式 **Test scenarios:** - 拖拽时分割线高亮 - 拖拽时显示当前比例百分比 - 百分比标签定位正确不遮挡内容 - 拖拽结束后高亮和标签消失 **Verification:** 手动测试拖拽交互。 --- ### U17. 面板折叠缩略预览 **Goal:** 面板折叠时显示缩略内容预览。 **Requirements:** R25 **Dependencies:** U1 **Files:** - `src/agentkit/server/frontend/src/components/layout/QuadrantPanel.vue` — 折叠时显示缩略预览 **Approach:** 1. 折叠状态下,在 Tab 栏下方显示约 60px 高的缩略预览区域 2. 预览内容根据当前活跃 Tab 类型显示:监控显示关键指标数字、技能显示技能数量、工作流显示节点缩略图 3. 预览区域使用半透明背景,不占用过多空间 **Patterns to follow:** QuadrantPanel 的折叠模式;Design Token 的间距和圆角 **Test scenarios:** - 右上面板折叠后显示缩略预览 - 右下面板折叠后显示缩略预览 - 预览内容根据活跃 Tab 更新 - 预览区域不遮挡 Tab 栏 - 暗色主题下预览区域正常显示 **Verification:** 手动测试折叠预览效果。 --- ## Scope Boundaries **在范围内:** 见需求文档的 Scope Boundaries。 **延迟到后续迭代:** - Cmd+K 内联编辑 - Computer Use Docker 容器化隔离 - 代码 Diff 查看器实现 - 代码 Diff Accept/Reject 回滚 - 响应式移动端适配 - httpx 连接池配置优化(U5 已实现,无需额外工作) - A/B 测试框架和性能基准 CI - Ant Design Vue 按需引入(unplugin-vue-components) - ECharts 按需引入 **不在本产品身份内:** - 多用户协作/实时协同编辑 - 插件市场 - 代码编辑器 --- ## Risks & Mitigations | Risk | Likelihood | Impact | Mitigation | |------|-----------|--------|------------| | @-mention 后端查询聚合性能差 | Medium | Medium — 慢速 autocomplete 影响体验 | mention-suggest 端点添加缓存(TTL 30s),结果集限制 20 条 | | 本地截屏兼容性问题 | Medium | High — 不同 OS 环境截屏命令不同 | 检测 OS 类型选择对应命令,添加 fallback 到 InMemory 模式 | | 暗色主题对比度不足 | Low | Medium — 部分组件在暗色下不可读 | 使用 WCAG AA 标准验证对比度,添加自动化对比度检查 | | 消息格式增强破坏现有渲染 | Low | High — 已有消息显示异常 | MarkdownIt 插件添加 fallback,解析失败时回退到纯文本;DOMPurify 白名单扩展需谨慎测试 | | 布局重构影响现有路由和状态 | Medium | Medium — localStorage 旧 key 导致异常 | 添加 key 版本化,旧 key 自动迁移或清理 | | DOMPurify 白名单扩展引入 XSS | Low | High — 恶意内容可能注入 | 仅添加必要的标签和属性,不开放 `on*` 事件属性,`img` 的 `src` 限制为相对路径和已知域名 | | Ant Design token 不跟随暗色切换 | Medium | Medium — 组件颜色不一致 | 改造 theme.ts 为响应式,切换时重新生成 themeConfig | | 与 001 计划的 U-unit 重叠 | High | High — 并行执行产生合并冲突 | 003 吸收 001 的重叠 U-unit,001 标注为"由 003 覆盖",不并行执行 | --- ## System-Wide Impact - **前端布局:** AgentLayout 从三层 SplitPane 改为两层,所有依赖象限位置的路由和状态需调整 - **前端样式:** 暗色主题影响所有组件,需全面测试 - **WebSocket 协议:** @-mention 扩展了 `WsClientMessage` 的 `mentions` 字段,需前后端同步升级 - **后端路由:** 新增 `/portal/mention-suggest` 端点,portal.py 需解析 mentions - **工具系统:** 新增 OpenCLIComputerUseSession,ComputerUseTool 降级链调整 - **响应速度:** portal.py 的 ReActEngine 复用减少实例创建开销 --- ## Outstanding Questions **Deferred to Implementation:** - @-mention 后端解析的具体协议细节:mentions 字段在 WebSocket 消息中的 JSON 结构 - 工具调用步骤卡片的折叠/展开交互细节:默认折叠还是展开 - 骨架屏的具体形状和占位内容 - 暗色主题的具体色值需要视觉调优 - R22/R23 对 portal.py 路径无效的决策:portal.py 使用自己的 ConversationStore(内存 dict),不使用 SessionManager,异步写入和并行工具执行对 portal 路径无影响。是否需要迁移 portal.py 到 SessionManager? **Plan Relationship:** - 本计划(003)吸收了 001 计划(GUI 产品化)的所有重叠 U-unit(布局重构、暗色主题、交互增强),001 计划应标注为"由 003 覆盖",避免并行执行产生合并冲突 --- ## Sources & Research - 需求文档:`docs/brainstorms/2026-06-13-agentkit-platform-experience-upgrade-requirements.md` - 响应速度优化计划(U1-U4 已实现):`docs/plans/2026-06-12-021-feat-chat-response-speed-optimization-plan.md` - GUI 产品化计划(前一轮):`docs/plans/2026-06-13-001-feat-gui-productization-plan.md` - 前端产品化计划:`docs/plans/2026-06-12-023-feat-frontend-productization-plan.md` - 现有 Design Token 体系:`src/agentkit/server/frontend/src/styles/tokens.css` - 现有 WebSocket 协议:`src/agentkit/server/frontend/src/api/types.ts` - 现有 Computer Use 工具:`src/agentkit/tools/computer_use.py`、`src/agentkit/tools/computer_use_session.py`