fix(ui): run /ask off the request path so the composer clears immediately (LC-676) #638

Merged
longjacksonle merged 1 commit from fix/LC-676-ask-async-composer into main 2026-08-04 21:14:55 +02:00

Follow-up to LC-676 (the composer half). This is a SINGLE-commit PR so it can't lose a trailing commit like #636/#637 did.

Why a new PR

The async-ask commit (483646b) was pushed onto the #637 branch, but #637 was merged at its first commit (87befc8, the retrieval fix) before the async commit was picked up - the same drop that happened to #636. So the retrieval fix landed but the composer fix did not. Cherry-picked here as its own commit.

Symptom (1.png, 2.png)

After sending /ask ..., the composer keeps the typed text and the slash argument-hint stays up - for the whole answer duration - and the "The assistant is thinking..." placeholder shows in the meantime.

Root cause

handle_ask posted the placeholder and then ran the LLM synchronously, holding the /ask POST open for the whole multi-second local-model answer. The composer clears its text and dismisses the slash hint on the POST's return, so both hung until the answer resolved.

Fix

handle_ask now posts the placeholder and returns immediately, running retrieval + the LLM in a spawned task that replaces the placeholder body in place when ready. /ask answers with a fast 204 - the composer clears its text and slash hint at once - and the assistant works in the background (the placeholder is still the instant loading feedback). A failed answer resolves the placeholder to a friendly italic note instead of leaving "thinking..." forever (build_ask_answer never fails).

Tests

routes_assistant now polls for the async answer and still asserts one message (placeholder edited in place), the quiet quote, and no leftover "thinking". routes_assistant, fmt, clippy green.

🤖 Generated with Claude Code

https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg

Follow-up to LC-676 (the composer half). This is a SINGLE-commit PR so it can't lose a trailing commit like #636/#637 did. ## Why a new PR The async-ask commit (`483646b`) was pushed onto the #637 branch, but #637 was merged at its first commit (`87befc8`, the retrieval fix) before the async commit was picked up - the same drop that happened to #636. So the retrieval fix landed but the composer fix did not. Cherry-picked here as its own commit. ## Symptom (1.png, 2.png) After sending `/ask ...`, the composer keeps the typed text and the slash argument-hint stays up - for the whole answer duration - and the "The assistant is thinking..." placeholder shows in the meantime. ## Root cause `handle_ask` posted the placeholder and then ran the LLM synchronously, holding the `/ask` POST open for the whole multi-second local-model answer. The composer clears its text and dismisses the slash hint on the POST's *return*, so both hung until the answer resolved. ## Fix `handle_ask` now posts the placeholder and returns immediately, running retrieval + the LLM in a spawned task that replaces the placeholder body in place when ready. `/ask` answers with a fast 204 - the composer clears its text and slash hint at once - and the assistant works in the background (the placeholder is still the instant loading feedback). A failed answer resolves the placeholder to a friendly italic note instead of leaving "thinking..." forever (`build_ask_answer` never fails). ## Tests `routes_assistant` now polls for the async answer and still asserts one message (placeholder edited in place), the quiet quote, and no leftover "thinking". routes_assistant, fmt, clippy green. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg
fix(ui): run /ask off the request path so the composer clears immediately (LC-676)
All checks were successful
check-secrets / TruffleHog (push) Successful in 5s
check-secrets / Nosey parker (push) Successful in 5s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / Nosey parker (pull_request) Successful in 4s
check-secrets / Kingfisher (pull_request) Successful in 5s
check-secrets / TruffleHog (pull_request) Successful in 6s
Check / clippy + fmt + tests (pull_request) Successful in 5m37s
Create release / Create release from merged PR (pull_request) Has been skipped
1b463d899b
After LC-676 the /ask handler posted a "thinking..." placeholder and then ran the LLM synchronously, holding the POST open for the whole (multi-second, local-model) answer. The composer clears its text and dismisses the slash hint on the POST's *return*, so both hung for the entire answer: the box kept "/ask ..." and the argument hint stayed up until the answer resolved (ref 1.png, 2.png).

handle_ask now posts the placeholder and returns immediately, running the retrieval + LLM in a spawned task that replaces the placeholder body in place when the answer is ready. So /ask answers with a fast 204: the composer clears its text and slash hint at once, and the assistant works in the background (the placeholder is still the instant loading feedback). Errors resolve the placeholder to a friendly italic note rather than leaving "thinking..." forever (build_ask_answer never fails).

The integration test now polls for the resolved answer (the edit lands via the background task) and still asserts exactly one message (placeholder edited in place), the quiet quote, and no leftover "thinking". routes_assistant, fmt, clippy green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013pGppokMfgq5W46EY2Takg
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-08-04 21:09:43 +02:00
longjacksonle deleted branch fix/LC-676-ask-async-composer 2026-08-04 21:14:56 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!638
No description provided.