- {message.parts.map(renderMessagePart)}
+ {message.parts
+ .filter((part) => part !== toolToRenderLast)
+ .map(renderMessagePart)}
+ {toolToRenderLast &&
+ renderMessagePart(toolToRenderLast, message.parts.length - 1)}
{hasActions && (
diff --git a/packages/instantsearch-ui-components/src/components/chat/ChatMessages.tsx b/packages/instantsearch-ui-components/src/components/chat/ChatMessages.tsx
index 2a86b962932..75a46d12ffe 100644
--- a/packages/instantsearch-ui-components/src/components/chat/ChatMessages.tsx
+++ b/packages/instantsearch-ui-components/src/components/chat/ChatMessages.tsx
@@ -116,6 +116,7 @@ export type ChatMessagesProps<
* Function to close the chat
*/
onClose: () => void;
+ sendMessage: (message: string) => void;
/**
* Optional class names
*/
@@ -194,6 +195,7 @@ function createDefaultMessageComponent<
setIndexUiState,
onReload,
onClose,
+ sendMessage,
actionsComponent,
classNames,
messageTranslations,
@@ -209,6 +211,7 @@ function createDefaultMessageComponent<
onReload: (messageId?: string) => void;
onClose: () => void;
actionsComponent?: ChatMessageProps['actionsComponent'];
+ sendMessage: (newMessage: string) => void;
translations: ChatMessagesTranslations;
classNames?: Partial;
messageTranslations?: Partial;
@@ -244,6 +247,7 @@ function createDefaultMessageComponent<
indexUiState={indexUiState}
setIndexUiState={setIndexUiState}
onClose={onClose}
+ sendMessage={sendMessage}
actions={defaultActions}
actionsComponent={actionsComponent}
data-role={message.role}
@@ -288,6 +292,7 @@ export function createChatMessagesComponent({
hideScrollToBottom = false,
onReload,
onClose,
+ sendMessage,
translations: userTranslations,
userMessageProps,
assistantMessageProps,
@@ -361,6 +366,7 @@ export function createChatMessagesComponent({
onReload={onReload}
actionsComponent={ActionsComponent}
onClose={onClose}
+ sendMessage={sendMessage}
translations={translations}
classNames={messageClassNames}
messageTranslations={messageTranslations}
diff --git a/packages/instantsearch-ui-components/src/components/chat/types.ts b/packages/instantsearch-ui-components/src/components/chat/types.ts
index 4c6164dc496..bbd319c6eba 100644
--- a/packages/instantsearch-ui-components/src/components/chat/types.ts
+++ b/packages/instantsearch-ui-components/src/components/chat/types.ts
@@ -24,6 +24,7 @@ export type ClientSideToolComponentProps = {
setIndexUiState: (state: object) => void;
onClose: () => void;
addToolResult: AddToolResultWithOutput;
+ sendMessage: (message: string) => void;
};
export type ClientSideToolComponent = (
@@ -40,6 +41,7 @@ export type ClientSideTool = {
addToolResult: AddToolResultWithOutput;
}
) => void;
+ renderLast?: boolean;
};
export type ClientSideTools = Record;
diff --git a/packages/instantsearch.js/src/lib/chat/index.ts b/packages/instantsearch.js/src/lib/chat/index.ts
index 6480d2fc5d0..6cd19e5f9c5 100644
--- a/packages/instantsearch.js/src/lib/chat/index.ts
+++ b/packages/instantsearch.js/src/lib/chat/index.ts
@@ -6,3 +6,4 @@ export { Chat } from './chat';
export const SearchIndexToolType = 'algolia_search_index';
export const RecommendToolType = 'algolia_recommend';
+export const PromptSuggestionsToolType = 'algolia_prompt_suggestions';
diff --git a/packages/react-instantsearch/src/widgets/Chat.tsx b/packages/react-instantsearch/src/widgets/Chat.tsx
index 0e94f2266f9..bc5451f4a91 100644
--- a/packages/react-instantsearch/src/widgets/Chat.tsx
+++ b/packages/react-instantsearch/src/widgets/Chat.tsx
@@ -2,12 +2,14 @@ import { createChatComponent } from 'instantsearch-ui-components';
import {
SearchIndexToolType,
RecommendToolType,
+ PromptSuggestionsToolType,
} from 'instantsearch.js/es/lib/chat';
import React, { createElement, Fragment } from 'react';
import { useInstantSearch, useChat } from 'react-instantsearch-core';
import { useStickToBottom } from '../lib/useStickToBottom';
+import { createPromptSuggestionsTool } from './chat/tools/PromptSuggestionsTool';
import { createCarouselTool } from './chat/tools/SearchIndexTool';
export { SearchIndexToolType, RecommendToolType };
@@ -45,6 +47,7 @@ export function createDefaultTools(
itemComponent,
getSearchPageURL
),
+ [PromptSuggestionsToolType]: createPromptSuggestionsTool(),
};
}
@@ -268,6 +271,9 @@ export function Chat<
},
translations: messagesTranslations,
messageTranslations,
+ sendMessage: (newMessage: string) => {
+ sendMessage({ text: newMessage });
+ },
...messagesProps,
}}
promptProps={{
diff --git a/packages/react-instantsearch/src/widgets/chat/tools/PromptSuggestionsTool.tsx b/packages/react-instantsearch/src/widgets/chat/tools/PromptSuggestionsTool.tsx
new file mode 100644
index 00000000000..52ee1bf91aa
--- /dev/null
+++ b/packages/react-instantsearch/src/widgets/chat/tools/PromptSuggestionsTool.tsx
@@ -0,0 +1,43 @@
+import { createButtonComponent } from 'instantsearch-ui-components';
+import React, { createElement } from 'react';
+
+import type {
+ ClientSideToolComponentProps,
+ Pragma,
+ UserClientSideTool,
+} from 'instantsearch-ui-components';
+
+export function createPromptSuggestionsTool(): UserClientSideTool {
+ const Button = createButtonComponent({
+ createElement: createElement as Pragma,
+ });
+
+ function PromptSuggestionsComponent({
+ message,
+ sendMessage,
+ }: ClientSideToolComponentProps) {
+ const input = message.input as { promptSuggestions?: string[] } | undefined;
+ const promptSuggestions = input?.promptSuggestions;
+
+ if (!promptSuggestions || promptSuggestions.length === 0) {
+ return <>>;
+ }
+
+ return (
+
+ {promptSuggestions.map((suggestion, index) => (
+ -
+
+
+ ))}
+
+ );
+ }
+
+ return {
+ layoutComponent: PromptSuggestionsComponent,
+ renderLast: true,
+ };
+}