ask agent in crew introduce new question twice #72
Labels
No labels
prio_critical
prio_low
type_bug
type_contact
type_issue
type_lead
type_question
type_story
type_task
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
lhumina_code/hero_shrimp#72
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Implementation Spec for Issue #72
Objective
Stop the operator's new question from appearing twice as an
ASKbubble in the crew agent chat thread when using "Ask this agent". The question must render exactly once from the moment it is sent until (and after) the agent replies.Root Cause Analysis
This is a UI double-render, not a backend double-insert.
crates/hero_shrimp_server/src/rpc/methods/crew/mod.rs,method_crew_sendbuilds a singleAgentMessageRowand writes it once viaruntime.database.upsert_agent_message(&row). No second insert occurs on that path.crates/hero_shrimp_web/ui/src/components/CrewPage.tsx:sendAsk()(lines 176-194) optimistically setspendingAskand then callsrpc("crew.send", ...)followed byrefresh().refresh()re-fetchescrew.messagesand repopulatesmsgs(), so the real persisted ask now appears inbyAgent().focusedThread()(lines 204-216) unconditionally appends an optimistic ask bubble (line 211) plus a "working..." reply (line 212) wheneverpendingAskis set for the focused agent.pendingAskis only cleared when a reply crosses the baseline reply count (lines 196-201:if (replies > p.replies0) setPendingAsk(null)).Result: after
refresh()pulls the real ask intobasebut before any reply lands, the thread shows both (a) the real ask frombyAgent()and (b) the optimistic ask fromfocusedThread()— the duplicateASKbubble seen in the screenshot. The optimistic bubble is keyed off "reply count" rather than "is my ask now present in the fetched messages", so it lingers alongside the real ask.Requirements
msgs(), not only when a reply arrives.ASKbubble at any point in the in-flight lifecycle.Files to Modify/Create
crates/hero_shrimp_web/ui/src/components/CrewPage.tsx- Fix the optimistic-ask clearing/merging logic so the placeholder is suppressed once the real ask is fetched.crates/hero_shrimp_web/static/assets/(generated) - Rebuilt Vite bundle the server serves; regenerated after the source change.Implementation Plan
Step 1: Clear the optimistic ask once the real ask is present in fetched messages
Files:
crates/hero_shrimp_web/ui/src/components/CrewPage.tsxcreateEffectat lines 196-201 so it ALSO clearspendingAskwhen the real ask now exists inbyAgent()[p.to], matched by kindask+ trimmed text equality against the pending ask.Dependencies: none
Step 2: Make
focusedThread()defensive against the same-text real askFiles:
crates/hero_shrimp_web/ui/src/components/CrewPage.tsxfocusedThread()(lines 204-216), before appending the optimistic ask bubble, guard against the case where the real ask is already inbase(a message with kindaskwhose trimmed text equals the pending ask text).Dependencies: none (independent of Step 1; both applied for a robust fix)
Step 3: Rebuild the UI bundle
Files:
crates/hero_shrimp_web/ui/-> outputs tocrates/hero_shrimp_web/static/assets/npm run buildincrates/hero_shrimp_web/ui/, which runsvite buildand writes hashed assets into../static/assets).crates/hero_shrimp_web/static/assets/is regenerated (old hashedapp.<hash>.jsreplaced).Dependencies: Steps 1 and 2 complete first.
Acceptance Criteria
ASKbubble exactly once immediately after Send.crew.send+refresh()but before the reply), the thread shows the single real ask plus at most one "working..." indicator — no secondASKbubble.ASKand oneREPLY; no leftover optimistic placeholder.method_crew_sendstill persists exactly one row.crates/hero_shrimp_web/static/assets/rebuilt and committed.Notes
refresh()-fetched real ask; it is not fixed in the backend.id. A stronger key (theidreturned bycrew.send) is possible later but is a larger change; the text-match fix is the minimal, focused solution.anyAskInFlight) is unaffected and left as-is.Test Results
This fix is frontend-only (single SolidJS component plus the regenerated bundle); the backend was not touched, so no Rust tests are in scope.
Production build (vite)
npm run buildincrates/hero_shrimp_web/uicrates/hero_shrimp_web/static/assets/app.D6QRCr1C.js,static/index.htmlupdated to the new hash.TypeScript typecheck (
tsc --noEmit)CrewPage.tsxreports 0 type errors.tscreports some pre-existing errors in unrelated, untouched files (ChatActivity.tsx,CostBadge.tsx,DiffViewer.tsx,HeroWelcome.tsx,store.ts). These are present ondevelopmentindependently of this change and do not affect the build pipeline (thebuildscript runsvite build, which does not runtsc).Summary
Implementation Summary
Fixed the duplicate ASK bubble that appeared when an operator asks a crew agent a new question via "Ask this agent".
Root cause
Client-side render timing, not a backend double-insert. After
sendAsk()optimistically showed the ask,refresh()re-fetched the real persisted ask into the message list, but the optimistic copy was only cleared when a reply arrived — so during the in-flight window both the real ask and the optimistic ask rendered together.Changes
crates/hero_shrimp_web/ui/src/components/CrewPage.tsxcreateEffectthat clearspendingAsknow also clears it as soon as the real ask is present in the re-fetched messages (matched by kindask+ trimmed text), in addition to the existing reply-count trigger.focusedThread()now guards before appending the optimistic ask: if the real ask is already in the thread it is not duplicated; the "working..." indicator is still shown until a reply lands.crates/hero_shrimp_web/static/index.htmlandcrates/hero_shrimp_web/static/assets/— regenerated Vite bundle (app.D6QRCr1C.js) reflecting the source change.No backend changes;
method_crew_sendstill persists exactly one row.Test results
vite build): PASS.Pull request opened: #84
This PR implements the changes discussed in this issue.