feat/frontend-phase2-themes-trace-mermaid
main
上一版前端第二阶段 PR(#18)被审阅关闭,结论「请求修改,暂不合并」,共 6 项 P2 问题。本 PR 在同一分支上逐项修复并补充回归测试,功能范围与 #18 一致(Agent Trace 可视化、主题清单/导入、Mermaid 渲染、插件命令与设置 UI)。
审阅版本 12869b5,本次提交 f273fef。
12869b5
f273fef
1. 主题导入未读取用户提供的 CSS
inspectThemePackage 原先只解析 YAML 清单,ThemesView.confirmInstall 另外调用 generateThemeCss() 生成硬编码演示配色 —— 用户提供的 CSS 被整份丢弃。
inspectThemePackage
ThemesView.confirmInstall
generateThemeCss()
---
parseThemePackage()
generateThemeCss
PK\x03\x04
UEsDB
accept
THEME_PACKAGE_UNSUPPORTED_FORMAT
.yaml,.yml,.theme
readAsText
installTheme
validateCssSafety
applyThemeCss
<details>
2. 刷新页面后无法恢复自定义主题
initTheme 原先 void loadCustomThemes() 未 await,applyTheme(saved) 因主题不在 allThemes 里而静默 return,页面停在完全没有 data-theme 的裸状态。
initTheme
void loadCustomThemes()
applyTheme(saved)
allThemes
return
data-theme
applyTheme
boolean
false
{ persist: false }
await loadCustomThemes()
themeLoadWarning
loadCustomThemes
3. Trace 建树逻辑与真实后端事件顺序不一致
核对 backend/app/agent/runtime.py 后确认:真实顺序是 ModelCallStarted → ModelCallCompleted → Usage → ToolCall/ToolResult,工具在模型调用完成之后才执行,且多个工具并发跑(asyncio.gather + Semaphore)会交错到达 —— 事件相邻性根本不可用。
backend/app/agent/runtime.py
ModelCallStarted → ModelCallCompleted → Usage → ToolCall/ToolResult
asyncio.gather
Semaphore
model_call_id
parent_model_call_id
tool_call_id
ToolResult
ToolCall
running
ModelCallCompleted/Failed
success
token_usage
input_tokens/output_tokens/total_tokens
4. 树形视图叶子节点无法展开详情
行的 click 是 children.length && toggleExpand(id),而详情 v-if 又要求 children.length === 0 —— 两个条件互斥,叶子详情永远打不开。
children.length && toggleExpand(id)
v-if
children.length === 0
expandedNodes
detailNodes
<button>
@click.stop
aria-label
role="button" tabindex="0"
aria-expanded
5. 引用点击未接入笔记定位流程
navigateToCitation()
useCitationNavigation()
await loadFile
highlightBlock
stores/editor.ts
loadFile
highlightBlockId
AgentView
@open-citation
ChatView
AppShell
6. 新命令页缺少参数输入和实际效果执行
排查后发现 PluginsView 的命令页是 PluginMcpPanel 已有 schema 驱动表单的劣化副本,因此按建议复用而非各自改进:
PluginsView
PluginMcpPanel
PluginCommandPanel.vue
loadVersion
when
pluginCommandForm.ts
commandFields
initialArguments
coerceArgument
missingRequiredFields
cleanArguments
applyCommandEffect
navigate
router.push(undefined)
refresh
workspaceStore.refreshFileTree()
traceService.spec.ts
theme.spec.ts
themePackageService.spec.ts
parseThemePackage
pluginCommandForm.spec.ts
useCitationNavigation.spec.ts
TraceTimeline.spec.ts
vue-tsc -b --force
vitest
vite build
MarkdownContent
tsconfig.app.json
skipLibCheck: true
type-fest
type-fest@^4
^5
仅 frontend/src 下第二阶段前端相关文件,未改动 backend 与契约实现(contracts/index.ts 仅新增 ThemePackageInspection.css 字段与两个主题错误码)。
frontend/src
contracts/index.ts
ThemePackageInspection.css
审阅 PR #23,版本 f273fef,目标分支 main 为 1c7b5b4。
1c7b5b4
本轮发现两个已复现的问题,另有 8 个文件存在合并冲突。建议完成以下修复并解决冲突后,再进行合并验证。
位置:frontend/src/services/themePackageService.ts:235–240
frontend/src/services/themePackageService.ts:235–240
安装主题时会立即注入 CSS,加载主题列表时又会注入所有已安装主题的 CSS。当前校验仅对缺少主题作用域给出警告,因此包内的 body、:root 等规则会直接影响当前页面,即使用户尚未启用该主题。
body
:root
已复现:
light
body { color: rgb(1, 2, 3) !important; }
切回内置主题也不会移除这些规则,多个已安装主题之间可能互相覆盖。
建议只挂载当前主题的 CSS,并在切换时移除旧主题样式;或者强制隔离主题包中的所有规则,确保未启用主题不会影响页面。
建议补充回归测试:
位置:frontend/src/features/plugins/PluginSettingsPanel.vue:56–62
frontend/src/features/plugins/PluginSettingsPanel.vue:56–62
设置保存期间输入框仍可编辑,但请求成功后会无条件执行 hasChanges = false。这会把请求发出后产生的新编辑错误地标记为已保存。
hasChanges = false
first edit
second edit
此时用户无法直接保存最新输入,离开页面还可能丢失该修改。
建议使用编辑版本或提交快照判断是否仍有未保存内容;也可以在保存期间禁用编辑,确保显示状态与实际持久化结果一致。
当前 PR 与最新 main 存在以下 8 个文件冲突:
frontend/src/components/common/CommandPalette.vue
frontend/src/features/agent/AgentView.vue
frontend/src/features/chat/ChatView.vue
frontend/src/features/plugins/PluginMcpPanel.vue
frontend/src/features/plugins/PluginsView.vue
frontend/src/features/themes/ThemesView.vue
frontend/src/main.ts
frontend/src/stores/theme.ts
解决冲突时需保留 main 已合入的中英文支持、聊天记录持久化及会话并发修复,随后对合并结果重新运行测试和构建。
请修复上述问题、补充回归测试并解决合并冲突后再次请求审阅。
整合最新 main,并修复 frontend phase2 前两轮审阅发现的问题。
审阅结论:同意合并。
此前提出的主题 CSS 泄漏、保存状态竞态、密钥新输入丢失和社区主题预览无效问题均已修复,并补充回归测试。
本轮复审未发现新的阻塞问题。最新 main 的聊天持久化、会话并发修复、中英文支持和 Shiki 能力得到保留。
验证结果:233 项前端测试、类型检查及生产构建通过;浏览器已验证主题隔离、实际预览与保存行为。
生产插件后端端到端验收尚未覆盖,构建体积提示可作为后续优化项。
No dependencies set.
The note is not visible to the blocked user.
背景
上一版前端第二阶段 PR(#18)被审阅关闭,结论「请求修改,暂不合并」,共 6 项 P2 问题。本 PR 在同一分支上逐项修复并补充回归测试,功能范围与 #18 一致(Agent Trace 可视化、主题清单/导入、Mermaid 渲染、插件命令与设置 UI)。
审阅版本
12869b5,本次提交f273fef。审阅问题修复(6 项 P2)
1. 主题导入未读取用户提供的 CSS
inspectThemePackage原先只解析 YAML 清单,ThemesView.confirmInstall另外调用generateThemeCss()生成硬编码演示配色 —— 用户提供的 CSS 被整份丢弃。---+ 主题 CSS,新增parseThemePackage()取出真实 CSS,安装时原样使用,已删除generateThemeCss。PK\x03\x04与 base64 的UEsDB(文件选择器的accept只是提示,不能依赖),返回THEME_PACKAGE_UNSUPPORTED_FORMAT。accept收窄为.yaml,.yml,.theme,统一readAsText。installTheme内保留validateCssSafety必须先于applyThemeCss的约束与注释(未校验的 CSS 一律不进页面)。<details>展示将要安装的 CSS 原文与字符数,便于用户核对。2. 刷新页面后无法恢复自定义主题
initTheme原先void loadCustomThemes()未 await,applyTheme(saved)因主题不在allThemes里而静默return,页面停在完全没有data-theme的裸状态。applyTheme改为返回boolean,主题不存在时返回false而非静默失败。{ persist: false },避免把用户存的自定义主题 id 冲掉,也不让首屏干等接口),await loadCustomThemes()之后再切到真正保存的那个。themeLoadWarning告知用户;loadCustomThemes的 catch 不再吞掉异常。3. Trace 建树逻辑与真实后端事件顺序不一致
核对
backend/app/agent/runtime.py后确认:真实顺序是ModelCallStarted → ModelCallCompleted → Usage → ToolCall/ToolResult,工具在模型调用完成之后才执行,且多个工具并发跑(asyncio.gather+Semaphore)会交错到达 —— 事件相邻性根本不可用。model_call_id/parent_model_call_id/tool_call_id。ToolResult不再单独成节点,而是回填对应ToolCall的状态与耗时,结束后不会再停在running;结果数据合并进调用节点供展开查看。ModelCallCompleted/Failed同样只更新对应节点状态。ToolResult也按success显示 error,不再一律算成功。token_usage,原实现读的input_tokens/output_tokens/total_tokens都不存在。4. 树形视图叶子节点无法展开详情
行的 click 是
children.length && toggleExpand(id),而详情v-if又要求children.length === 0—— 两个条件互斥,叶子详情永远打不开。expandedNodes(子树展开)与detailNodes(查看本节点数据)两个独立状态集合,任何节点含叶子都能查看自身数据。<button>+@click.stop+aria-label;行本身role="button" tabindex="0",支持 Enter/Space,aria-expanded跟随详情开合。5. 引用点击未接入笔记定位流程
navigateToCitation()(纯函数 + 依赖注入,可脱离 Vue 上下文测试)与useCitationNavigation()组合式封装。await loadFile再highlightBlock——stores/editor.ts的loadFile末尾会把highlightBlockId清空,顺序反了高亮会被自己冲掉;loadFile失败时抛出且不跳转,避免把用户从未保存的编辑器里弹走。AgentView接上@open-citation并把失败原因显示给用户;顺带消除原有三处重复实现:ChatView改为委托同一函数,AppShell里那份既无调用方又漏了loadFile的副本一并修正。6. 新命令页缺少参数输入和实际效果执行
排查后发现
PluginsView的命令页是PluginMcpPanel已有 schema 驱动表单的劣化副本,因此按建议复用而非各自改进:PluginCommandPanel.vue(loadVersion防竞态、重新加载时重置表单避免用旧值提交非法参数、when条件判断),PluginMcpPanel与PluginsView均改为复用,删除两份重复实现与相关孤立 CSS。pluginCommandForm.ts:commandFields/initialArguments/coerceArgument/missingRequiredFields/cleanArguments/applyCommandEffect。navigate走路由白名单(未知路由只提示,不会router.push(undefined))、refresh按 scope 实际派发(新增workspaceStore.refreshFileTree()),不再只拼成说明文本。PluginMcpPanel里两个潜在问题:必填字段标了「必填」却无客户端校验(只能靠后端拒绝才知道),以及布尔下拉框显示「否」但参数对象里没有该键 —— UI 与实际提交值不一致。测试
traceService.spec.ts—— 按真实后端事件顺序重写建树用例,覆盖并发工具交错到达、ToolResult回填状态、SSE 断点恢复孤立事件。theme.spec.ts—— 覆盖 await 后恢复、首屏兜底不覆盖已存 id、主题失效回退与告警、列表加载失败告警。themePackageService.spec.ts—— 新增parseThemePackage全套用例(真实 CSS 提取、CSS 内含---不被截断、CRLF、缺分隔行、空 CSS、ZIP 与 base64 ZIP 拒绝),并补「注入的 CSS 与包内内容逐字一致」。pluginCommandForm.spec.ts、useCitationNavigation.spec.ts、TraceTimeline.spec.ts。vue-tsc -b --force通过,vitest32 个文件 / 182 项全部通过,vite build成功。已知项 / 待确认
MarkdownContent约 1.5 MB,主因 mermaid + katex)。可改为动态 import 拆分,但会影响首次渲染时序,倾向单独一个 PR 处理,本轮未动。tsconfig.app.json的skipLibCheck: true是绕开 mermaid 打包缺陷(它把type-fest泄漏进发布类型却只声明为自身 devDependency)。另一条路是自行补type-fest@^4devDependency(^5需要 ES2024,与本项目 ES2022 目标冲突)。听审阅意见取舍。范围
仅
frontend/src下第二阶段前端相关文件,未改动 backend 与契约实现(contracts/index.ts仅新增ThemePackageInspection.css字段与两个主题错误码)。审阅结论:请求修改,暂不合并
审阅 PR #23,版本
f273fef,目标分支 main 为1c7b5b4。本轮发现两个已复现的问题,另有 8 个文件存在合并冲突。建议完成以下修复并解决冲突后,再进行合并验证。
[P2] 未启用主题的 CSS 仍会影响当前页面
位置:
frontend/src/services/themePackageService.ts:235–240安装主题时会立即注入 CSS,加载主题列表时又会注入所有已安装主题的 CSS。当前校验仅对缺少主题作用域给出警告,因此包内的
body、:root等规则会直接影响当前页面,即使用户尚未启用该主题。已复现:
light。body { color: rgb(1, 2, 3) !important; }的自定义主题。切回内置主题也不会移除这些规则,多个已安装主题之间可能互相覆盖。
建议只挂载当前主题的 CSS,并在切换时移除旧主题样式;或者强制隔离主题包中的所有规则,确保未启用主题不会影响页面。
建议补充回归测试:
[P2] 保存响应会错误清除请求期间的新编辑状态
位置:
frontend/src/features/plugins/PluginSettingsPanel.vue:56–62设置保存期间输入框仍可编辑,但请求成功后会无条件执行
hasChanges = false。这会把请求发出后产生的新编辑错误地标记为已保存。已复现:
first edit并点击保存。second edit。first edit。second edit,但保存按钮已禁用,未保存提示也已消失。此时用户无法直接保存最新输入,离开页面还可能丢失该修改。
建议使用编辑版本或提交快照判断是否仍有未保存内容;也可以在保存期间禁用编辑,确保显示状态与实际持久化结果一致。
建议补充回归测试:
合并冲突
当前 PR 与最新 main 存在以下 8 个文件冲突:
frontend/src/components/common/CommandPalette.vuefrontend/src/features/agent/AgentView.vuefrontend/src/features/chat/ChatView.vuefrontend/src/features/plugins/PluginMcpPanel.vuefrontend/src/features/plugins/PluginsView.vuefrontend/src/features/themes/ThemesView.vuefrontend/src/main.tsfrontend/src/stores/theme.ts解决冲突时需保留 main 已合入的中英文支持、聊天记录持久化及会话并发修复,随后对合并结果重新运行测试和构建。
验证记录
请修复上述问题、补充回归测试并解决合并冲突后再次请求审阅。
变更说明
整合最新 main,并修复 frontend phase2 前两轮审阅发现的问题。
主题管理
插件设置
与 main 整合
验证
限制
审阅结论:同意合并。
此前提出的主题 CSS 泄漏、保存状态竞态、密钥新输入丢失和社区主题预览无效问题均已修复,并补充回归测试。
本轮复审未发现新的阻塞问题。最新 main 的聊天持久化、会话并发修复、中英文支持和 Shiki 能力得到保留。
验证结果:233 项前端测试、类型检查及生产构建通过;浏览器已验证主题隔离、实际预览与保存行为。
生产插件后端端到端验收尚未覆盖,构建体积提示可作为后续优化项。
Pull request closed