Commit Graph

12 Commits

Author SHA1 Message Date
Eva 089b437b35 fix(tui): stop queued dispatch after session close 2026-08-16 06:26:37 -07:00
Teknium 4ac12d53fb fix(tui_gateway): keep steer-mode fall-through bursts queued instead of interrupting
Desktop/TUI busy-input `steer` mode escalated any fall-through message
(steer() rejected, raised, or a non-steerable multimodal payload) into a
hard interrupt of the live turn. AIAgent.interrupt() also clears the
pending steer buffer, so a burst of user messages sent while the agent
was busy could be silently destroyed: earlier successfully-steered
messages were dropped from the buffer and the live turn was killed.

Steer-mode fall-throughs now keep pure queue semantics: preserved FIFO
in queued_prompt/queued_prompts and drained on turn end, per the
existing steer contract. Only explicit `interrupt` mode still fires
_interrupt_busy_session. No synthetic user messages are injected
mid-loop; accepted steers continue through the sanctioned OOB
steer-marker path.

Regression tests cover: rejected steer queues without interrupting,
steer exception falls back to queue, multimodal payload queues, a mixed
burst preserves accepted steers plus the queued fall-through, and a
fall-through burst drains all texts FIFO after turn end.

Fixes #86134
2026-08-14 20:24:06 -07:00
StanleyStetson 3995fd434c fix(tui_gateway): stop replaying live-turn user text after redirect
A mid-turn correction (Desktop session.redirect / busy-input interrupt redirect)
must not leave a server-queue self-copy of the live inflight user prompt.
Otherwise post-turn _drain_queued_prompt restarts that original text as a
fresh agent turn after Q completes (#84417).

Scrub text-only self-duplicates of inflight_turn.user on successful
redirect/steer, refuse admitting them in _enqueue_prompt, rewrite merged
"{P}\n\n{Q}" slots to Q-only, bump _queued_prompt_generation on compression
session rotation, and restore the claimed queue envelope when generation
cancels mid-drain. Stabilize profile-scoped agent-build unit tests under CI load.

Fixes #84417
2026-08-14 20:24:06 -07:00
fyzanshaik d50858584c fix(tui): preserve queued image ownership 2026-08-01 15:58:42 +05:30
Teknium 6b81590c55 test: prune low-value tests suite-wide (wave 1) — 46,820 → 28,106 test functions
Systematic prune per AGENTS.md test policy, one pass over every major
test tree (gateway, hermes_cli, tools, agent, run_agent, plugins, cli,
cron, tui_gateway, honcho/openviking, root-level):

- DELETE: source-reading tests (read_text/getsource on prod files),
  change-detector tests (exact catalog counts, model-name snapshots,
  config version literals), mock-echo tests (assert a mock returns what
  it was told), assertion-free/trivial tests, near-duplicate
  parametrizations (boundaries + one representative kept), async/sync
  twin duplicates, cosmetic within-file variations.
- KEEP (mandatory): security/redaction/approval guards, message-role
  alternation invariants, prompt-caching/deterministic-call-id
  invariants, issue-number regression tests (deduped), E2E tests.
- 6 test files deleted outright (script-style/no-assert or fully
  redundant); conftest.py, fakes/, fixtures/ untouched.
- tests/acp/conftest.py added: autouse fixture stubs the live
  models.dev/GitHub/Copilot/Anthropic inventory fetches that ACP server
  tests performed on every session create — test_server.py 147s → 3.4s,
  and the tests are now genuinely hermetic.
- Sleep-based slowness shrunk where safe (codex_ttfb_watchdog,
  compression_concurrent_fork, etc.); no wall-clock assertion tightened.

Verification: full hermetic suite via scripts/run_tests.sh —
2439 files, 31,130 tests passed, 0 failed, 0 flaky retries, 315s wall
(baseline: 583s wall, 13,564s subprocess CPU).
2026-07-29 13:10:23 -07:00
atakan g 3d30232eba fix(delegate): isolate async batches from parent interrupts
Detached background delegation batches (_batch_runner) no longer honor
the foreground parent's interrupt flag — a busy-submit interrupt in the
TUI/desktop previously fabricated 'interrupted' results for background
children that should outlive the turn. Explicit cancellation still works
via _batch_interrupt.

Rebased onto current main from PR #65040; both interrupt-suppression
regression tests aligned with the current _session test helper.

Original work by @AtakanGs in #65040.
2026-07-28 14:20:10 -07:00
Brooklyn Nicholson ab68c5efec fix(gateway): a queue drain never becomes a live-turn correction
The desktop's queue promises "run this AFTER the current turn", but the
promise broke on a race the user can't see: a drain that fired when the
client observed idle while the server was still unwinding the turn landed
in _handle_busy_submit, which applied busy_input_mode — redirecting or
interrupting the live turn with text the user explicitly queued. That's
why force-sending the queue felt like a dice roll: the same gesture
steered, interrupted, or queued depending on a millisecond settle race.

prompt.submit now carries queued:true on every fromQueue drain (composer
auto-drain, send-now, background drain), and the gateway's busy path
honors it by forcing queue semantics — never steer, never redirect,
never interrupt. Lose the race and the text simply waits its turn, which
is what queueing meant all along.

Covered on both sides: a gateway test proving a queued drain cannot touch
redirect/steer/interrupt on the live agent, and the desktop drain tests
now assert the flag rides every prompt.submit shape (direct, background,
resume-retry).
2026-07-28 01:48:08 -05:00
Brooklyn Nicholson 2dd4cbbe61 fix(tui_gateway): keep the original prompt when a redirect corrects a turn
An accepted mid-turn redirect wrote its correction over inflight_turn["user"].
That field is the only user text session.resume can replay, so the prompt that
started the turn was gone the moment the user typed again while it ran. On the
next resume the client rebuilt the thread without it.

Record corrections in their own list instead, alongside the prompt. Renamed
_replace_inflight_user to _record_inflight_correction now that it appends.
_start_inflight_turn rebuilds the dict wholesale, so corrections cannot leak
into a later turn.
2026-07-26 19:43:23 -05:00
ethernet 6d17b2a593 fix(desktop): preserve active correction on warm resume (#69725)
Update the gateway's live turn projection after an accepted correction so a warm session resume does not add the stale original prompt beside the persisted correction.

Cover the inference-time correction path end to end and assert both redirect entry points refresh the live user text.
2026-07-22 21:53:56 -04:00
Brooklyn Nicholson 34d0de80e6 feat(surfaces): route busy-input corrections through active-turn redirect
The default `busy_input_mode: interrupt` now redirects the live turn instead
of hard-stopping it and re-queuing a fresh turn, wired consistently across
every first-party surface via the shared core primitive.

- CLI, gateway (busy + PRIORITY paths), TUI (`_handle_busy_submit`), desktop
  (`session.redirect` RPC), and ACP call `redirect()` when the agent advertises
  `_supports_active_turn_redirect`, and fall back to the proven interrupt +
  next-turn queue for older runtimes.
- Redirect is gated to plain text with no attachments: captioned or
  attachment-bearing events (including adapters that classify unknown media as
  `TEXT`) stay queued so media is never dropped.
- ACP `cancel()` records the interrupted prompt, sets its cancel event, and
  hard-stops the agent while holding `runtime_lock`, closing the
  cancel-then-correct ordering gap; connection I/O happens after the lock is
  released.
- Desktop appends the correction as a real user transcript message so the live
  view matches the durable history after reload.
- `/busy` help, onboarding hints, and the new `session.redirect` RPC describe
  the redirect behavior; `/stop` remains the hard stop.
2026-07-22 12:10:58 -05:00
UnathiCodex e45d12642d fix(tui_gateway): prevent resume stalls during submit and teardown (#66573)
* fix(tui_gateway): keep busy submits resume-safe

* chore: map contributor email

* fix(tui_gateway): release resume lock before teardown
2026-07-18 14:51:06 -04:00
Brooklyn Nicholson 70319626a9 fix(tui_gateway): queue mid-turn prompts instead of dropping them on a busy retry
A prompt sent while a turn was in flight got rejected with 4009 "session busy",
which pushed clients (the desktop app) into a deadline-bounded busy-retry. When
turn teardown outlived that deadline — e.g. the user hits stop while a slow,
non-interruptible tool (web_search, read_file, an MCP call) is mid-flight, since
the sequential executor only checks the interrupt flag between tools — the
resubmitted message was silently dropped: "it just doesn't listen".

Wire the previously-dead display.busy_input_mode config into prompt.submit:
instead of rejecting, apply the policy and queue the message to run as the next
turn (drained in run()'s tail, ahead of goal/notification follow-ups). Modes:
interrupt (default) interrupts the live turn so it winds down promptly then runs
the queued message; queue runs it after the current turn finishes; steer injects
it into the live turn when accepted, else queues. The queued slot pins the
sender's transport and losslessly merges a second arrival. No client deadline,
no dropped sends.
2026-06-25 12:29:49 -05:00