Skip to content

Standalone aft_search cannot be cancelled and blocks the whole bridge while waiting #281

Description

@trim21

Problem

Over the standalone NDJSON transport, a semantic_search request can neither be cancelled by the client nor avoided blocking sibling requests.

1. Search runs inline on the single request thread

The NDJSON main loop dispatches synchronously (crates/aft/src/main.rs:314, dispatch_outcome called inline). With AFT_WAIT_FOR_SEMANTIC_READY=1 (set by harness plugins so the first search doesn't return partial results), wait_for_semantic_index_before_search (main.rs:914-953) sleeps in a loop for up to AFT_WAIT_FOR_SEMANTIC_READY_MS (600s in the pi plugin) while the index builds. During that window every other command — status polls, outline, other tool calls — queues behind it, because they all share the one request thread. A big-repo cold build (~2h) means every search during the build hangs ~10 minutes and then errors with semantic_index_timeout, and takes the rest of the bridge down with it.

2. Cancellation infra exists but isn't reachable standalone

search_cancellation_requested() (crates/aft/src/commands/semantic_search.rs:191 → executor current_job_cancelled) is only wired for the subc/executor job path (route-closed cancellation). There is no wire-level cancel command for NDJSON: when the client gives up, the child keeps waiting/embedding to completion. Harness-side, the best a client can do is abandon the request locally — the search keeps occupying the request thread.

Proposal

  1. Route long-running read commands (semantic_search, maybe others) through deferred dispatch on the existing executor so JobCancellation applies; keep the response delivered via the pending-response path already used by inspect.
  2. Add a wire cancel_request { id } command for standalone so clients can propagate user aborts.
  3. Honor cancellation in wait_for_semantic_index_before_search (wake the 250ms sleep loop on cancel) and in the query-embed path.

Even without (2), (1) alone removes the collateral damage: a stuck search would no longer block status polls and sibling tool calls.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions