agent-Specialization/doc/frontend/legacy_ui_spec.md

20 KiB
Raw Blame History

Legacy UI 规格说明static/old_version_backup/前端备份)

目的:彻底记录旧版前端(static/old_version_backup/前端备份/index.html + app.js + style.css)的 UI 结构、状态域、交互与 API用于后续 Phase 3+ 全量重构时精准还原体验。下文所有字段/方法名称均沿用备份代码,方便对照实现。

全局运行环境

  • 依赖加载:直接在 index.html 通过 CDN/本地脚本注入 Vue 3Vue.createApp、Socket.IO 客户端、Marked、Prism、KaTeX以及 /static/security.js 与彩蛋脚本 (/static/easter-eggs/*.js)。window.requestSocketTokenwindow.ensureCsrfToken 来自后端脚本。
  • 样式体系:单一 style.css 使用大量 CSS 变量(--claude-*打造“Claude 风”视觉;含左/右侧边栏、对话区、输入区、Toast、面板等所有样式。另挂载彩蛋专用 CSSflood.css/snake.css)。
  • 入口 DOM:整个应用被包裹在 <div id="app"> 中,通过 Vue 模板语法渲染;根节点同时承载 Toast/Confirm/Overlay/ContextMenu。
  • 脚手架行为:页面加载时会执行 bootstrapApp() → 确保 Vue/Socket.IO 存在 → createApp,并在 window.load 后挂载。Viewport 逻辑通过 updateViewportHeightVar 挂在 window.visualViewport 事件CSS 使用 --app-viewport 控制高度。

状态域(app.jsdata()

状态分组 关键字段 说明/用途 建议 Pinia Store
连接 & 系统 isConnected, socket, projectPath, agentVersion, thinkingMode, stopRequested 管理 Socket.IO 生命周期、后端模式、思考/快速切换、Stop 指令等 useConnectionStore / useSystemStore
对话 & 消息 messages, currentConversationId, currentConversationTitle, currentMessageIndex, streamingMessage, expandedBlocks, thinkingScrollLocks, autoScrollEnabled, userScrolling 聊天历史、流式状态、思考块折叠、滚动锁、当前对话元信息 useConversationStore + useChatStore
面板布局 sidebarCollapsed, leftWidth, rightWidth, rightCollapsed, isResizing, resizingPanel, panelMode, panelMenuOpen 控制三个侧栏宽度/折叠及 Panel 切换 useUiStore
资源与统计 tokenPanelCollapsed, currentContextTokens, currentConversationTokens, usageQuota, usageQuotaTimer, projectStorage, containerStatus, containerNetRate Token/Quota/容器与存储统计,含轮询定时器 useResourceStore
Toast/Confirm/Quota quotaToast, toastQueue, nextToastId, confirmDialog, pendingConfirmResolver 全局通知与确认框 useUiStore
文件/待办/子智能体 fileTree, expandedFolders, focusedFiles, todoList, subAgents, subAgentPollTimer 侧栏三合一内容、聚焦文件、子智能体轮询 useFileStore / useTaskStore / useSubAgentStore
工具/快捷菜单 toolMenuOpen, settingsOpen, quickMenuOpen, toolSettings, toolSettingsLoading, preparingTools, activeTools, toolActionIndex, toolStacks 工具禁用菜单、Quick Menu、流式工具卡片状态 useToolStore
输入与上传 inputMessage, inputLineCount, inputIsMultiline, inputIsFocused, uploading 输入框动态高度、上传反馈 useChatStore / useUploadStore
个性化 personalPageVisible, personalizationLoading, personalForm, tonePresets, newConsideration, personalizationStatus/Error 个人空间表单、拖拽排序、开关提示 usePersonalizationStore
其它 contextMenu, easterEgg, icons, toolCategoryIcons, onDocumentClick/onWindowScroll/onKeydownListener 文件树右键、彩蛋生命周期、全局事件清理 useUiStore

注意:toolActionIndexdata() 中被声明两次,后者覆盖前者;重构时可合并为单一 Map。

API & Socket 交互速览

  • REST 拉取/api/files, /api/focused, /api/status, /api/todo-list, /api/sub_agents, /api/tool-settings, /api/usage, /api/project-storage, /api/container-status, /api/conversations, /api/conversations/<id>/load|messages|tokens|compress, /api/conversations/current, /api/upload, /api/download/file|folder, /api/personalization, /api/thinking-mode, /api/logout, /api/focus 相关(通过工具块触发),/api/terminalsvia 终端页面)。部分接口混用 GET/POST/PUT。
  • Socket 通道ai_message_start|end, thinking_start|chunk|end, text_start|chunk|end, tool_preparing|status|start|result, tool_settings_updated, append_payload, modify_payload, system_message, quota_update|notice|exceeded, token_update, todo_updated, 子智能体/聚焦更新等。发送事件包括 send_message, send_command, stop_task
  • 轮询:容器指标每 500ms项目存储 5s额度 60s子智能体 5s仅在 tab 打开时Tool 设置按需拉取。

布局与模块

1. 对话历史侧边栏(.conversation-sidebar

  • 收起状态:仅露出三个纵向按钮(展开、开新对话、个人页面)。点击任意按钮会展开或进入个人页面。
  • 展开后结构
    1. conversation-header:左侧“新建对话”主按钮、右侧“折叠”箭头;另有快捷按钮(加号、折叠/展开)。
    2. conversation-search:输入框绑定 searchQuery@input 防抖 300ms 触发 searchConversations(当前实现仅回退到全列表,保留 TODO
    3. conversation-list:显示加载态/空态/列表;条目包含标题、更新时间、消息/工具数量、删除/复制按钮(调用 /api/conversations/<id>/delete|duplicate,逻辑位于 methods);点击条目触发 loadConversation。列表底部 加载更多 控制分页 (limit=20 offset 递增)。
    4. conversation-personal-entry:打开“个人空间”。
  • 路由策略bootstrapRoute 根据 window.location.pathname 自动加载 conv_<id>history.pushState 在切换对话后更新 URLpopstate 监听需重载历史。

2. 三合一左侧面板(.left-sidebar

  1. 状态卡:展示 LogoiconStyle('bot'))、agentVersionthinkingMode 标签(brain/zap 图标切换),右侧连接状态圆点(connection-dot)。
  2. 面板卡
    • 顶部 panel-menu 透视 panelModefiles/todo/subAgentssidebar-view-toggle 打开菜单,点击按钮 selectPanelMode() 并可 cyclePanelMode()
    • 文件树(默认):递归组件 <file-node>,使用 expandedFolders 记住展开;右键触发 contextMenu(下载文件/目录 ZIP。点击文件节点 currently 仅选中 highlight无 open 行为)。
    • 待办todoListinstruction, tasks。任务展示标题、执行人与状态标记。
    • 子智能体subAgents 卡片显示 agent_id, status, summary, last_tool;点击调用 openSubAgent() 生成 URL 并 window.open
  3. 拖拽手柄.resize-handle 左侧 @mousedown="startResize('left', $event)" 控制 leftWidth350~600px

3. 聊天区域(.chat-container

3.1 Token/Quota/资源抽屉(.token-drawer

  • currentConversationId 存在时显示,tokenPanelCollapsed 控制折叠。
  • 内容
    • Token 统计currentContextTokens, currentConversationTokens
    • 性能统计:容器状态 pill + CPU/内存 + 宿主机占位提示。
    • 额度统计:显示常规模型/思考/搜索剩余额、自动格式化 reset 时间。
    • 资源统计:网络速率(containerNetRate+ 项目存储用量(projectStorage)。
  • 抽屉状态可通过 Quick Menu → 设置 → “用量统计”切换。

3.2 消息时间线(.chat-messages

  • 数据结构messages 数组,元素为 { role: 'user'|'assistant'|'system', content, actions[] }
  • 渲染块
    1. 用户消息:头像 + 气泡、背景框。
    2. 助手消息:每个 action 渲染成折叠块(thinking/text/tool/append_payload/modify_payload/system)。
      • thinking:带“正在思考”标题,自动滚动/折叠/锁定;thinkingScrollLocks 确保块滚至底部,结束后 1s 自动折叠改名为“思考过程”。
      • textMarkdown 渲染 + marked + Prism + KaTeX,支持 copy codecopyCodeBlock() 通过 data-code-id/data-code 属性工作)。
      • tool:卡片包含工具名、图标(TOOL_ICON_MAP),参数快照/状态消息/结果JSON、plain text、命令输出 pre),流式时加 loading 条;action.tool.awaiting_content 控制“等待正文”占位。工具 status 颜色区分 preparing/running/completed/error
      • append_payload/modify_payload:专门显示文件路径、强制标志、成功/失败行数。
      • system:用于 role=system 文本,折叠块 system-message
  • 特殊处理renderHistoryMessages() 会读取消息的 reasoning_content、自定义 metadataappend_payload, modify_payload),并避免 LLM 输出的 <<<APPEND/<<<MODIFY>>> 内容直接进入 UI。
  • 滚动策略messagesArea 的 scroll 事件更新 userScrolling/autoScrollEnabledscroll-lock-toggle 按钮切换锁定;思考块单独监听 scroll 以保持 pinned 行为。

3.3 输入区(.compact-input-area

  • 结构:stadium-shell 包含隐藏 <input type="file">、左侧 + 按钮、textarea、右侧发送/停止按钮。textarea 支持 Ctrl+Enter 发送、根据内容自动扩高(最多 6 行,autoResizeInput 计算 line-height
  • + 按钮弹出 quick-menu(点击外部关闭):
    • 上传文件 → 触发隐藏文件输入 → /api/upload → Toast 队列显示进度、完成、失败;完成后刷新文件树。
    • 工具禁用 → 二级菜单罗列 toolSettings(按分类 toggles, icon 由 TOOL_CATEGORY_ICON_MAP 指定)。禁用/启用通过 POST /api/tool-settings 并即时刷新。
    • 思考/快速模式 → 切换 thinkingMode(调用 /api/thinking-mode)。
    • 设置 二级菜单:
      1. 实时终端openRealtimeTerminal() 新开 /terminal
      2. 聚焦面板 → 切换右侧 rightCollapsed
      3. 用量统计 → 切换 Token Drawer。
      4. 压缩对话 → POST /api/conversations/<id>/compress,需确认框、compressing 状态。
  • 发送按钮:若 streamingMessage 为真则显示 STOP 图标,点击调用 stopTaskSocket stop_task)。发送前检查额度(isQuotaExceeded + quotaToast)。命令以 / 开头时走 send_command

4. 右侧聚焦面板(.right-sidebar

  • 默认折叠(rightCollapsed = true),通过 Quick Menu → 设置或拖拽手柄展开。
  • 内容:顶部标题 + “聚焦文件 (x/3)” 计数;focusedFiles{ path: { size, content } }
  • 每个 tab 展示文件名、大小KB, 1 decimal<pre><code> 语法高亮(getLanguageClass 基于拓展名)。无文件时显示“暂无聚焦文件”。

5. 个人空间(.personal-page-overlay

  • 从左侧最下方“个人页面”按钮或 Sidebar collapsed 图标进入,覆盖全屏(透明蒙层 + Card。支持鼠标/触摸长按关闭(handleOverlayPress*)。
  • 表单字段:启用开关(即时 POST /api/personalizationpersonalizationToggleUpdating 防抖、自称、称呼、职业、语气、Considerations 列表(拖拽排序 + 新增输入 + 预设语气 chips。保存按钮提交 /api/personalizationPOST JSON
  • 顶部按钮退出登录POST /logout)与返回工作区。

6. 全局 Overlay/服务

  • Quota Toast:置顶横幅 quota-toast 显示额度提醒;showQuotaToast() 控制。
  • Toast StacktoastQueue 通过 <transition-group> 渲染,支持自动消失/手动关闭。
  • Confirm DialogconfirmDialog + handleConfirm 用于危险操作。
  • 上下文菜单contextMenu 仅针对文件树节点(下载文件/文件夹)。
  • Easter Egg OverlayeasterEgg.active 控制 <div class="easter-egg-overlay">Tool trigger_easter_egg 结果由 handleEasterEggPayload -> EasterEggRegistry 播放,支持自动清理。

消息/工具渲染细节

  • 助手消息结构ensureAssistantMessage() 保证 messages 末尾存在 role: 'assistant'actions: [],之后所有流式事件都向该 actions push。
  • 流式顺序ai_message_start 新增消息 → thinking_start/chunk/endtext_start/chunk/end → 多个工具事件preparing/status/start/result/append_payload/modify_payload/system_messageai_message_end(重置 currentMessageIndex, streamingMessage, stopRequested)。
  • Tool Actionaction.tool 包含 id/name/status/statusDetail/result/arguments/argumentSnapshot/argumentLabel/message/executionId/awaiting_contentregisterToolAction & Maps 用于后续 socket事件匹配。
  • Append/Modify Payload:用于 append_to_file/modify_file 工具响应,展示 path、强制写入 flag、影响行数/块数。
  • System BlockappendSystemAction 插入“系统消息” collapsible。
  • LaTeXrenderLatexInRealtime()text_chunk/text_end 之后执行 renderMathInElement

文件/待办/聚焦/子智能体逻辑

  • 文件树updateFileTree()/api/files 返回的嵌套结构转换为 nodes{ type: 'folder'|'file', name, path, children, annotation });右键 @contextmenu 记录 node 与鼠标位置,点击菜单按钮调用 /api/download/file|folder
  • 聚焦文件/api/focused 返回 { path -> { size, content } },显示/下载/滚动 purely 只读。工具 focus_file/unfocus_file 事件会触发 focusedFiles 刷新(applyStatusSnapshot/socket
  • 待办/api/todo-list -> this.todoList = { tasks: [], instruction }todo_updated socket 事件使 UI 立即同步。
  • 子智能体/api/sub_agents + 5s 轮询;openSubAgent 构建 URL优先 window.SUB_AGENT_BASE_URL。状态 pill 颜色由 class agent.status 控制。

Token/资源/Quota 面板行为

  • token_update socket:仅处理当前对话 ID一次更新 currentConversationTokens + currentContextTokens + usageQuota + quotaToast
  • 工具完成数updateCurrentContextTokens() 在 Tool 完成/消息发送后延迟调用 /api/conversations/<id>/tokens
  • 容器指标pollContainerStats()(未在片段展示)调用 /api/container-statusupdateContainerStatus() 根据 stats.timestamp/rx_bytes/tx_bytes 计算 containerNetRate(字节差 / 时间差)。
  • 项目存储pollProjectStorage() -> /api/project-storageusage_percent/limit_label 直接展示。
  • 额度/api/usage -> normalizeUsageQuota() -> Quick Menu, Toast, Token Drawer 共享;quota_notice/exceeded socket 触发顶部通知 + 立刻刷新额度。

快捷交互流程

  1. 加载流程mountedbootstrapRoute()(解析 URLinitSocket()(分配 token, 监听事件)→ initScrollListener()setTimeout(loadInitialData, 500)(并发加载文件树/聚焦/待办/状态/工具设置/对话 tokensstart*Polling()
  2. 发送消息:输入→sendMessage() 检查 quota → push 用户消息 → socket.emit('send_message', { message, conversation_id })scrollToBottom → 1s 后刷新 token。
  3. 停止任务streamingMessage + Stop 按钮 → socket.emit('stop_task')ai_message_endtext_end 事件最终 stopRequested = false
  4. 上传Quick Menu “上传文件” → <input type=file>/api/uploadFormData→ Toast 过渡 + refreshFileTree() → 出错时匹配错误文案(安全审核/禁用类型)。
  5. 对话切换:侧栏点击 → /api/conversations/<id>/loadPUTresetAllStates()fetchAndDisplayHistory() + fetchConversationTokenStatistics() + updateCurrentContextTokens()history.pushState()
  6. 个性化:打开个人空间 → /api/personalization GET → 表单编辑/拖拽/预设 → 保存 POST → 成功/失败提示;启用/停用走单独 API。
  7. 工具禁用Quick Menu → Tool submenu → POST /api/tool-settings → UI 更新 + tool_settings_updated socket 兜底。
  8. 压缩对话Quick Menu → 设置 → handleCompressConversationClick() → Confirm → POST /api/conversations/<id>/compress → 新 ID 赋值 + 继续加载。

样式与布局要点

  • 定位.main-container 高度锁定 var(--app-viewport)避免移动端地址栏影响body overflow: hidden,聊天区域内部 overflow-y: auto
  • 配色:大量 var(--claude-*) 变量 + 玻璃态背景(backdrop-filter)。按钮/输入/面板 radius 取值 12~24px。
  • 动效:多处 transition (quick-menu, submenu-slide, personal-page-fade, quota-toast-fademode-icon 等)Thinking → Collapse, Scroll lock UI 2 态 SVG。
  • 拖拽Considerations 列表使用 draggable + dragstart/dragover/drop;侧栏手柄 cursor: col-resize
  • Icon 渲染:统一使用 CSS mask.icon+ iconStyle('--icon-src') 设定路径。

重构建议(旧 → 新 Store/组件映射)

模块 旧 DOM/方法 目标组件 相关 Store/Composable
对话历史侧栏 conversation-sidebar + loadConversationsList/loadConversation/duplicate/delete ConversationSidebar.vue useConversationStore
Logo/状态卡 + Panel 切换 .sidebar-status + .sidebar-panel-card LeftPanel.vue + StatusHeader.vue + PanelSwitcher.vue useSystemStore, useFileStore, useTaskStore, useSubAgentStore
文件树节点 <file-node> 组件 FileTreePanel.vue useFileStore
Token/Quota Drawer .token-drawer + startContainerStatsPolling TokenDrawer.vue + ResourceStats.vue useResourceStore
聊天消息 .chat-messages + messages/actions 渲染 ChatArea.vue + MessageList.vue + MessageItem.vue + ActionCard 子组件 useChatStore, useToolStore
输入区/Quick Menu .compact-input-area + quick-menu InputComposer.vue + QuickMenu.vue + ToolToggleMenu.vue + SettingsMenu.vue useChatStore, useToolStore, useUploadStore
聚焦面板 .right-sidebar RightFocusPanel.vue useFocusStore
个人空间 .personal-page-overlay PersonalizationDrawer.vue usePersonalizationStore
Toast/Confirm/ContextMenu quota-toast, .toast-stack, .confirm-overlay, .context-menu ToastStack.vue + ConfirmDialog.vue + ContextMenu.vue useUiStore
彩蛋 .easter-egg-overlay + handleEasterEggPayload EasterEggOverlay.vue + composable useUiStore

关键注意事项

  • 完全还原Phase 标签已失效,重构时应以本文 + 备份代码为唯一真值;任何现存 Vite 代码若偏离需求可直接推翻。
  • 流式同步Tool/思考/文本事件严格依赖顺序、状态映射与 action.id,必须在组件化后保持同等粒度,避免“危房式”拼接。
  • 多重状态同步Token 面板、Quota Toast、Quick Menu 与资源轮询之间互相引用(如工具完成后更新 Token实现时应通过跨 store action 协调。
  • 可访问性:旧版所有按钮均提供 title/aria-label,复制按钮状态 2s 自动恢复;滚动锁按钮使用 svg icon 反馈;保留这些交互细节。
  • 安全脚本/static/security.jswindow.ensureCsrfTokenwindow.requestSocketTokenEasterEggRegistry 等全局依赖需要在新构建链路中继续注入或以 shim 方式提供。

后续编码时,请以此文档 + static/old_version_backup/前端备份 中的 HTML/CSS/JS 为参考基准,确保界面结构、逻辑流与交互表现与旧版完全一致,再逐步拆分到 Vue 组件与 Pinia store。