Skip to content

feat(chat): centralize AI mode entry points behind openChat helper#7036

Open
Haroenv wants to merge 2 commits into
masterfrom
feat/chat-open-chat-helper
Open

feat(chat): centralize AI mode entry points behind openChat helper#7036
Haroenv wants to merge 2 commits into
masterfrom
feat/chat-open-chat-helper

Conversation

@Haroenv
Copy link
Copy Markdown
Contributor

@Haroenv Haroenv commented May 13, 2026

Summary

  • Clicking the AI mode button (or an autocomplete prompt suggestion) repeatedly used to re-send the same query each time, including after a response had returned. This PR introduces a shared openChat helper that all entry points route through, so duplicate sends are no longer possible.
  • New helpers in instantsearch.js/es/lib/chat:
    • openChat(chatRenderState, { message? }) — opens the chat unconditionally; sends only when message is non-empty and the chat is not already processing; returns true when a message was sent so callers can clear their input.
    • isChatBusy(chatRenderState) — used to disable the AI mode button while a message is in flight.
  • All five AI-mode entry points now follow the same shape:
    • React SearchBox AI button
    • React Autocomplete AI button
    • React Autocomplete prompt-suggestion onSelect
    • JS SearchBox AI button
    • JS Autocomplete AI button
    • JS Autocomplete prompt-suggestion onSelect
  • Pattern at each callsite:
    if (openChat(chatRenderState, { message })) {
      // clear input — varies per widget
    }
  • The button on send clears the visible input; subsequent clicks with an empty input just open/focus the chat composer (the "valid empty-state" case the user can still rely on).
  • Disabled state propagates: aiModeButtonDisabled is now a prop on the React SearchBox UI, the shared AutocompleteSearch UI, and the Preact SearchBox button.

Why this matters

The original behavior was the combination of:

  1. The AI mode click handler always called setOpen(true) + sendMessage({ text: query }) with no in-flight guard.
  2. The button stayed visible after the chat opened, so a second click on the same query would re-submit it as a new user message.

AbstractChat.sendMessage is queued in a SerialJobExecutor, so repeated clicks weren't dropped — they were queued, each producing its own assistant response. This PR fixes that.

Vue InstantSearch doesn't yet expose AI mode, so nothing to mirror there. Any future entry point that has access to chatRenderState can call openChat({ message }) and inherit the same behavior without needing to re-implement the open/send/busy logic.

Test plan

  • yarn jest — 199 tests pass across modified packages, including 13 new tests for openChat/isChatBusy (packages/instantsearch.js/src/lib/chat/__tests__/openChat.test.ts)
  • New UI tests for the aiModeButtonDisabled prop on the React SearchBox UI and on the shared AutocompleteSearch
  • yarn type-check — clean on touched files
  • Manual smoke test in the JS and React e-commerce examples: open AI mode with a query, confirm input clears and chat opens with the message; click AI mode again with empty input, confirm it just focuses the chat composer; click rapidly while the chat is streaming, confirm the button is disabled and no duplicate user messages appear

🤖 Generated with Claude Code

Clicking the AI mode button multiple times sent the same query each time,
even after a response had returned. Same for autocomplete prompt suggestions.

Introduce `openChat` and `isChatBusy` in `lib/chat`. All AI-mode entry
points in the searchbox and autocomplete (React + JS) now route through
`openChat`, which opens the chat unconditionally, sends only when the
message is non-empty and the chat is not already processing, and returns
whether it sent so callers can clear their own input. The AI mode button
is disabled while the chat is processing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codacy-production
Copy link
Copy Markdown

codacy-production Bot commented May 13, 2026

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 2 complexity

Metric Results
Complexity 2

View in Codacy

TIP This summary will be updated as you push new changes.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 13, 2026

More templates

algoliasearch-helper

npm i https://pkg.pr.new/algolia/instantsearch/algoliasearch-helper@7036

instantsearch-ui-components

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch-ui-components@7036

instantsearch.css

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch.css@7036

instantsearch.js

npm i https://pkg.pr.new/algolia/instantsearch/instantsearch.js@7036

react-instantsearch

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch@7036

react-instantsearch-core

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-core@7036

react-instantsearch-nextjs

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-nextjs@7036

react-instantsearch-router-nextjs

npm i https://pkg.pr.new/algolia/instantsearch/react-instantsearch-router-nextjs@7036

vue-instantsearch

npm i https://pkg.pr.new/algolia/instantsearch/vue-instantsearch@7036

commit: a5e2002

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR centralizes all “AI mode” entry points behind a shared openChat helper to prevent duplicate chat submissions (especially from repeated clicks while a message is in flight), and propagates a disabled state to AI mode buttons based on chat busy status.

Changes:

  • Added openChat / isChatBusy helpers to standardize “open + (conditionally) send” chat behavior and prevent re-sends while streaming/submitted.
  • Updated React InstantSearch and InstantSearch.js SearchBox/Autocomplete entry points to route through openChat, and clear inputs only when a message is actually sent.
  • Added aiModeButtonDisabled plumbing + UI tests to ensure AI mode buttons disable while chat is busy.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/react-instantsearch/src/widgets/SearchBox.tsx Uses openChat for AI mode click behavior and wires aiModeButtonDisabled from isChatBusy.
packages/react-instantsearch/src/widgets/Autocomplete.tsx Routes AI-mode button + prompt-suggestion selection through openChat, and propagates disabled state.
packages/react-instantsearch/src/ui/SearchBox.tsx Adds aiModeButtonDisabled prop and applies it to the AI mode button.
packages/react-instantsearch/src/ui/tests/SearchBox.test.tsx Adds UI coverage for rendering/disabling/click behavior of the AI mode button.
packages/react-instantsearch/src/components/AutocompleteSearch.tsx Passes through the new aiModeButtonDisabled prop to shared UI component.
packages/instantsearch.js/src/widgets/search-box/search-box.tsx Centralizes chat open/send via openChat and disables AI button using isChatBusy.
packages/instantsearch.js/src/widgets/autocomplete/autocomplete.tsx Uses openChat for AI-mode and prompt suggestions; disables AI button while chat is busy.
packages/instantsearch.js/src/lib/chat/openChat.ts Introduces shared openChat + isChatBusy helpers.
packages/instantsearch.js/src/lib/chat/index.ts Re-exports openChat / isChatBusy and OpenChatOptions.
packages/instantsearch.js/src/lib/chat/tests/openChat.test.ts Adds unit tests for open/send behavior and busy-state handling.
packages/instantsearch.js/src/components/SearchBox/SearchBox.tsx Adds aiModeButtonDisabled prop and applies it to the Preact AI mode button.
packages/instantsearch-ui-components/src/components/autocomplete/AutocompleteSearch.tsx Adds aiModeButtonDisabled prop and applies it to the AI mode button.
packages/instantsearch-ui-components/src/components/autocomplete/tests/AutocompleteSearch.test.tsx Adds UI coverage for disabled AI mode button behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/instantsearch.js/src/lib/chat/openChat.ts Outdated
`chatRenderState.sendMessage` is part of a `Partial<ChatRenderState>`,
so it can be undefined. The previous code did `sendMessage?.(...)` and
returned `true` unconditionally, which would cause callers to clear their
input even though no message had actually been sent. Check for
`sendMessage` before invoking and only return `true` when it ran.

Also bump instantsearch.development.js bundlesize limit (262.25 → 262.5 kB)
to accommodate the new openChat helper.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Haroenv Haroenv marked this pull request as ready for review May 13, 2026 16:44
@Haroenv Haroenv requested review from a team, aymeric-giraudet and shaejaz and removed request for a team May 13, 2026 16:44
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.

2 participants