Skip to content

send_message deterministically fails with "No action selected" when the target chat's row sits below the sidebar viewport #173

Description

@gaoyangz77

send_message deterministically fails with "No action selected" when the target chat's row sits below the sidebar viewport

Summary

POST /api/messages/send fails every time for a chat whose row in the Chats sidebar is scrolled out of view (e.g. a contact with little or no recent activity, sitting at index ~60 of ~80 sessions). The failure is deterministic, not flaky: retries never succeed until the chat moves near the top of the list (i.e. receives a message). Sends to chats near the top of the list work normally on the same install at the same time.

Root cause

ChatOpenState::identify (packages/agent-server-rust/src/ia/states/chat.rs) distinguishes chat from chat_open by whether a visible list[name="Chats"] > list-item carries the SELECTED a11y state:

// ChatState: identified when no selected item is visible
if find_selected_chat_item(args.a11y).is_some() { return ... identified: false ... }
// ChatOpenState: identified when a selected item is visible
if find_selected_chat_item(args.a11y).is_none() { return ... identified: false ... }

The a11y tree only exposes the list items currently in the viewport (~11 rows). When chat-select selects a session whose row is below the viewport (via the selectSession hook redirect), the chat pane opens correctly — the a11y tree contains the Send(S) button, the edit box, and the chat header — but no visible list item is SELECTED, so the main window is identified as chat, never chat_open.

SendMessagePlan's Focusing phase requires main_state_id == Some("chat_open") and returns None otherwise (packages/agent-server-rust/src/plans/send_message.rs), which surfaces as the generic "No action selected". The Opening phase succeeds (or skips via current_sel == target), so the plan reaches Focusing and then fails on every step, forever.

Reproduction

  1. A logged-in account with enough sessions that some rows sit below the sidebar viewport (we had 80).
  2. Pick a target chat with old/no activity so its row is well below the fold. chat-select --list shows it present; chat-select --force <id> returns {"ok": true, ...} and the chat pane visibly opens.
  3. POST /api/messages/send for that chat → {"success": false, "error": "No action selected"} every attempt.
  4. Same call for a chat near the top of the list succeeds.

Evidence from our install

  • /api/debug/a11y sampled 15× at 2s intervals while the target chat was open: stable 13.4 KB tree, Send(S) present, edit box present, list[name="Chats"] exposing 11 items, none SELECTED (the selected row is off-viewport). The tree is healthy; only the state classification is wrong.
  • Execution logs during a send show the signature oscillation: step=0 mainWindow=chat_open (transiently, while the click used to fire the hook lands on a visible top row) followed by step=1 mainWindow=chat → receipt fails ~30ms later.
  • chat-select stderr confirms the selection itself works: Current selection: <target>, hook fired, click landed.

Suggested fixes (any one of these would resolve it)

  1. Identify chat_open by chat-pane features instead of the sidebar: presence of the message edit box + Send(S) button (the pair find_edit_and_send_button already locates), or the chat header label. That reflects what the state actually means — a conversation is open — and is viewport-independent.
  2. Or: after the selectSession hook redirect, scroll the sidebar so the selected row is in view before returning from chat-select.
  3. Or: let SendMessagePlan::Focusing accept the chat state when find_edit_and_send_button succeeds — the button pair is itself proof that a chat is open.

Happy to test a patch against our install.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions