Skip to content

bug(control-center): 历史会话切换模型失败时报错文本内联进中控区,撑破排版且会话内始终无法切换模型 #51

Description

@AlchemistCxC

问题

重启应用后打开历史会话,点击中控区(Control Center)的「模型」控件切换模型会失败,并且失败信息会内联渲染在中控区自身的排版流里:中控区被报错文本填满、排版错乱(状态栏控件被挤开/换行),且在会话内反复重试始终无法正常切换模型。

同一个渲染点(cc-widget-error)也被权限模式控件复用,故权限模式切换失败应有同样表现。

复现(报告人描述)

  1. 重启 Pylon。
  2. 在历史会话列表中打开一个已有会话。
  3. 点击中控区的 model 按钮 → 选择另一个模型。
  4. 预期:模型切换生效(或给出可关闭的失败提示,排版不受影响)。
  5. 实际:中控区出现报错文本并把排版撑乱;会话内 model 切换无法成功,重试仍失败并重复渲染错误。

环境

  • Windows(报告人环境),main f27c1c81d5b36f0b07cdd451d7dd26932389ae9f
  • 报告时间与 perf(frontend): 优化显示调度并整合已验证的结构简化 #50refactor/frontend-scheduling,同日合并)同日,未做 A/B 对照,因此不能判定是否为该次合并引入的回归。
  • 报告人未提供 Pylon 自身版本号与 agent 类型,修复前建议补齐。

证据:源码链条(静态阅读远端 main f27c1c8,未经运行时验证)

1. 失败文本被直接内联到中控区控件里

  • WorkbenchWidgets.solid.tsx#L122SolidModelWidget 在返回的 .solid-model-widget 内、紧邻模型控件之前渲染 <span class="cc-widget-error" role="alert">{message()}</span>
  • 同文件#L92choose()if (!result.ok) setError(result.error || '模型切换失败')result.error 是后端原始 message(见下)。
  • 同文件#L311:权限模式控件复用同一 class/同一内联位置。
  • 错误只在「下次切换成功」(#L93)或「会话 id 变化」(#L56-L65)时清空——因此在同一会话内失败一次后,文本会持续留在中控区,符合「被报错信息填满」。

2. .cc-widget-error 在整个仓库里没有任何 CSS 规则

f27c1c8ControlCenter.cssWorkbenchChrome.css 以及全仓库(排除 node_modules/target/dist/)grep cc-widget-error:只命中上面两处 TSX,无任何样式定义。即它是未加样式控制的裸文本:

  • ControlCenter.css#L90.cc-widget.cc-natural { width:max-content !important; height:auto !important; min-width:0 !important; }——控件宽度按内容取 max-content,没有上限。
  • 同文件#L83/#L91.cc-widgetdisplay:flex; overflow:visible;.cc-natural > *flex:none(不收缩)。
  • 同文件#L47.cc-status-row { display:flex; flex-wrap:wrap; }(footer 布局下对应 .cc-footer-status-row,L42)。

⇒ 一条不被截断、不可收缩的长文本会把所在 widget 撑到内容宽度,并把同排其它状态控件挤开/换行——与「中控区排版错乱」一致。(该机理为静态推断,具体变形形态需在有 GUI 的机器上复现确认。)

3. 失败信息本身可能很长,且切换在「模型面未宣告」时必然被拒

  • session/model.rs#L144SessionInfo::new 默认 model_surface: ModelSurface::None
  • 同文件#L233-L238model_surface 只在 apply_session_response(即 session/newsession/load 响应形状判定)时刷新apply_config_options(#L241-L268)亦仅在 agent 全量宣告 model 选项时刷新,否则把失效的 ConfigOption 面降级为 None
  • 同文件#L1053-L1057resolve_model_switch_targetModelSurface::None 时直接返回 PylonError::Protocol("model switching unavailable: agent advertises no model surface")
  • 同文件#L1065-L1073validate_model_advertisedmodel_not_advertised: requested model "…" is not in the agent-advertised choices [a, b, c, …]——把整份宣告列表拼进 message,文本可任意长。

推断(待运行时验证):重启后打开历史会话时,若该会话未重新走一次 session/load(或 agent 连接尚未建立/未宣告模型面),runtime 侧该会话的 model_surface 仍是 None ⇒ 每次切换都被 set_config_option 以长字符串拒绝 ⇒ 前端把它内联进中控区 ⇒ 排版被撑破且「会话内无法切换模型」。这同时解释了「重启后」这个前置条件和「反复重试都不成功」。

预期与建议

  1. 错误展示不进排版流:给 .cc-widget-error 补样式(max-width + text-overflow:ellipsis/white-space:nowrap + title 全文),或改为中控区之上/之下的固定浮层或 toast,任何长度都不推动同排控件布局;失败后可关闭/可自动消退。
  2. 区分「不可切换」与「切换失败」model_surface === None 时控件应为禁用/只读态并给出简短说明(类似既有 ModelSurface::None = 会话模型只读 的产品语义),而不是让用户反复点到长报错;结构化错误码(model_not_advertised / 无模型面)应保留在日志/diagnostics,长列表不进 UI 文案。
  3. 根因侧需确认:历史会话恢复路径(revive/load)是否会重新取得模型面;若不会,需要在恢复链路上补齐,或由后端向前端发布「本会话模型不可切换」的显式状态。
  4. 验收建议
    • L2:注入 setModel 失败返回值,断言中控区其它控件位置/行高不变,错误以非内联方式呈现且可关闭。
    • L3:真实重启 → 打开历史会话 → 模型按钮在无模型面时为禁用/只读态;正常会话下切换成功。

未验证声明

本 issue 的症状描述来自报告人实测;源码链条部分为对远端 main f27c1c8 的静态阅读与代码搜索(含 .cc-widget-error 无 CSS 的仓库级 grep),未在本机复现 GUI 现象,也未构造运行时证据。「排版错乱的具体表现」与「失败根因是 model_surface 未刷新」属推断,需在修复前用可运行环境确认。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions