feat: WebUI 导航三分区与场景工作区;修复流式工具参数被截断仍照常执行 - #749
Open
jamon-bodhi wants to merge 9 commits into
Open
Conversation
- 侧栏:删除「场景工作区」分组,SOC 工作区升为一级分组,设备接入移入智能体工作室;AI 工作台与工作区分组做成手风琴,同一时刻只展开一个,进入对应页面自动切换并持久化 - 二级菜单:AI 工作台、SOC 工作区、智能体工作室都支持拖拽和 Alt+方向键排序,按分组存 localStorage - 顶部标签栏:打开过的侧栏入口成为标签,可切换、关闭、拖动排序,记住最后停留的子路径;「+」菜单按分组列出未打开页面 - keep-alive:路由子表抽到 routes/contentRoutes.tsx,Layout 为每个打开过的标签保留面板,非当前面板 visibility:hidden + inert,状态与滚动位置保留;刷新后恢复的标签懒挂载 - 工作区宿主页:根路径直接跳默认页,去掉页内页签,修复 t 进依赖导致的重复拉取 - SOC 态势大屏插件:三处 100vh 改为按容器高度,soc_ui 升到 1.1.6
顶栏只保留 Agent、SOC工作区、系统设置三个分区,左侧只显示当前分区的菜单。每个访问过的 菜单项各自保活,切走再切回来页面还是原样(滚动位置、未提交的输入都在),分区之间也各自 记住上次停留的页面。 - 系统设置改为在布局内渲染,不再是带「返回」的独立整屏页 - 场景工作区的页面平铺成同一级菜单,不做分组 - 场景套件的安装、停用、卸载统一放到场景工作区,插件广场不再列出场景套件 - Hub 插件增加 edition 字段:Pro 专属套件(代码审计、AI 红队)仍然列出但拒绝安装, 直接访问它们的路由会说明需要 Flocks Pro - 场景工作区可以停用而不卸载套件,停用后旧页面链接给出提示 - 安装/更新套件时会带上版本落后的子件,避免套件与它的页面版本脱节 Claude-Session: https://claude.ai/code/session_019toMtTXUWkgQBBRfUCy2PJ
长 write / edit 的参数流被上游切断后,累加器会把残缺 JSON 补齐再执行,结果是文件只写了一半却报成功。 三处根因一起修: - 累加器不再用补齐后的 JSON 兜底执行。JSON 解析失败时先判断是不是「补上未闭合的引号和括号就能解析」, 是就走截断路径:发 ToolInputErrorEvent、标记失败、抛 StreamToolArgumentsTruncatedError,不执行工具。 真正格式错误的参数仍走原来的 invalid-tool 路径 - Anthropic 适配层保留 stop_reason:原来 message_stop 一律上报 "stop",max_tokens 截断和正常结束 在下游无法区分。现在 max_tokens 映射为 length、tool_use 映射为 tool_calls - openai_base 改为参数片段边到边转发:原来把整段参数 JSON 攒到 finish_reason 才发, 长调用期间适配层整段静默,把 runner 的流中途 chunk 看门狗饿死了。末尾那个 chunk 只带还没转发的尾巴, 避免累加器重复追加 回归测试都验过有效性:三个源文件各自还原到修改前,对应用例都会红。 Claude-Session: https://claude.ai/code/session_019toMtTXUWkgQBBRfUCy2PJ
装了不止一个场景工作区时,侧栏底部的「自定义页面」「自定义标题」两个按钮会消失。 根因是 `LayoutNavSection.workspace` 一个字段同时承担了两件事:决定拖动排序存到哪个工作区的 key 下, 以及决定工作区动作挂在谁身上。多场景共用一条平铺菜单时前者必须为空——否则会把别的场景的页面顺序 写进 SOC 的排序 key——结果把后者一起关掉了。 拆成两个字段:`workspace` 继续只管排序归属,新增 `actionsWorkspace` 固定指向 SOC 工作区, 有几个场景都不受影响。 菜单本身维持一级平铺、分区名仍为 SOC工作区,这次不改。 新增回归测试 keeps every scene in one flat menu and keeps the SOC actions when several are installed,已验有效性:把 `actionsWorkspace` 改回旧写法后该用例报找不到 workspace.customPage 按钮。 Claude-Session: https://claude.ai/code/session_019toMtTXUWkgQBBRfUCy2PJ
装了多个场景工作区(SOC / 代码审计 / AI 红队)时,它们的页面原来全部并进同一条侧栏菜单, 既没有切换入口也分不清某一页属于哪个场景。 顶栏右侧加场景切换器,侧栏仍是一级平铺、不做分组,但只显示当前场景的页面;分区名保持 「SOC工作区」不变。当前场景由路由推导,路由里没有时取上次选过的、再没有就取第一个; 只装了一个场景时切换器不显示。工作区动作(自定义页面 / 自定义标题)只在 SOC 是当前场景时出现, 不跨场景跟随。 顺带修两处: - 顶栏改成单一横向滚动容器。原来三个 tablist 各自 overflow-x-auto 各自裁剪,400px 宽下 遮挡检测报出 3 个控件点不到(「SOC工作区」「系统设置」中心命中顶栏容器本身、「代码审计」 中心命中「场景套件」图标),复扫后降为 0 - 删掉账号弹窗里的「设置」入口。系统设置已经是顶栏分区,这是条重复路径 新增三条回归测试,都验过有效性:场景切换与隔离、单场景时不显示切换器、多场景时保留 SOC 动作。 Claude-Session: https://claude.ai/code/session_019toMtTXUWkgQBBRfUCy2PJ
对着 xlsx 逐条核对 feat/202609 的代码,查出两处报告称已完成、实际没进代码的缺口。 TC-02 要求「5个入口完整保留在对应分组下」,代码里 AI 工作台组只有工作台、文件目录、 任务中心、工作流 4 项,首页是独立的一节。对照 TC-03「7个入口完整保留在智能体工作室 分组下」——那一组代码里确实是 7 项,口径一致,所以本组应为 5 项。现把首页并入该组, 与 D01「首页归 Agent」一致。 规划表「Hub 场景入口」行要求目录、计数、版本、安装进度和工作区注册使用同一状态, 前四项已具备,安装进度缺失:SceneSuites 用的是普通 install 接口,装套件时只有按钮转圈。 改为走流式 installStream,复用 Hub 原有的 SuiteInstallProgressPanel 逐组件显示进度, 失败时落到 failSuiteInstallProgress 而不是只弹一个 toast。 两条回归测试都验过有效性:把源码分别还原后, reorders AI workbench entries by dragging 与 shows per-component install progress while a suite installs 各自变红。 Claude-Session: https://claude.ai/code/session_019toMtTXUWkgQBBRfUCy2PJ
- 告警态势所在 section 带 themeOverride: dark,宿主靠卸载时的清理撤销临时主题; 上了 KeepAlive 后页面不再卸载,override 一直挂着,切到哪个页签都是深色。 新增 PaneActiveContext,KeepAlivePanes 告诉子树自己是否在前台,宿主只在 自己的 pane 可见时持有 override,切走即由 effect cleanup 释放;inactive 的 pane 不再主动写 null,避免覆盖当前 pane 刚设的值。 - ThemeContext 加 mode: light | dark | system,默认 system,监听 prefers-color-scheme 的 change 事件实时跟随。旧实现一挂载就把 light 写进 localStorage.flocks_theme,从此再也不跟系统;改为只在用户显式选择时落盘, 换新键 flocks_theme_mode,旧键读时忽略、写时顺手删掉。index.html 的防闪烁 脚本同步改读新键,判定规则与 ThemeContext 一致。 - 偏好页主题从两项改为三项:跟随系统 / 浅色 / 深色;右列放宽到 20rem 并对 选项加 whitespace-nowrap,三项一行放下。 - 测试:ThemeContext 6 项按新行为重写(含 OS 实时切换与旧键忽略);宿主新增 「pane 隐藏时释放 override、重新可见时取回」回归用例;Settings 新增跟随系统 选项用例。 Claude-Session: https://claude.ai/code/session_013YByVmNxkWwDs1kMpwkeN7
每个已启用的场景工作区各成一个一级分组(标题为场景名),页面是二级; 分组接入现有的 primary 手风琴,同一时间只展开一个场景,进入某场景的路由 自动展开它,展开状态沿用 flocks_layout_expanded_primary_nav_section (id 为 workspace:<id>)。自定义页面 / 自定义标题两个动作仍只挂在 SOC 分组下。 上一版「一级平铺 + 顶栏场景切换器」按最新要求撤掉:PartitionTopBar 去掉 scenes / activeSceneId / onSelectScene 与对应渲染,Layout 删除 activeSceneId 及 selectScene 派生逻辑,nav.json 去掉只给切换器用的 scenes 键。 Layout 测试改为断言场景标题、aria-expanded 互斥与直开链接自动展开,新增 「直接打开另一场景页面时展开对应分组」「单场景也有一级标题」两条。 Claude-Session: https://claude.ai/code/session_013YByVmNxkWwDs1kMpwkeN7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
分支 feat/202609 上的三块改动一起提,互不依赖,合并到 dev 无冲突。
WebUI 导航改成三个固定分区 + 场景工作区
顶栏只留 Agent、SOC工作区、系统设置三个分区,左侧只显示当前分区的菜单。访问过的菜单项各自保活,切走再切回来页面还是原样(滚动位置、没提交的输入都在),分区之间也各自记住上次停留的页面。系统设置改为在布局内渲染,不再是带「返回」的独立整屏页。
场景套件(SOC / 代码审计 / AI 红队)的安装、停用、卸载统一放到新的「场景工作区」页,插件广场不再列场景套件。SOC工作区分区的侧栏按套件分一二级:每个已启用的场景各占一个一级分组(标题是场景名),页面是二级;分组走手风琴,同一时间只展开一个场景,进某场景的路由自动展开它,刷新后记住。装一个场景就是一个一级标题加它的页面。Hub 插件加了
edition字段,Pro 专属套件照常列出但拒绝安装,直接访问它们的路由会提示需要 Flocks Pro。安装/更新套件时会一起带上版本落后的子件,避免套件和它的页面版本脱节。顺带修的几处:多场景时 SOC 的「自定义页面 / 自定义标题」按钮消失(
LayoutNavSection.workspace一个字段兼了排序归属和动作归属,拆成workspace+actionsWorkspace);顶栏 tablist 各自裁剪,400px 宽下有 3 个控件点不到,改成单一横向滚动容器后复扫为 0;账号弹窗里重复的「设置」入口删掉;首页并入 AI 工作台组;SceneSuites 安装改走 installStream,逐组件显示进度。告警态势的临时深色随页签走,主题默认跟随系统
告警态势所在 section 带
themeOverride: dark,宿主靠组件卸载时的清理撤销临时主题。上了 KeepAlive 后页面不再卸载,清理永远不跑,进过一次告警态势之后切到哪都是深色。新增PaneActiveContext,KeepAlivePanes 告诉子树自己是否在前台,宿主只在自己的 pane 可见时持有 override,切走即释放。另一处是主题从来没真正跟过系统:
index.html的防闪烁脚本是「没存过就跟系统」,但ThemeContext一挂载就把light写进localStorage.flocks_theme,写完就固定了。现在加了system模式并作为默认,监听prefers-color-scheme实时跟随,只在用户显式选择时落盘,换新键flocks_theme_mode(旧键读时忽略、写时删掉),偏好页主题变成 跟随系统 / 浅色 / 深色 三项。流式工具参数被截断时不再照常执行
长 write / edit 的参数流被上游切断后,累加器原来会把残缺 JSON 补齐再执行,文件只写了一半却报成功。三处一起修:
session/streaming/tool_accumulator.py:JSON 解析失败时先判断「补上未闭合的引号和括号就能解析」,是就走截断路径(发 ToolInputErrorEvent、标记失败、抛 StreamToolArgumentsTruncatedError),不执行工具;真正格式错误的参数仍走原来的 invalid-tool 路径provider/sdk/anthropic.py:message_stop 不再一律上报stop,max_tokens 映射为length、tool_use 映射为tool_calls,下游能区分截断和正常结束provider/sdk/openai_base.py:参数片段边到边转发,不再攒到 finish_reason 才整段发。原来长调用期间适配层整段静默,把 runner 的流中途 chunk 看门狗饿死了本地验证
CI 那几步(
ruff check两个 cli 文件、validate_flockshub.py800 个插件、pytest tests/scripts tests/hub、webuinpm run lint+npm run build)全过。后端另跑了tests/provider、tests/session/test_write_truncation_guard.py、tests/contracts/webui,和 CI 目录合计 696 passed / 17 skipped / 2 failed——那 2 个是tests/provider/test_chinese_providers.py里 qwen3.7 的 catalog 用例,在干净的 origin/dev 上同样红,本分支没动catalog.json。webui 在最新提交 c829230 上:
tsc0 错、eslint --max-warnings 00 错、vitest 1018 passed / 2 failed,失败的chunkLoadRecovery与Home 非管理员两条在 origin/dev 上同样红,本分支没动这两个文件。新增回归测试的有效性验证(还原源码让对应用例变红)见各提交正文。浏览器实测(Chrome,OSS 版):三分区切换、分区回访落点、KeepAlive 状态保持、套件卸载/重装(子件级联、文件清单逐项一致)、Pro 套件 403 与直开提示页、多场景一二级菜单与手风琴、告警态势进出的主题恢复,都跑过;带截图的测试报告是本地文件,没有随分支提交,需要的话另发。
https://claude.ai/code/session_013YByVmNxkWwDs1kMpwkeN7