环境
- Eta 3.0.4(versionCode 2026091202,main,最后一次提交 2026-09-12)
- Android 15(ColorOS);与 Root 无关,任意对话入口都能复现
复现步骤
- 发一条执行时间较长的任务(例如让 Eta 跑终端命令,或检索相册/日历)。
- 任务运行期间在输入框里打字。
- 看右下角圆形按钮:显示为「停止」,点了只会中断任务。
- 按输入法回车:只换行,不会发送。
期望行为
运行中可以追加指令:消息排到当前 turn 结束后注入,不取消正在执行的模型请求或工具批次,也不必先停止再重发。行为对齐 Codex / Claude Code 的 steering。
实际情况
ui/components/AgentChatInputBar.kt:isStreaming 时圆形按钮的 onClick 被换成 onStop,图标变停止方块;输入框是 imeAction = ImeAction.Default,没有 onSend。
ui/app/AgentAppState.kt:sendCurrentMessage() 开头遇到 homeState.isStreaming 直接 return,既不排队也不提示。
- 底层能力已经存在:
AgentRunController.steer() 会把文本排进队列,AgentLoop 在 turn 边界用 pollSteeringMessage() 注入。但唯一入口是悬浮光球展开气泡里的「补充」,而光球只在运行 tap / scroll / observe_screen 这类前台驱动工具时才出现(AgentOverlayVisibilityPolicy);终端、文件、网页类任务全程没有可输入的地方。
AgentRuntimeClient / AgentRuntimeWire 没有对应的跨进程消息,所以对话页在协议层也够不到这条能力。另外「新开一个对话发消息」不可行:AgentRuntimeService.startRun() 开头的 activeSession?.controller?.cancel() 会取消当前任务。
建议方案
- wire 层加一条补充指令消息(请求 + 接受/拒绝应答)。
AgentRuntimeClient 暴露 steerRun(runId, text);服务端只对 runId 匹配且仍在 RUNNING 的 OP_CHAT 会话入队,其余情况明确拒绝并回原因。
- 对话页运行时把按钮拆成「补充 + 停止」,并让 IME 动作在运行时切到 Send;数字助理面板同样放开执行中的输入。
- 入口收到拒绝(run 已结束或已进入收尾)时退回一次普通发送,避免静默丢弃用户输入。
环境
复现步骤
期望行为
运行中可以追加指令:消息排到当前 turn 结束后注入,不取消正在执行的模型请求或工具批次,也不必先停止再重发。行为对齐 Codex / Claude Code 的 steering。
实际情况
ui/components/AgentChatInputBar.kt:isStreaming时圆形按钮的 onClick 被换成onStop,图标变停止方块;输入框是imeAction = ImeAction.Default,没有onSend。ui/app/AgentAppState.kt:sendCurrentMessage()开头遇到homeState.isStreaming直接 return,既不排队也不提示。AgentRunController.steer()会把文本排进队列,AgentLoop在 turn 边界用pollSteeringMessage()注入。但唯一入口是悬浮光球展开气泡里的「补充」,而光球只在运行tap/scroll/observe_screen这类前台驱动工具时才出现(AgentOverlayVisibilityPolicy);终端、文件、网页类任务全程没有可输入的地方。AgentRuntimeClient/AgentRuntimeWire没有对应的跨进程消息,所以对话页在协议层也够不到这条能力。另外「新开一个对话发消息」不可行:AgentRuntimeService.startRun()开头的activeSession?.controller?.cancel()会取消当前任务。建议方案
AgentRuntimeClient暴露steerRun(runId, text);服务端只对 runId 匹配且仍在RUNNING的OP_CHAT会话入队,其余情况明确拒绝并回原因。