问题
重启应用后打开历史会话 ,点击中控区(Control Center)的「模型」控件切换模型会失败,并且失败信息会内联渲染在中控区自身的排版流里 :中控区被报错文本填满、排版错乱(状态栏控件被挤开/换行),且在会话内反复重试始终无法正常切换模型。
同一个渲染点(cc-widget-error)也被权限模式控件复用,故权限模式切换失败应有同样表现。
复现(报告人描述)
重启 Pylon。
在历史会话列表中打开一个已有会话。
点击中控区的 model 按钮 → 选择另一个模型。
预期:模型切换生效(或给出可关闭的失败提示,排版不受影响)。
实际:中控区出现报错文本并把排版撑乱;会话内 model 切换无法成功,重试仍失败并重复渲染错误。
环境
Windows(报告人环境),main f27c1c81d5b36f0b07cdd451d7dd26932389ae9f。
报告时间与 perf(frontend): 优化显示调度并整合已验证的结构简化 #50 (refactor/frontend-scheduling,同日合并)同日,未做 A/B 对照 ,因此不能判定是否为该次合并引入的回归。
报告人未提供 Pylon 自身版本号与 agent 类型,修复前建议补齐。
证据:源码链条(静态阅读远端 main f27c1c8,未经运行时验证)
1. 失败文本被直接内联到中控区控件里
WorkbenchWidgets.solid.tsx#L122 :SolidModelWidget 在返回的 .solid-model-widget 内、紧邻模型控件之前 渲染 <span class="cc-widget-error" role="alert">{message()}</span>。
同文件#L92 :choose() 里 if (!result.ok) setError(result.error || '模型切换失败'),result.error 是后端原始 message(见下)。
同文件#L311 :权限模式控件复用同一 class/同一内联位置。
错误只在「下次切换成功」(#L93)或「会话 id 变化」(#L56-L65)时清空——因此在同一会话内失败一次后,文本会持续 留在中控区,符合「被报错信息填满」。
2. .cc-widget-error 在整个仓库里没有任何 CSS 规则
对 f27c1c8 的 ControlCenter.css、WorkbenchChrome.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-widget 为 display: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#L144 :SessionInfo::new 默认 model_surface: ModelSurface::None。
同文件#L233-L238 :model_surface 只在 apply_session_response(即 session/new、session/load 响应形状判定)时刷新 ;apply_config_options(#L241-L268)亦仅在 agent 全量宣告 model 选项时刷新,否则把失效的 ConfigOption 面降级为 None。
同文件#L1053-L1057 :resolve_model_switch_target 在 ModelSurface::None 时直接返回 PylonError::Protocol("model switching unavailable: agent advertises no model surface")。
同文件#L1065-L1073 :validate_model_advertised 抛 model_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 以长字符串拒绝 ⇒ 前端把它内联进中控区 ⇒ 排版被撑破且「会话内无法切换模型」。这同时解释了「重启后」这个前置条件和「反复重试都不成功」。
预期与建议
错误展示不进排版流 :给 .cc-widget-error 补样式(max-width + text-overflow:ellipsis/white-space:nowrap + title 全文),或改为中控区之上/之下的固定浮层或 toast,任何长度都不推动同排控件布局;失败后可关闭/可自动消退。
区分「不可切换」与「切换失败」 :model_surface === None 时控件应为禁用/只读态并给出简短说明(类似既有 ModelSurface::None = 会话模型只读 的产品语义),而不是让用户反复点到长报错;结构化错误码(model_not_advertised / 无模型面)应保留在日志/diagnostics,长列表不进 UI 文案。
根因侧需确认 :历史会话恢复路径(revive/load)是否会重新取得模型面;若不会,需要在恢复链路上补齐,或由后端向前端发布「本会话模型不可切换」的显式状态。
验收建议 :
L2:注入 setModel 失败返回值,断言中控区其它控件位置/行高不变,错误以非内联方式呈现且可关闭。
L3:真实重启 → 打开历史会话 → 模型按钮在无模型面时为禁用/只读态;正常会话下切换成功。
未验证声明
本 issue 的症状描述来自报告人实测;源码链条部分为对远端 main f27c1c8 的静态阅读与代码搜索(含 .cc-widget-error 无 CSS 的仓库级 grep),未在本机复现 GUI 现象 ,也未构造运行时证据。「排版错乱的具体表现」与「失败根因是 model_surface 未刷新」属推断,需在修复前用可运行环境确认。
问题
重启应用后打开历史会话,点击中控区(Control Center)的「模型」控件切换模型会失败,并且失败信息会内联渲染在中控区自身的排版流里:中控区被报错文本填满、排版错乱(状态栏控件被挤开/换行),且在会话内反复重试始终无法正常切换模型。
同一个渲染点(
cc-widget-error)也被权限模式控件复用,故权限模式切换失败应有同样表现。复现(报告人描述)
环境
f27c1c81d5b36f0b07cdd451d7dd26932389ae9f。refactor/frontend-scheduling,同日合并)同日,未做 A/B 对照,因此不能判定是否为该次合并引入的回归。证据:源码链条(静态阅读远端 main
f27c1c8,未经运行时验证)1. 失败文本被直接内联到中控区控件里
SolidModelWidget在返回的.solid-model-widget内、紧邻模型控件之前渲染<span class="cc-widget-error" role="alert">{message()}</span>。choose()里if (!result.ok) setError(result.error || '模型切换失败'),result.error是后端原始 message(见下)。2.
.cc-widget-error在整个仓库里没有任何 CSS 规则对
f27c1c8的ControlCenter.css、WorkbenchChrome.css以及全仓库(排除node_modules/、target/、dist/)grepcc-widget-error:只命中上面两处 TSX,无任何样式定义。即它是未加样式控制的裸文本:.cc-widget.cc-natural { width:max-content !important; height:auto !important; min-width:0 !important; }——控件宽度按内容取max-content,没有上限。.cc-widget为display:flex; overflow:visible;,.cc-natural > *为flex:none(不收缩)。.cc-status-row { display:flex; flex-wrap:wrap; }(footer 布局下对应.cc-footer-status-row,L42)。⇒ 一条不被截断、不可收缩的长文本会把所在 widget 撑到内容宽度,并把同排其它状态控件挤开/换行——与「中控区排版错乱」一致。(该机理为静态推断,具体变形形态需在有 GUI 的机器上复现确认。)
3. 失败信息本身可能很长,且切换在「模型面未宣告」时必然被拒
SessionInfo::new默认model_surface: ModelSurface::None。model_surface只在apply_session_response(即session/new、session/load响应形状判定)时刷新;apply_config_options(#L241-L268)亦仅在 agent 全量宣告 model 选项时刷新,否则把失效的 ConfigOption 面降级为None。resolve_model_switch_target在ModelSurface::None时直接返回PylonError::Protocol("model switching unavailable: agent advertises no model surface")。validate_model_advertised抛model_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以长字符串拒绝 ⇒ 前端把它内联进中控区 ⇒ 排版被撑破且「会话内无法切换模型」。这同时解释了「重启后」这个前置条件和「反复重试都不成功」。预期与建议
.cc-widget-error补样式(max-width+text-overflow:ellipsis/white-space:nowrap+title全文),或改为中控区之上/之下的固定浮层或 toast,任何长度都不推动同排控件布局;失败后可关闭/可自动消退。model_surface === None时控件应为禁用/只读态并给出简短说明(类似既有ModelSurface::None = 会话模型只读的产品语义),而不是让用户反复点到长报错;结构化错误码(model_not_advertised/ 无模型面)应保留在日志/diagnostics,长列表不进 UI 文案。setModel失败返回值,断言中控区其它控件位置/行高不变,错误以非内联方式呈现且可关闭。未验证声明
本 issue 的症状描述来自报告人实测;源码链条部分为对远端 main
f27c1c8的静态阅读与代码搜索(含.cc-widget-error无 CSS 的仓库级 grep),未在本机复现 GUI 现象,也未构造运行时证据。「排版错乱的具体表现」与「失败根因是model_surface未刷新」属推断,需在修复前用可运行环境确认。