Skip to content

fix(chat): preserve queued follow-ups while the active head loads - #9134

Open
mameikagou wants to merge 1 commit into
multica-ai:mainfrom
mameikagou:fix/chat-queue-preserve-followups-20261009
Open

mameikagou wants to merge 1 commit into
multica-ai:mainfrom
mameikagou:fix/chat-queue-preserve-followups-20261009

Conversation

@mameikagou

Copy link
Copy Markdown
Contributor

What does this PR do?

Preserve accepted chat follow-ups when their queued acknowledgements arrive before the client has loaded the active pending head. Previously, every acknowledgement replaced the queue-only cache with [task], dropping earlier queued entries from local pending state.

Thinking path:

  • Chat send acknowledgements and the authoritative pending query settle asynchronously.
  • A response with queued: true can arrive before the running head is available locally. The shared pending helper deliberately keeps such state headless until the pending query loads.
  • More than one acknowledgement can arrive in this window. Replacing queued_tasks loses earlier accepted entries; merging through the existing normalizeQueue preserves them with the same FIFO ordering, task-ID deduplication, and rich-preview preference as the existing loaded-head path.
  • Both the main chat and floating chat window use this helper, so the fix belongs in this shared state layer, with regression tests beside it.

Scope: this fixes a deterministic frontend queue-state overwrite. It does not change backend scheduling, cancel/retry behavior, or claim that persisted messages were deleted. It has not established that every reported instance of a replaced message has this cause.

Related Issue

User-reported repeated chat queue replacement; no linked GitHub issue.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Refactor / code improvement (no behavior change)
  • Documentation update
  • Tests (adding or improving test coverage)
  • CI / infrastructure

Changes Made

  • packages/core/chat/pending.ts: append queued acknowledgements to the existing headless queue and normalize, rather than replacing it. Preserve supports_queue and keep the active head unspecified until it is known.
  • packages/core/chat/pending.test.ts: four regression cases covering sequential and reversed acknowledgements, late head acknowledgement, task-ID deduplication, sibling preservation, and rich/sparse preview observations in either order. Also declare the DOM-free Node test environment.

How to Test

  1. Begin without a cached active head. Accept follow-up A with queued: true, then accept follow-up B with queued: true. Before this fix the cached queue changes from [A] to [B]; after it the queue is [A, B] with no fabricated head. Reversing acknowledgement order produces the same FIFO queue.
  2. Confirm that a later head acknowledgement preserves both follow-ups. Re-observe one queued task with a sparse or rich payload and verify the sibling and message preview remain intact.
  3. Run the regression suite and checks below from the repository root:
pnpm --filter @multica/core exec vitest run chat realtime/use-realtime-sync.test.ts api/schemas.test.ts --maxWorkers=2
pnpm --filter @multica/core typecheck
pnpm --filter @multica/core exec eslint chat/pending.ts chat/pending.test.ts
git diff --check

Verified locally: 10 test files / 320 tests pass; core typecheck, changed-file lint, and diff whitespace check pass. The four new regression cases all failed against the original helper before applying the fix. Dependencies were reused from an existing local installation; no dependency or lockfile changes are included.

Risks / verification limits: this reuses existing normalization semantics and only changes the headless queued: true branch. It was manually reviewed, but no browser E2E, real-provider smoke test, full-monorepo build, or deployment was performed. No server or daemon changes are included.

Checklist

  • I have included a thinking path that traces from project context to this change
  • I have run tests locally and they pass
  • I have added or updated tests where applicable
  • If this change affects the UI, I have included before/after screenshots (no browser screenshots captured; deterministic state reproduction above)
  • I have updated relevant documentation to reflect my changes (not applicable: internal state fix, no public API changes)
  • If I added a new runtime / coding tool / UI tab, I synced the change to landing copy (apps/web/features/landing/i18n/) and relevant docs (apps/docs/content/docs/) (not applicable)
  • If this PR touches Chinese product copy, I checked it against apps/docs/content/docs/developers/conventions.zh.mdx (terminology, mixed-rule for task / issue / skill) (not applicable)
  • I have considered and documented any risks above
  • I will address all reviewer comments before requesting merge

AI Disclosure

AI tool used: Codex via Multica.

Prompt / approach: The user reported that sending additional chat messages before a response replaced earlier messages instead of queueing them, and requested an upstream PR. Inspected the send and pending-state paths, reproduced the shared helper's headless queue overwrite, added failing regression tests, reused existing queue normalization for a minimal fix, ran related core tests/typecheck/lint, and manually reviewed the two-file diff. No live chat messages or provider requests were used to test this patch.

Screenshots (optional)

No visual styling changes or browser screenshots. The reproducible queue-state trace is [A] -> [B] before and [A] -> [A, B] after the fix.

@vercel

vercel Bot commented Oct 8, 2026

Copy link
Copy Markdown

@mameikagou is attempting to deploy a commit to the IndexLabs Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant