Skip to content

[6778][6776] fix(frontend): Show working dots and the new session as soon as a message is sent - #6783

Open
ardaerzin wants to merge 1 commit into
mainfrom
fix/chat-submit-feedback
Open

[6778][6776] fix(frontend): Show working dots and the new session as soon as a message is sent#6783
ardaerzin wants to merge 1 commit into
mainfrom
fix/chat-submit-feedback

Conversation

@ardaerzin

@ardaerzin ardaerzin commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Fixes #6778
Fixes #6776

Linear: AGE-4334, AGE-4332.

Context

Two delays Mahmoud reported together, and they do share a cause. Both reproduce on /m; the desktop playground was checked too and does not show the dots delay, so it is untouched.

When you send a chat message in /m, the message shows at once but the working dots arrive later, and when the message is the first one of a new session, the session shows up in the sidebar later still. Measured on the local EE stack with a scripted send (times from Enter):

message shown working dots session in sidebar
warm runner ~100 ms 356 ms 563 ms
cold runner ~130 ms 2,591 ms 2,882 ms

The send does not go through the AI SDK's sendMessage. The queue hands it to useServerSessionInputs, which does its own fetch to the invoke URL and shows the message as a local "echo" row. So useChat's status stays ready for the whole turn, and the only "a run is happening" signal the screen had was the session liveness poll. That poll can only see the run once the runner has admitted it, and it runs on its own cadence. The sidebar has the same dependency: the server lists a new session only once its first turn is admitted (absent at 86 ms, present at 269 ms warm, seconds on a cold runner), and the list refetches after that.

Changes

Both surfaces now read what the client already knows at submit time.

Working dots (#6778). The echo state machine in usePendingSendEchoes already tracks each send from "left the composer" through "runner named the turn" to "row persisted". It now exposes inFlight (an echo that is neither refused nor parked), useAgentChatQueue returns it as sendInFlight, and useAgentConversation folds it into the published run status and returns it. The /m conversation treats it as activity, next to the SDK status and the liveness-derived remote turn. The session's status dot goes live at the same moment.

Sidebar (#6776). @agenta/entities/session gains a small reactive registry of sessions this client created and sent into (localSessionsAtom, with the agent and the first message as the name). The /m conversation registers the session on the first send of a fresh session. The navigation package already had a host seam for exactly this (localSessionRefsAtom, fed on the desktop from its playground tab cache); /m never fed it. A mobile binding now derives rows from the registry, mirrors them into the seam, and retires a local row once the server lists that id, using a new sidebarServerSessionIdsAtomFamily export. The existing merge lets the server row win the moment it exists, so the row the agent later renames is the same row.

Tests

  • Unit: the in-flight predicate (pendingSendsInFlight), the registry atoms (register, idempotent rename, forget), and the mobile row derivation following the session's run status. All pass; eslint, prettier --check, and tsc --noEmit pass in entities, chat, navigation, and mobile.
  • Browser, /m, same scripted send after the change: working dots at 73 ms in an existing session; in a new session the sidebar row appears at 86 ms and the dots at 102 ms, both before the invoke request has even returned. After the run settles there is exactly one row for the session, carrying the server's name.
  • Desktop: timed the same send in the agent playground with the new signal switched off and on; the dots appear as the request leaves either way (185 ms and 209 ms), so the desktop gate is left as is. sendInFlight is available from useAgentChatQueue if a desktop surface ever needs it.

What to QA

  • /m: open an existing session, send a message. The three dots appear under your message in the same instant it does, and stay until the reply starts.
  • /m: press + for a new session, send a first message. Your message text is the top row in the sidebar's Sessions list immediately, with the running spinner. When the agent renames the session, the row's label updates in place and there is only one row for it.
  • /m: send from Home's composer instead of a session page. Same two checks.
  • Regression: queue a second message while a run is going (it parks). No extra dots for the parked one, and the session row does not duplicate.

…sage is sent

On /m the working dots trailed a sent message by 0.4-2.6 s, and a new session
reached the sidebar 0.6-2.9 s after its first message. Both wait on the runner
admitting the turn: the send goes through `useServerSessionInputs`, which does
its own fetch and shows the message as a local echo, so `useChat`'s status never
leaves "ready" and the only "a run is happening" signal was the liveness poll.
The server lists a new session only once that same admission happens.

The echo state machine already knows a send is on its way. It now exposes
`inFlight`, the queue returns it as `sendInFlight`, and `useAgentConversation`
folds it into the published run status and returns it; the /m conversation
counts it as activity, so the dots render with the message.

`@agenta/entities/session` gains `localSessionsAtom`, a reactive registry of
sessions this client created and sent into. The /m conversation registers a
fresh session on its first send, and a mobile binding derives sidebar rows from
it into the navigation package's existing `localSessionRefsAtom` seam (which
the desktop feeds from its tab cache and /m never fed), retiring a row once the
server lists that id via the new `sidebarServerSessionIdsAtomFamily`.

Measured after the change on /m: dots at 73 ms in an existing session; in a new
session the sidebar row at 86 ms and the dots at 102 ms, both before the invoke
request returns. The desktop playground does not show the dots delay, so it is
untouched.

Fixes #6778
Fixes #6776
@vercel

vercel Bot commented Sep 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
agenta-documentation Ready Ready Preview Sep 12, 2026 10:43am UTC

Request Review

@coderabbitai

coderabbitai Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

📝 Summary

Summary by CodeRabbit

  • New Features

    • Newly created chat sessions now appear immediately in the mobile session list, before server synchronization completes.
    • Session names are generated from the first message and preserved across updates.
    • Chat activity indicators remain active while messages are being submitted or streamed.
    • Local sessions are automatically reconciled when server data becomes available.
  • Bug Fixes

    • Improved visibility and status handling for newly submitted messages and sessions.
  • Tests

    • Added coverage for local session registration, naming, synchronization, and pending message states.

Walkthrough

The change registers fresh mobile sessions locally, synchronizes them with the mobile sidebar, and removes them after server discovery. It also exposes in-flight send state through chat hooks and uses that state for immediate mobile activity feedback.

Changes

Local session visibility

Layer / File(s) Summary
Local session registry and server session IDs
web/packages/agenta-entities/src/session/core/localSessions.ts, web/packages/agenta-entities/src/session/index.ts, web/packages/agenta-entities/tests/unit/session-local-sessions.test.ts, web/packages/agenta-navigation/src/dynamic/sessionsSource.ts, web/packages/agenta-navigation/src/index.ts
Adds local session records, registration and cleanup atoms, title derivation, tests, and a scope-specific atom for server session IDs.
Mobile sidebar synchronization
web/mobile/src/features/nav/localSessionRefs.ts, web/mobile/src/features/nav/useMobileNavItems.tsx, web/mobile/tests/unit/localSessionRefs.test.ts
Maps local sessions into mobile sidebar references, synchronizes them with navigation state, and removes entries after server discovery. Tests cover registration and status changes.

Send activity feedback

Layer / File(s) Summary
In-flight send state
web/packages/agenta-chat/src/assets/pendingSendEchoes.ts, web/packages/agenta-chat/src/hooks/usePendingSendEchoes.ts, web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts, web/packages/agenta-chat/src/hooks/useAgentConversation.ts, web/packages/agenta-chat/tests/unit/pendingSendsInFlight.test.ts
Adds in-flight detection for pending sends and exposes it through the chat queue and conversation APIs. Session run status treats admitted sends as active.
Mobile chat integration
web/mobile/src/features/chat/LiveConversation.tsx
Registers fresh sessions before sending, routes composer sends through the wrapper, and includes in-flight sends in turn activity display.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant MobileComposer
  participant LiveConversation
  participant LocalSessionRegistry
  participant AgentConversation
  participant ChatQueue
  MobileComposer->>LiveConversation: submit message
  LiveConversation->>LocalSessionRegistry: register fresh session
  LiveConversation->>AgentConversation: send message
  AgentConversation->>ChatQueue: admit send
  ChatQueue-->>AgentConversation: sendInFlight
  AgentConversation-->>LiveConversation: activity state
Loading

Possibly related PRs

Merge Risk: 🟡 Moderate · up to 2cce3

Navigating away during a send can clear the chat's pending activity and reset the session to idle before the runner accepts it. Resolve the lifecycle mismatch before merge.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Description check ✅ Passed The description clearly explains the delayed indicators, the local-session registry, implementation details, tests, QA steps, and preserved desktop behavior.
Linked Issues check ✅ Passed The description references and fixes issues #6778 and #6776, and the implementation directly addresses both delayed working indicators and delayed new-session sidebar visibility.
Out of Scope Changes check ✅ Passed The changed files support the stated mobile chat, session registry, navigation, and test objectives. The description also confirms that existing desktop behavior remains unchanged.
Title check ✅ Passed The title concisely identifies the frontend fix and its two primary user-visible outcomes: immediate working dots and immediate new-session visibility.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chat-submit-feedback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
web/mobile/src/features/nav/localSessionRefs.ts (1)

46-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a hook-level reconciliation test.

withLocalSessions excludes local refs already present in server rows, so a stale ref does not create an immediate duplicate. It can reappear when the server row leaves the loaded window. The current tests never mount useSyncLocalSessionRefs or seed sidebarServerSessionIdsAtomFamily(scopeId). Register a session, expose its ID through the scoped server list, mount the hook, and assert that localSessionRefsAtom and localSessionsAtom no longer contain it.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Advanced

Run ID: b66c2199-cecb-42cd-82e7-b659747a0820

📥 Commits

Reviewing files that changed from the base of the PR and between dd55885 and 2cce3b4.

📒 Files selected for processing (14)
  • web/mobile/src/features/chat/LiveConversation.tsx
  • web/mobile/src/features/nav/localSessionRefs.ts
  • web/mobile/src/features/nav/useMobileNavItems.tsx
  • web/mobile/tests/unit/localSessionRefs.test.ts
  • web/packages/agenta-chat/src/assets/pendingSendEchoes.ts
  • web/packages/agenta-chat/src/hooks/useAgentChatQueue.ts
  • web/packages/agenta-chat/src/hooks/useAgentConversation.ts
  • web/packages/agenta-chat/src/hooks/usePendingSendEchoes.ts
  • web/packages/agenta-chat/tests/unit/pendingSendsInFlight.test.ts
  • web/packages/agenta-entities/src/session/core/localSessions.ts
  • web/packages/agenta-entities/src/session/index.ts
  • web/packages/agenta-entities/tests/unit/session-local-sessions.test.ts
  • web/packages/agenta-navigation/src/dynamic/sessionsSource.ts
  • web/packages/agenta-navigation/src/index.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.

error: !!errorBoundary.runError,
hitlPending,
busy: busy || acceptedRunPending || ownsContinuation,
busy: busy || acceptedRunPending || ownsContinuation || sendInFlight,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Include sendInFlight in busyRef.current.

useAgentChatQueue marks the durable send in flight before server.submit, but line 537 updates busyRef.current before that hook runs and omits sendInFlight. Line 975 can therefore publish running while useSessionChat reads false during cleanup. releaseSessionChat then drops the chat, and the unmount cleanup sets the session to idle.

Move the assignment after sendInFlight is available:

Proposed fix
-    busyRef.current = busy || acceptedRunPending
+    busyRef.current = busy || acceptedRunPending
...
     const {
         // ...
         sendInFlight,
     } = useAgentChatQueue({
         // ...
     })
+    busyRef.current = busy || acceptedRunPending || sendInFlight
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
busy: busy || acceptedRunPending || ownsContinuation || sendInFlight,
busyRef.current = busy || acceptedRunPending
const {
// ...
sendInFlight,
} = useAgentChatQueue({
// ...
})
busyRef.current = busy || acceptedRunPending || sendInFlight

@github-actions

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-pr-6783.up.railway.app/w
Project agenta-oss-clone-spike
Image tag pr-6783-bb7ba02
Status Deployed
Railway logs Open logs
Workflow logs View workflow run
Updated at 2026-09-12T10:54:34.411Z

@ardaerzin ardaerzin changed the title [6778] fix(frontend): Show working dots and the new session as soon as a message is sent [6778][6776] fix(frontend): Show working dots and the new session as soon as a message is sent Sep 12, 2026
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.

(bug) Working dots appear late after sending a chat message (bug) New sessions take too long to appear in the sidebar after the first message

1 participant