Cli agent block fix#286
Conversation
|
这个功能对于企业开发很有需要,大部分工作在跳板机完成,望审核后合并~ |
zerx-lab
left a comment
There was a problem hiding this comment.
(详见 inline comments 和下方总结 comment)
— 由 Claude Routine 自动生成;如需复评请 @ 维护者人工触发。
Generated by Claude Code
| ) -> Vector2F { | ||
| // 参考 Warp 的外层约束形态:由 block list 先给浮窗足够大的布局上限, | ||
| // 再交给 CLISubagentView 内部 Resizable 处理最终拖拽尺寸。 | ||
| let max_width = (available_size.x() * CLI_SUBAGENT_MAX_WIDTH_RATIO |
There was a problem hiding this comment.
Bug(边界条件):极窄窗口下外层布局约束上限可能小于内层 Resizable 的 min,产生冲突
cli_subagent_layout_max_size 中:
let max_width = (available_size.x() * CLI_SUBAGENT_MAX_WIDTH_RATIO - CLI_SUBAGENT_HORIZONTAL_MARGIN).max(0.);对宽度约 375px 的窗口,max_width ≈ 359.5px,而 cli.rs 内层 Resizable 的 min bound 来自 cli_subagent_width_bounds(window_width) 返回的 (MIN_RESIZABLE_WIDTH=360, ...) ——外层约束上限 < 内层 min,两者冲突。
测试 cli_subagent_resize_width_bounds_do_not_drop_below_panel_minimum 只验证了 min=max=360 的情况,没有覆盖与外层 layout max(305.6,窗口=320)的关系。
SSH 跳板机场景下用户可能在较小窗口中运行,建议在 cli_subagent_width_bounds 中接受外层布局 available width 并以此为 max 的上限,或在 CLISubagentView::render() 里把外层 layout constraint 传给 Resizable 的 bounds callback,使两者的上下限保持一致。
Generated by Claude Code
There was a problem hiding this comment.
Question:EventHandler.with_always_handle() 在滚动到底部边界时会意外解除 auto-scroll 钉住状态
CLISubagentView::render() 末尾:
let content = EventHandler::new(clipped_content)
.with_always_handle()
.on_scroll_wheel(|ctx, _app, _, _| {
ctx.dispatch_typed_action(CLISubagentAction::ConversationScrollManuallyMoved);
cli_subagent_conversation_scroll_wheel_dispatch_result()
})
.finish();NewScrollable 设置了 with_propagate_mousewheel_if_not_handled(true):当内容已经滚到底部,再向下滚动时,scroll 事件「未被消费」→ 向上冒泡 → 外层 EventHandler 触发 → ConversationScrollManuallyMoved 被 dispatch → is_conversation_scroll_pinned_to_bottom = false。
场景:内容正在流式输出(持续 auto-scroll 到底),用户下意识再往下滚一下(已在底部)→ 解钉 → 新输出不再自动跟踪,用户需手动拖回底部。
是否可以检测「scroll 事件实际上是向下的且内容已在底部」时不解钉?或者在 ConversationScrollManuallyMoved handler 中加一个「当前是否已在底部」的判断?
Generated by Claude Code
Review 总结倾向:Comment(非阻塞,建议处理 scroll 边界行为后合并) 功能目标(SSH 跳板机模式下 CLI agent 浮窗可拖拽、可查看对话历史)在核心逻辑上实现完整: 阻塞问题无严格阻塞,但以下两点建议修复后合并:
建议
看起来不错的地方
— 由 Claude Routine 自动生成;如需复评请 @ 维护者人工触发。 Generated by Claude Code |
|
ssh连跳板机模式下agent cli |
维护者复审:FIX-NEEDED(阻塞,涉及安全)可缩放浮窗 + 历史保留的整体实现是站得住的(resize 钳制正确、滚轮事件派发顺序正确、AIBlockModelImpl 为轻量句柄无内存泄漏、无新增 TerminalModel::lock() 死锁风险)。但发现一个密钥脱敏(secret redaction)索引错位的阻塞缺陷: 根因
后果(当
修复方案(二选一):
请补充对应的单元/集成测试(多轮 + 开启脱敏)覆盖该路径后再合并。本仓库无 PR CI,review 是唯一门槛,这一项涉及密钥泄露,必须先修复。 |
已提交新的修复,请重新审核 |
SSH 跳板机场景的 agent CLI 浮窗走 AltScreenElement 路径,浮窗内多轮 对话气泡(query/output/action)平铺在同一个 Flex::column 里,每个气泡是 独立的 SelectableArea。 根因: - Flex::dispatch_event 会把同一个鼠标事件广播给所有子元素,命中不 break; - SelectableArea::dispatch_event 在 LeftMouseDown/LeftMouseUp 时无条件调用 invoke_selection_handler,即使鼠标不在该气泡内(框架为"点击空白清选"设计); - cli.rs 回调入口无条件调用 clear_selection_handles_for_active_area,会清掉 同组其它 index 的 handle。 三者叠加,导致在 block N 上 down/up 时,前面未命中气泡的回调先执行,用自己 的 index 把 block N 的选择清掉: - 前/中 block:被后续未命中气泡的回调误清 → 无法保持选中; - 最后一个 block:LeftMouseUp 广播时前面的气泡先清掉它,松手即失选。 修复:在三处 SelectableArea 回调(query/output/action)入口加 is_this_area_active 判定 —— 只有本区域确实参与选择时(is_selecting() 为 true 或 selection 非空) 才清掉其它同级区域的旧选择。Flex 广播给未命中气泡的回调不再误清命中区域。 该修复对 alt-screen(SSH 跳板机)和 block_list(主对话区)两条路径都生效, 不触碰框架层(selectable_area.rs / flex)与现有 WIP。
之前主对话区(block_list 路径)在开启 "Hide responses" 时只隐藏 AI 输出,仍保留用户提问气泡,导致界面只藏输出不藏输入,与 CLI 浮窗 (commit 6878548)的行为不一致。 新增 common::should_render_query_and_header,在原有判断基础上增加 !should_hide_responses 条件,view_impl 在渲染 query/header 以及 contains_user_query_and_is_not_pin_to_top 判断时统一使用该函数。 带 2 个单元测试覆盖隐藏/显示两种场景。
|
对气泡的一些交互做了更多细节修正 |

Description
ssh连跳板机模式下agent cli浮窗功能增强,现在可以随意拖放大小,防止显示不完整;同时可以看到历史对话记录,之前会因为下一轮对话覆盖前一轮的显示。
Testing
已经打包做过测试,没有问题了,可以直接合并~
Server API dependencies
Agent Mode
Changelog Entries for Stable
CHANGELOG-NEW-FEATURE: {{text goes here...}}
CHANGELOG-IMPROVEMENT: {{text goes here...}}
CHANGELOG-BUG-FIX: {{text goes here...}}
CHANGELOG-BUG-FIX: {{more text goes here...}}
CHANGELOG-IMAGE: {{GCP-hosted URL goes here...}}
CHANGELOG-OZ: {{text goes here...}}