Skip to content

Stop dropping steers routed to a non-active conversation, and clear the input after a CLI-harness follow-up - #14682

Open
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/remote-2486-steer-drop-and-input-clear
Open

Stop dropping steers routed to a non-active conversation, and clear the input after a CLI-harness follow-up#14682
warp-agent-staging[bot] wants to merge 2 commits into
masterfrom
factory/remote-2486-steer-drop-and-input-clear

Conversation

@warp-agent-staging

Copy link
Copy Markdown
Contributor

Description

Steering a running Warp session was unreliable in two ways (REMOTE-2486): a mid-session steer was sometimes refused and then never completed or silently dropped, and when it did go through the message was left sitting in the input. Both symptoms trace back to the same place — a send path that never reaches BlocklistAIControllerEvent::SentRequest, which is what both dispatches the request and clears the input.

1. A steer routed to a non-active conversation was dropped on the floor.
BlocklistAIController::send_query cancelled progress on the terminal surface's active conversation — the one most recently streamed — while sending the query to the target conversation. Those are explicitly different concepts (BlocklistAIHistoryModel::active_conversation_id documents that follow-up targeting uses context_model.selected_conversation_id instead), and they diverge in practice: a shared-session participant's steer is routed to whichever conversation its server_conversation_token maps to, a fired queued row targets the conversation it was queued on, and a passive request registers a stream without ever marking its conversation active.

When they diverged, the target's response stream stayed in flight, so send_request_input hit its in-flight guard and bailed with Not sending AI input because there is an in-flight request. That error is swallowed by send_query (report_error! only) — no toast, no queue row, no retry. The prompt was gone, and because SentRequest never fired the input was never cleared either. send_query now also cancels the target conversation's progress when it differs from the active one.

2. A follow-up handed to a third-party CLI harness never cleared the shared input.
On the sharer, NetworkEvent::AgentPromptRequested writes the prompt straight to the CLI agent's PTY when a third-party harness (e.g. Claude Code) is running, then returns. That branch bypasses the Oz dispatch entirely, so no SentRequest fires and nothing calls system_clear_buffer — which is the only thing that emits the CRDT delete ops clearing the shared input for the sharer and every viewer. The requesting viewer gets an optimistic display-only empty ephemeral from AgentPromptRequestInFlight, but that ephemeral is discarded on materialization, so the original text reappeared as soon as they typed again. The sharer now unfreezes and clears the input explicitly on that branch, matching what the Oz-harness branch gets for free.

Linked Issue

REMOTE-2486 (carries triage-done; triage recorded spec_recommended: false, so no spec was written).

Testing

Two regression tests, each failing before the corresponding fix and passing after.

  • ai::blocklist::controller::tests::steering_a_non_active_conversation_dispatches_the_request — puts an in-flight stream on the conversation being steered while a different conversation is the surface's active one, sends a user query into the steered conversation, and asserts a SentRequest was emitted. Reverting the send_query change makes it fail with the exact drop path: panicked at app/src/ai/blocklist/controller.rs:2439: Not sending AI input because there is an in-flight request.
  • terminal::input::tests::clear_buffer_after_shared_session_agent_prompt_empties_the_shared_input — asserts the sharer-side sequence run after the prompt is written to the CLI agent's PTY leaves the shared input empty. It pairs with the existing unfreeze_agent_input_does_not_clear_buffer, which documents that unfreezing alone deliberately leaves the text behind — that gap is what left the prompt in the input.

Repository checks run from the repo root:

  • ./script/format --check — pass

  • ./script/check_no_inline_test_modules — pass

  • cargo clippy -p warp --all-targets --tests -- -D warnings — pass

  • cargo nextest run -p warp scoped to every touched module (ai::blocklist::*, terminal::input*, terminal::local_tty::*, terminal::view::*, terminal::shared_session::*) — 1330 tests, 1328 passed. The 2 failures (terminal::input::decorations::tests::test_decorations_with_multibyte_chars, terminal::input::tests::test_histignorespace_support_in_zsh) reproduce identically on unmodified master in this sandbox and are environment gaps, not regressions.

  • I have manually tested my changes locally with ./script/run

Screenshots / Videos

Visual proof of the changed paths is outstanding — please confirm the rendered behavior before merging.

The desktop build from this branch was compiled and launched successfully on a headless runner (screenshots below show the app running from this branch), but neither changed path can be reached there. Both require a signed-in account plus a live shared session with a second executor participant, and one of them additionally requires a third-party CLI harness running on the sharer. The sandbox has no account credentials and no second client, so the app opens straight into a signed-out plain terminal with no agent conversation. Capturing proof on the wrong surface would be worse than none, so it was not attempted.

Suggested manual check for a reviewer with a real session:

  1. Share a session and have an executor viewer send a follow-up while the sharer's agent is mid-turn on a conversation that is not the sharer's most recently streamed one — the steer should land instead of vanishing.
  2. Repeat with a third-party CLI harness (e.g. Claude Code) running on the sharer — the input should be empty on both sides after the follow-up is accepted.

Agent Mode

  • Warp Agent Mode - This PR was created via Warp's AI Agent Mode

Originating thread: https://warpdev.slack.com/archives/C09E37H1NMA/p1785807618502619

Computer-use screenshots

The launched Warp debug build from this branch, showing a terminal window with a "bash" tab and an empty command input block at the bottom.
The same window with "hello" typed into the command input block — a plain signed-out terminal with no agent conversation, i.e. neither changed path is reachable here.

Conversation: https://staging.warp.dev/conversation/eb5dd26c-b524-4297-ab5c-76d6850392ef
Run: https://oz.staging.warp.dev/runs/019fca77-91da-78d8-a7fd-204bfeb38e0d

This PR was generated with Oz.

…he input after a CLI-harness follow-up

Two defects made steering a running Warp session unreliable (REMOTE-2486).

1. `send_query` cancelled progress only on the terminal surface's *active*
   (most recently streamed) conversation, while sending the query to the
   *target* conversation. When those diverge — a shared-session steer routed by
   server token, a fired queued row, or a conversation whose stream started
   passively — the target's stream stayed in flight, `send_request_input`
   refused the query ("Not sending AI input because there is an in-flight
   request") and it was discarded with no user-visible error. No `SentRequest`
   fired either, so the input was never cleared. The target conversation's
   progress is now cancelled as well.

2. A shared-session follow-up forwarded to a third-party CLI harness's PTY
   never reaches the Oz dispatch that emits `SentRequest`, so nothing issued
   `system_clear_buffer` and the submitted prompt stayed in the shared CRDT
   input for the sharer and the requesting viewer. The sharer now unfreezes and
   clears the input explicitly on that branch.

Co-Authored-By: Warp <agent@warp.dev>
Co-Authored-By: Warp Agent <agent@warp.dev>
@cla-bot cla-bot Bot added the cla-signed label Aug 4, 2026
@warp-agent-staging
warp-agent-staging Bot marked this pull request as ready for review August 4, 2026 02:44

@warp-agent-staging warp-agent-staging Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overview

This PR fixes the non-active-conversation steering drop and explicit shared-input clearing for the third-party CLI-harness path. The code change is independently reviewable, but a real shared-session recording remains required before acceptance.

Concerns

No reviewer is assigned because the requester’s Slack identity could not be resolved; a human must assign one before merge. The PR description also incorrectly says the issue carries triage-done; that cleanup and the missing wiring-level regression test are being relayed to implementation.

Verdict

Checks: CI ✅ (all required checks) · local presubmit ⚠️ (sandbox killed the test compilation; CI completed the full matrix)
Found: 0 critical, 1 important, 0 suggestions, 2 questions

Request changes

Review run

https://oz.staging.warp.dev/runs/019fcaab-4ac5-7544-a90d-2f0c0abc579c

// optimistic display-only clear is materialized, for the requester too.
view.input().update(ctx, |input, ctx| {
input.unfreeze_agent_input(false, ctx);
input.clear_buffer_after_shared_session_agent_prompt(ctx);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ [QUESTION] The proposed two-step manual procedure correctly covers both affected paths, but the attached screenshots show only a signed-out terminal. Please have a reviewer with a live shared session run it and attach a short recording showing (1) the mid-turn steer is delivered and (2) a CLI-harness follow-up clears the input for both participants before this merges.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant