@docsearch/react 5.0.0-beta.2 → 5.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/esm/{AskAiScreenState-Bw2WIgv_.d.ts → AskAiScreenState-Sqbn60f2.d.ts} +2 -2
  2. package/dist/esm/{DocSearch-CVj6U-nI.d.ts → DocSearch-BVqxFxTw.d.ts} +18 -27
  3. package/dist/esm/{DocSearchAskAiModal-BczGFkvR.js → DocSearchAskAiModal-C_sH1j8Y.js} +9 -9
  4. package/dist/esm/{DocSearchAskAiModal-BczGFkvR.js.map → DocSearchAskAiModal-C_sH1j8Y.js.map} +1 -1
  5. package/dist/esm/{DocSearchAskAiModal-MF2py4NM.d.ts → DocSearchAskAiModal-DpB7pLCC.d.ts} +4 -4
  6. package/dist/esm/{DocSearchModal-D_tfhoN1.js → DocSearchModal-CITTG0fe.js} +10 -8
  7. package/dist/esm/DocSearchModal-CITTG0fe.js.map +1 -0
  8. package/dist/esm/askaiModal.d.ts +1 -1
  9. package/dist/esm/askaiModal.js +1 -1
  10. package/dist/esm/docsearchAi.d.ts +10 -102
  11. package/dist/esm/docsearchAi.js +1 -1
  12. package/dist/esm/docsearchAi.js.map +1 -1
  13. package/dist/esm/index.d.ts +4 -4
  14. package/dist/esm/index.js +2 -2
  15. package/dist/esm/index.js.map +1 -1
  16. package/dist/esm/modal.d.ts +1 -1
  17. package/dist/esm/modal.js +1 -1
  18. package/dist/esm/{normalizeDocSearchIndexes-D8P3VEXa.js → normalizeDocSearchIndexes-ChnVvoVt.js} +16 -20
  19. package/dist/esm/normalizeDocSearchIndexes-ChnVvoVt.js.map +1 -0
  20. package/dist/esm/sidepanel.d.ts +19 -7
  21. package/dist/esm/sidepanel.js +1 -1
  22. package/dist/esm/sidepanel.js.map +1 -1
  23. package/dist/esm/useDocSearchKeyboardEvents.js +1 -1
  24. package/dist/esm/useDocSearchKeyboardEvents.js.map +1 -1
  25. package/dist/esm/useSearchClient-mIHVB6ga.js.map +1 -1
  26. package/dist/esm/{useSuggestedQuestions-Ds7H1JCr.js → useSuggestedQuestions-DwcUPOf_.js} +72 -25
  27. package/dist/esm/useSuggestedQuestions-DwcUPOf_.js.map +1 -0
  28. package/dist/esm/version.d.ts +1 -1
  29. package/dist/esm/version.js +1 -1
  30. package/dist/esm/version.js.map +1 -1
  31. package/dist/umd/index.js +33 -33
  32. package/dist/umd/index.js.map +1 -1
  33. package/package.json +4 -4
  34. package/dist/esm/DocSearchModal-D_tfhoN1.js.map +0 -1
  35. package/dist/esm/normalizeDocSearchIndexes-D8P3VEXa.js.map +0 -1
  36. package/dist/esm/useSuggestedQuestions-Ds7H1JCr.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  import "./index-Bqqv4HmN.js";
2
- import { f as ResultsScreenTranslations, h as StoredSearchesSectionsTranslations, m as ErrorScreenTranslations, p as NoResultsScreenTranslations } from "./DocSearch-CVj6U-nI.js";
2
+ import { _ as StoredSearchesSectionsTranslations, g as ErrorScreenTranslations, h as NoResultsScreenTranslations, m as ResultsScreenTranslations } from "./DocSearch-BVqxFxTw.js";
3
3
  import React, { JSX } from "react";
4
4
  import { AutocompleteState, BaseItem } from "@algolia/autocomplete-core";
5
5
  import "@ai-sdk/react";
@@ -106,4 +106,4 @@ type AskAiScreenStateTranslations = Partial<{
106
106
  }>;
107
107
  //#endregion
108
108
  export { NewConversationTranslations as n, ToolCallTranslations as r, AskAiScreenStateTranslations as t };
109
- //# sourceMappingURL=AskAiScreenState-Bw2WIgv_.d.ts.map
109
+ //# sourceMappingURL=AskAiScreenState-Sqbn60f2.d.ts.map
@@ -148,7 +148,7 @@ type DocSearchModalProps = DocSearchProps & {
148
148
  onClose?: () => void;
149
149
  translations?: ModalTranslations;
150
150
  };
151
- declare function DocSearchModal({ appId, apiKey, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, facets, ...props }: DocSearchModalProps): JSX.Element;
151
+ declare function DocSearchModal({ appId, apiKey, maxResultsPerGroup, theme, onClose, transformItems, hitComponent, resultsFooterComponent, navigator, initialScrollY, transformSearchClient, disableUserPersonalization, initialQuery: initialQueryFromProp, translations, getMissingResultsUrl, insights, recentSearchesLimit, recentSearchesWithFavoritesLimit, indices, facets, footerAction, ...props }: DocSearchModalProps): JSX.Element;
152
152
  //#endregion
153
153
  //#region src/DocSearch.d.ts
154
154
  type DocSearchTranslations = Partial<{
@@ -168,6 +168,13 @@ interface DocSearchFacet {
168
168
  key: string;
169
169
  label?: string;
170
170
  }
171
+ interface HitComponentProps {
172
+ hit: InternalDocSearchHit | StoredDocSearchHit;
173
+ children: React.ReactNode;
174
+ }
175
+ interface ResultsFooterComponentProps {
176
+ state: AutocompleteState<InternalDocSearchHit>;
177
+ }
171
178
  interface DocSearchProps {
172
179
  /** Algolia application id used by the search client. */
173
180
  appId: string;
@@ -194,32 +201,16 @@ interface DocSearchProps {
194
201
  maxResultsPerGroup?: number;
195
202
  /** Hook to post-process hits before rendering. */
196
203
  transformItems?: (items: DocSearchHit[]) => DocSearchHit[];
204
+ /** Custom component to render an individual hit. */
205
+ hitComponent?: (props: HitComponentProps) => JSX.Element;
206
+ /** Custom component rendered at the bottom of the results panel. */
207
+ resultsFooterComponent?: (props: ResultsFooterComponentProps) => JSX.Element | null;
197
208
  /**
198
- * Custom component to render an individual hit. Supports template patterns:
199
- *
200
- * - HTML strings with html helper: (props, { html }) => html`<div>...</div>`
201
- * - JSX templates: (props) => <div>...</div>
202
- * - Function-based templates: (props) => string | JSX.Element | Function.
203
- */
204
- hitComponent?: (props: {
205
- hit: InternalDocSearchHit | StoredDocSearchHit;
206
- children: React.ReactNode;
207
- }, helpers?: {
208
- html: (template: TemplateStringsArray, ...values: any[]) => any;
209
- }) => JSX.Element;
210
- /**
211
- * Custom component rendered at the bottom of the results panel. Supports
212
- * template patterns:
213
- *
214
- * - HTML strings with html helper: (props, { html }) => html`<div>...</div>`
215
- * - JSX templates: (props) => <div>...</div>
216
- * - Function-based templates: (props) => string | JSX.Element | Function.
209
+ * A custom action that can be rendered in the Modal's footer before the
210
+ * Algolia logo. The component will be rendered as a child of `<div
211
+ * className="DocSearch-Footer-Action" />`.
217
212
  */
218
- resultsFooterComponent?: (props: {
219
- state: AutocompleteState<InternalDocSearchHit>;
220
- }, helpers?: {
221
- html: (template: TemplateStringsArray, ...values: any[]) => any;
222
- }) => JSX.Element | null;
213
+ footerAction?: React.ReactNode;
223
214
  /** Hook to wrap or modify the algolia search client. */
224
215
  transformSearchClient?: (searchClient: DocSearchTransformClient) => DocSearchTransformClient;
225
216
  /** Disable storage and usage of recent and favorite searches. */
@@ -277,5 +268,5 @@ interface DocSearchProps {
277
268
  declare const DocSearch$1: React.ForwardRefExoticComponent<DocSearchProps & React.RefAttributes<DocSearchRef>>;
278
269
  declare function DocSearchInner(props: Omit<DocSearchProps, 'appId' | 'apiKey'>): JSX.Element;
279
270
  //#endregion
280
- export { FacetBarTranslations as _, DocSearchProps as a, DocSearchTranslations as c, ModalTranslations as d, ResultsScreenTranslations as f, FooterTranslations as g, StoredSearchesSectionsTranslations as h, DocSearchInner as i, DocSearchModal as l, ErrorScreenTranslations as m, DocSearchFacet as n, DocSearchRef$1 as o, NoResultsScreenTranslations as p, DocSearchIndex as r, DocSearchTransformClient as s, DocSearch$1 as t, DocSearchModalProps as u, InternalDocSearchHit as v };
281
- //# sourceMappingURL=DocSearch-CVj6U-nI.d.ts.map
271
+ export { StoredSearchesSectionsTranslations as _, DocSearchProps as a, InternalDocSearchHit as b, DocSearchTranslations as c, DocSearchModal as d, DocSearchModalProps as f, ErrorScreenTranslations as g, NoResultsScreenTranslations as h, DocSearchInner as i, HitComponentProps as l, ResultsScreenTranslations as m, DocSearchFacet as n, DocSearchRef$1 as o, ModalTranslations as p, DocSearchIndex as r, DocSearchTransformClient as s, DocSearch$1 as t, ResultsFooterComponentProps as u, FooterTranslations as v, FacetBarTranslations as y };
272
+ //# sourceMappingURL=DocSearch-BVqxFxTw.d.ts.map
@@ -1,8 +1,8 @@
1
1
  import { t as _objectSpread2 } from "./objectSpread2-BNmiQYyW.js";
2
- import { C as noop, D as SOURCE_IDS, E as identity, O as getCollection, S as scrollTo, T as isModifierEvent, _ as Hit, a as NoResultsScreen, b as SearchBoxForm, c as Results, d as useRefreshOnInitialQuery, f as useModalRefs, g as useDocSearchFacets, h as useSendItemClickEvent, i as ResultsScreen, l as useStoredDocSearches, m as useInitialModalQuery, n as buildNoQuerySources, o as ErrorScreen, p as useModalEnvironment, r as buildQuerySources, s as StoredSearchesSections, t as normalizeDocSearchIndexes, u as useSaveRecentSearch, v as Footer, w as isQueryEmpty, x as FacetBar, y as ModalShell } from "./normalizeDocSearchIndexes-D8P3VEXa.js";
2
+ import { C as noop, D as SOURCE_IDS, E as identity, O as getCollection, S as scrollTo, T as isModifierEvent, _ as Hit, a as NoResultsScreen, b as SearchBoxForm, c as Results, d as useRefreshOnInitialQuery, f as useModalRefs, g as useDocSearchFacets, h as useSendItemClickEvent, i as ResultsScreen, l as useStoredDocSearches, m as useInitialModalQuery, n as buildNoQuerySources, o as ErrorScreen, p as useModalEnvironment, r as buildQuerySources, s as StoredSearchesSections, t as normalizeDocSearchIndexes, u as useSaveRecentSearch, v as Footer, w as isQueryEmpty, x as FacetBar, y as ModalShell } from "./normalizeDocSearchIndexes-ChnVvoVt.js";
3
3
  import { n as SearchIcon, t as _objectWithoutProperties } from "./objectWithoutProperties-phqYxDS0.js";
4
4
  import { l as CloseIcon, m as LoadingIcon, p as SparklesIcon, t as useSearchClient } from "./useSearchClient-mIHVB6ga.js";
5
- import { S as AlertIcon, _ as BackIcon, a as MemoizedMarkdown, b as MoreVerticalIcon, c as buildDummyAskAiHit, d as getMessageContent, f as isAIToolPart, g as ConversationPromptSuggestions, h as FeedbackActions, i as groupConsecutiveToolResults, l as extractLinksFromMessage, m as SourcesPanel, n as useAskAi, o as ToolCall, p as isThreadDepthError, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-Ds7H1JCr.js";
5
+ import { S as AlertIcon, _ as BackIcon, a as MemoizedMarkdown, b as MoreVerticalIcon, c as buildDummyAskAiHit, d as getMessageContent, f as isAIToolPart, g as ConversationPromptSuggestions, h as FeedbackActions, i as groupConsecutiveToolResults, l as extractLinksFromMessage, m as SourcesPanel, n as useAskAi, o as ToolCall, p as isThreadDepthError, r as Menu, s as EMPTY_TOOLS, t as useSuggestedQuestions, u as getAgentPromptSuggestions, v as NewConversationIcon, x as StopIcon, y as ConversationHistoryIcon } from "./useSuggestedQuestions-DwcUPOf_.js";
6
6
  import React, { Fragment, useMemo } from "react";
7
7
  import { createAutocomplete } from "@algolia/autocomplete-core";
8
8
 
@@ -583,7 +583,8 @@ const _excluded = [
583
583
  "recentSearchesWithFavoritesLimit",
584
584
  "indices",
585
585
  "facets",
586
- "isHybridModeSupported"
586
+ "isHybridModeSupported",
587
+ "footerAction"
587
588
  ];
588
589
  const _excluded2 = [
589
590
  "footer",
@@ -592,7 +593,7 @@ const _excluded2 = [
592
593
  ];
593
594
  function DocSearchAskAiModal(_ref) {
594
595
  var _translations$searchB, _askAiConfig$memory$e, _askAiConfig$memory, _askAiConfig$tools;
595
- let { appId, apiKey, askAi, maxResultsPerGroup, theme, onClose = noop, transformItems = identity, hitComponent = Hit, resultsFooterComponent = () => null, navigator, initialScrollY = 0, transformSearchClient = identity, disableUserPersonalization = false, initialQuery: initialQueryFromProp = "", translations = {}, getMissingResultsUrl, insights = false, onAskAiToggle, interceptAskAiEvent, isAskAiActive = false, recentSearchesLimit = 7, recentSearchesWithFavoritesLimit = 4, indices, facets, isHybridModeSupported = false } = _ref, props = _objectWithoutProperties(_ref, _excluded);
596
+ let { appId, apiKey, askAi, maxResultsPerGroup, theme, onClose = noop, transformItems = identity, hitComponent = Hit, resultsFooterComponent = () => null, navigator, initialScrollY = 0, transformSearchClient = identity, disableUserPersonalization = false, initialQuery: initialQueryFromProp = "", translations = {}, getMissingResultsUrl, insights = false, onAskAiToggle, interceptAskAiEvent, isAskAiActive = false, recentSearchesLimit = 7, recentSearchesWithFavoritesLimit = 4, indices, facets, isHybridModeSupported = false, footerAction } = _ref, props = _objectWithoutProperties(_ref, _excluded);
596
597
  const { footer: footerTranslations, searchBox: searchBoxTranslations, facets: facetBarTranslations } = translations, screenStateTranslations = _objectWithoutProperties(translations, _excluded2);
597
598
  const [state, setState] = React.useState({
598
599
  query: "",
@@ -613,7 +614,7 @@ function DocSearchAskAiModal(_ref) {
613
614
  var _translations$searchB3;
614
615
  placeholder = (translations === null || translations === void 0 || (_translations$searchB3 = translations.searchBox) === null || _translations$searchB3 === void 0 ? void 0 : _translations$searchB3.placeholderTextAskAi) || "Ask another question...";
615
616
  }
616
- const { containerRef, modalRef, formElementRef, dropdownRef, inputRef, snippetLength } = useModalRefs();
617
+ const { containerRef, modalRef, formElementRef, dropdownRef, inputRef } = useModalRefs();
617
618
  const { initialQuery, initialQueryFromSelection } = useInitialModalQuery(initialQueryFromProp);
618
619
  const searchClient = useSearchClient(appId, apiKey, transformSearchClient);
619
620
  const askAiConfig = typeof askAi === "object" ? askAi : null;
@@ -767,7 +768,6 @@ function DocSearchAskAiModal(_ref) {
767
768
  setStatus,
768
769
  searchClient,
769
770
  indexes,
770
- snippetLength,
771
771
  insights: Boolean(insights),
772
772
  appId,
773
773
  apiKey,
@@ -797,7 +797,6 @@ function DocSearchAskAiModal(_ref) {
797
797
  inputRef,
798
798
  initialScrollY,
799
799
  modalRef,
800
- snippetLength,
801
800
  theme
802
801
  });
803
802
  React.useEffect(() => {
@@ -936,7 +935,8 @@ function DocSearchAskAiModal(_ref) {
936
935
  })),
937
936
  footer: /* @__PURE__ */ React.createElement(Footer, {
938
937
  translations: footerTranslations,
939
- isAskAiActive
938
+ isAskAiActive,
939
+ footerAction
940
940
  }),
941
941
  onClose
942
942
  });
@@ -944,4 +944,4 @@ function DocSearchAskAiModal(_ref) {
944
944
 
945
945
  //#endregion
946
946
  export { DocSearchAskAiModal as t };
947
- //# sourceMappingURL=DocSearchAskAiModal-BczGFkvR.js.map
947
+ //# sourceMappingURL=DocSearchAskAiModal-C_sH1j8Y.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DocSearchAskAiModal-BczGFkvR.js","names":[],"sources":["../../src/icons/MessageIcon.tsx","../../src/AggregatedSearchBlock.tsx","../../src/AskAiScreen.tsx","../../src/components/ui/RecentConversationsResults.tsx","../../src/components/AskAiStartScreen.tsx","../../src/ConversationHistoryScreen.tsx","../../src/NewConversationScreen.tsx","../../src/AskAiScreenState.tsx","../../src/ModalHeading.tsx","../../src/components/AskAiSearchBox.tsx","../../src/utils/createAskAiSources.ts","../../src/DocSearchAskAiModal.tsx"],"sourcesContent":["import React, { type JSX } from 'react';\n\nexport function MessageIcon(): JSX.Element {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n","import React, { type JSX, Fragment } from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { SearchIcon } from './icons';\n\ninterface AggregatedSearchBlockProps {\n queries: string[];\n translations: AskAiScreenTranslations;\n onSearchQueryClick: (query: string) => void;\n}\n\n// allow translators to return either simple string parts or a fully custom node\nexport interface AggregatedToolCallParts {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n}\n\n// default english implementation (\"Searched for \\\"A\\\", \\\"B\\\" and \\\"C\\\"\")\nconst defaultAggregatedToolCallParts: AggregatedToolCallParts = {\n before: 'Searched for ',\n separator: ', ',\n lastSeparator: ' and ',\n after: '',\n};\n\nexport function AggregatedSearchBlock({\n queries,\n translations,\n onSearchQueryClick,\n}: AggregatedSearchBlockProps): JSX.Element | null {\n // no queries? no render\n if (queries.length === 0) return null;\n\n // if the translator provides a fully custom node, render it and bail out.\n if (typeof translations.aggregatedToolCallNode === 'function') {\n return (\n <>{translations.aggregatedToolCallNode(queries, onSearchQueryClick)}</>\n );\n }\n\n // otherwise fall back to the classic english-pattern renderer.\n const parts = translations.aggregatedToolCallText\n ? translations.aggregatedToolCallText(queries)\n : defaultAggregatedToolCallParts;\n\n const {\n before = '',\n separator = ', ',\n lastSeparator = ' and ',\n after = '',\n } = parts || {};\n\n return (\n <div className=\"DocSearch-AskAiScreen-MessageContent-Tool Tool--AggregatedResult\">\n <SearchIcon size={18} />\n <span>\n {before && <span>{before}</span>}\n {queries.map((q, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={q + idx}>\n <span\n role=\"button\"\n tabIndex={0}\n className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSearchQueryClick(q);\n }\n }}\n onClick={() => onSearchQueryClick(q)}\n >\n &quot;{q}&quot;\n </span>\n {idx < queries.length - 2 && separator}\n {idx === queries.length - 2 && lastSeparator}\n </Fragment>\n ))}\n {after && <span>{after}</span>}\n </span>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport React, { type JSX, useMemo } from 'react';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { ConversationPromptSuggestions } from './components/ConversationPromptSuggestions';\nimport { FeedbackActions } from './components/FeedbackActions';\nimport { SourcesPanel } from './components/SourcesPanel';\nimport { ToolCall, type ToolCallTranslations } from './components/ToolCall';\nimport { AlertIcon, LoadingIcon, SparklesIcon } from './icons';\nimport { MemoizedMarkdown } from './MemoizedMarkdown';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n} from './types';\nimport { type AIMessage, type ToolCalls } from './types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n isThreadDepthError,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from './utils/ai';\nimport { groupConsecutiveToolResults } from './utils/groupConsecutiveToolResults';\n\nexport type AskAiScreenTranslations = Partial<\n // Inherit the shared tool-call translations, but expose the search-related\n // keys under AskAiScreen's own public names (see mapping below).\n Omit<ToolCallTranslations, 'searchingText' | 'toolCallResultText'> & {\n // Misc texts\n disclaimerText: string;\n /** Text shown describing a singular related source. */\n relatedSourcesText: string;\n /** Text shown describing multiple related sources. */\n relatedSourcesTextPlural: string;\n thinkingText: string;\n copyButtonText: string;\n copyButtonCopiedText: string;\n // Feedback buttons\n copyButtonTitle: string;\n likeButtonTitle: string;\n dislikeButtonTitle: string;\n thanksForFeedbackText: string;\n // Negative feedback note panel\n feedbackPanelTitle: string;\n feedbackDetailsPlaceholder: string;\n feedbackDisclaimerText: string;\n feedbackSubmitButtonText: string;\n feedbackCloseButtonTitle: string;\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n // Tool call texts\n /**\n * Text shown while assistant is performing search tool call. Maps to\n * `ToolCallTranslations.searchingText`.\n */\n duringToolCallText: string;\n /**\n * Text shown while assistant is finished performing tool call. Maps to\n * `ToolCallTranslations.toolCallResultText`.\n */\n afterToolCallText: string;\n /**\n * Build the full jsx element for the aggregated search block. If provided,\n * completely overrides the default english renderer.\n */\n aggregatedToolCallNode?: (\n queries: string[],\n onSearchQueryClick: (query: string) => void\n ) => React.ReactNode;\n /**\n * Generate the list connective parts only (backwards compatibility).\n * Receives full list of queries and should return translation parts for\n * before/after/separators. Example: (qs) => ({ before: 'searched for ',\n * separator: ', ', lastSeparator: ' and ', after: '' }).\n */\n aggregatedToolCallText?: (queries: string[]) => {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n };\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText: string;\n /** Message shown when thread depth limit is exceeded (AI-217 error). */\n threadDepthExceededMessage: string;\n /** Button text for starting a new conversation after thread depth error. */\n startNewConversationButtonText: string;\n suggestedPromptsTitleText: string;\n }\n>;\n\n/**\n * Maps AskAiScreen's public translation keys to the shared\n * `ToolCallTranslations` shape consumed by the `ToolCall` component, applying\n * default English values.\n */\nfunction toToolCallTranslations(\n translations: AskAiScreenTranslations\n): ToolCallTranslations {\n const {\n preToolCallText = 'Searching...',\n duringToolCallText = 'Searching...',\n afterToolCallText = 'Searched for',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n } = translations;\n\n return {\n preToolCallText,\n searchingText: duringToolCallText,\n toolCallResultText: afterToolCallText,\n savedMemoryToolResultText,\n memoryToolResultText,\n };\n}\n\ntype AskAiScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n messages: AIMessage[];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n translations?: AskAiScreenTranslations;\n onNewConversation: () => void;\n onSelectPromptSuggestion: (prompt: string) => void;\n memoryEnabled?: boolean;\n};\n\ninterface AskAiScreenHeaderProps {\n disclaimerText: string;\n}\n\nexport interface Exchange {\n id: string;\n userMessage: AIMessage;\n assistantMessage: AIMessage | null;\n}\n\nfunction AskAiScreenDisclaimer({\n disclaimerText,\n}: AskAiScreenHeaderProps): JSX.Element {\n return (\n <p className=\"DocSearch-AskAiScreen-Disclaimer\">\n <SparklesIcon /> {disclaimerText}\n </p>\n );\n}\n\ninterface AskAiExchangeCardProps {\n exchange: Exchange;\n askAiError?: Error;\n isLastExchange: boolean;\n loadingStatus: UseChatHelpers<AIMessage>['status'];\n onSearchQueryClick: (query: string) => void;\n translations: AskAiScreenTranslations;\n tools: ToolCalls;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onFeedback?: OnAskAiFeedback;\n memoryEnabled?: boolean;\n onSelectPromptSuggestion: (prompt: string) => void;\n}\n\nfunction AskAiExchangeCard({\n exchange,\n askAiError,\n isLastExchange,\n loadingStatus,\n onSearchQueryClick,\n translations,\n tools,\n conversations,\n onFeedback,\n memoryEnabled,\n onSelectPromptSuggestion,\n}: AskAiExchangeCardProps): JSX.Element {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n stoppedStreamingText = 'You stopped this response',\n errorTitleText = 'Chat error',\n relatedSourcesText,\n relatedSourcesTextPlural,\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const toolCallTranslations = useMemo(\n () => toToolCallTranslations(translations),\n [translations]\n );\n\n const isThreadDepth = isThreadDepthError(askAiError);\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n\n const displayParts = React.useMemo(() => {\n return groupConsecutiveToolResults(assistantMessage?.parts || []);\n }, [assistantMessage]);\n\n const promptSuggestions = useMemo(() => {\n if (!isLastExchange) return [];\n return getAgentPromptSuggestions(assistantMessage?.parts || []);\n }, [assistantMessage, isLastExchange]);\n\n const wasStopped =\n userMessage.metadata?.stopped || assistantMessage?.metadata?.stopped;\n\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange &&\n loadingStatus === 'ready' &&\n Boolean(assistantMessage)));\n\n const isThinking =\n ['submitted', 'streaming'].includes(loadingStatus) &&\n isLastExchange &&\n !displayParts.some((part) => part.type !== 'step-start');\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div className=\"DocSearch-AskAiScreen-Response-Container\">\n <div className=\"DocSearch-AskAiScreen-Response\">\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user\">\n <p className=\"DocSearch-AskAiScreen-Query\">{userContent ?? ''}</p>\n </div>\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant\">\n <div className=\"DocSearch-AskAiScreen-MessageContent\">\n {loadingStatus === 'error' &&\n askAiError &&\n isLastExchange &&\n !isThreadDepth && (\n <div className=\"DocSearch-AskAiScreen-Error\" role=\"alert\">\n <AlertIcon aria-hidden=\"true\" />\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <h4 className=\"DocSearch-AskAiScreen-Error-Title\">\n {errorTitleText}\n </h4>\n <MemoizedMarkdown\n content={askAiError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n {isThinking && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"DocSearch-shimmer\">\n {translations.thinkingText || 'Thinking...'}\n </span>\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-shimmer\" />\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short DocSearch-shimmer\" />\n </div>\n )}\n {displayParts.map((part, idx) => {\n const index = idx;\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={loadingStatus === 'streaming'}\n />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n translations={toolCallTranslations}\n part={part}\n tools={tools}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock\n key={index}\n queries={part.queries}\n translations={translations}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'reasoning' && part.state === 'streaming') {\n return (\n <div\n key={index}\n className=\"DocSearch-AskAiScreen-MessageContent-Reasoning DocSearch-shimmer\"\n >\n <LoadingIcon className=\"DocSearch-AskAiScreen-SmallerLoadingIcon\" />\n <span className=\"DocSearch-shimmer\">Reasoning...</span>\n </div>\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n // fallback for unknown part type\n return null;\n })}\n </div>\n\n {wasStopped && (\n <p className=\"DocSearch-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n pluralTitleText={relatedSourcesTextPlural}\n />\n <FeedbackActions\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {promptSuggestions.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={promptSuggestions}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n}\n\nexport function AskAiScreen({\n translations = {},\n ...props\n}: AskAiScreenProps): JSX.Element | null {\n const {\n disclaimerText = 'Answers are generated with AI which can make mistakes.',\n threadDepthExceededMessage = 'This conversation is now closed to keep responses accurate.',\n startNewConversationButtonText = 'Start a new conversation',\n } = translations;\n\n const { messages, tools, askAiError, status, memoryEnabled } = props;\n\n // Check if there's a thread depth error\n const hasThreadDepthError = useMemo(() => {\n return status === 'error' && isThreadDepthError(askAiError);\n }, [status, askAiError]);\n\n // Group messages into exchanges (user + assistant pairs)\n const exchanges: Exchange[] = useMemo(() => {\n const grouped: Exchange[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n const userMessage = messages[i];\n const assistantMessage =\n messages[i + 1]?.role === 'assistant' ? messages[i + 1] : null;\n grouped.push({ id: userMessage.id, userMessage, assistantMessage });\n if (assistantMessage) {\n i++;\n }\n }\n }\n\n // If there's a thread depth error, remove the last exchange (the one that triggered the error)\n // We only want to show successful exchanges\n if (hasThreadDepthError && grouped.length > 0) {\n // Check if the last exchange has no assistant message (failed to complete)\n const lastExchange = grouped[grouped.length - 1];\n if (!lastExchange.assistantMessage) {\n grouped.pop();\n }\n }\n\n return grouped;\n }, [messages, hasThreadDepthError]);\n\n const handleSearchQueryClick = (query: string): void => {\n props.onAskAiToggle(false);\n props.setQuery(query);\n };\n\n // Only show the thread depth error if we have assistant messages\n const showThreadDepthError =\n hasThreadDepthError && messages.some((m) => m.role === 'assistant');\n\n return (\n <div className=\"DocSearch-AskAiScreen DocSearch-AskAiScreen-Container\">\n {/* Thread Depth Error */}\n {showThreadDepthError && (\n <div className=\"DocSearch-AskAiScreen-MessageContent DocSearch-AskAiScreen-Error DocSearch-AskAiScreen-Error--ThreadDepth\">\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <p>\n {threadDepthExceededMessage}{' '}\n <button\n type=\"button\"\n className=\"DocSearch-ThreadDepthError-Link\"\n onClick={props.onNewConversation}\n >\n {startNewConversationButtonText}\n </button>{' '}\n to continue.\n </p>\n </div>\n </div>\n )}\n\n <AskAiScreenDisclaimer disclaimerText={disclaimerText} />\n\n <div className=\"DocSearch-AskAiScreen-Body\">\n <div className=\"DocSearch-AskAiScreen-ExchangesList\">\n {exchanges\n .slice()\n .reverse()\n .map((exchange, index) => (\n <AskAiExchangeCard\n key={exchange.id}\n exchange={exchange}\n askAiError={props.askAiError}\n isLastExchange={index === 0}\n loadingStatus={props.status}\n translations={translations}\n tools={tools}\n conversations={props.conversations}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={handleSearchQueryClick}\n onFeedback={props.onFeedback}\n onSelectPromptSuggestion={props.onSelectPromptSuggestion}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../../AskAiScreenState';\nimport { CloseIcon, MessageIcon } from '../../icons';\nimport { Results } from '../../Results';\nimport type { InternalDocSearchHit } from '../../types';\nimport { getCollection } from '../../utils';\n\nexport type RecentConversationsResultsTranslations = Partial<{\n recentConversationsTitle: string;\n removeRecentConversationButtonTitle: string;\n}>;\n\ntype RecentConversationsResultsProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: RecentConversationsResultsTranslations;\n};\n\nexport function RecentConversationsResults({\n translations = {},\n ...props\n}: RecentConversationsResultsProps): JSX.Element | null {\n const {\n recentConversationsTitle = 'Resume AI conversations',\n removeRecentConversationButtonTitle = 'Remove this conversation from history',\n } = translations;\n const recentConversations = getCollection(props.state, 'recentConversations');\n\n if (!recentConversations) {\n return null;\n }\n\n return (\n <Results\n {...props}\n title={recentConversationsTitle}\n collection={recentConversations}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon DocSearch-Hit-icon--start\">\n <MessageIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n title={removeRecentConversationButtonTitle}\n type=\"submit\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../AskAiScreenState';\nimport type { InternalDocSearchHit } from '../types';\n\nimport type { RecentConversationsResultsTranslations } from './ui/RecentConversationsResults';\nimport { RecentConversationsResults } from './ui/RecentConversationsResults';\nimport type { StoredSearchesSectionsTranslations } from './ui/StoredSearchesSections';\nimport { StoredSearchesSections } from './ui/StoredSearchesSections';\n\nexport type AskAiStartScreenTranslations =\n RecentConversationsResultsTranslations & StoredSearchesSectionsTranslations;\n\ntype AskAiStartScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n hasCollections: boolean;\n translations?: AskAiStartScreenTranslations;\n};\n\nexport function AskAiStartScreen({\n translations = {},\n ...props\n}: AskAiStartScreenProps): JSX.Element | null {\n return (\n <div className=\"DocSearch-Dropdown-Container\">\n <RecentConversationsResults {...props} translations={translations} />\n <StoredSearchesSections {...props} translations={translations} />\n </div>\n );\n}\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { CloseIcon, SparklesIcon } from './icons';\nimport { Results } from './Results';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport type { InternalDocSearchHit } from './types';\nimport { getCollection } from './utils';\n\ntype ConversationHistoryScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: ResultsScreenTranslations;\n};\n\nexport function ConversationHistoryScreen({\n onAskAiToggle,\n ...props\n}: ConversationHistoryScreenProps): JSX.Element | null {\n const collection = React.useMemo(\n () => getCollection(props.state, 'recentConversations'),\n [props.state]\n );\n\n React.useEffect(() => {\n if (!collection || collection.items.length === 0) {\n onAskAiToggle(true);\n }\n }, [collection, onAskAiToggle]);\n\n if (!collection) {\n return null;\n }\n\n return (\n <div className=\"DocSearch-Dropdown-Container DocSearch-Conversation-History\">\n <Results\n {...props}\n key={collection.source.sourceId}\n title=\"\"\n translations={props.translations}\n collection={collection}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon\">\n <SparklesIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n type=\"button\"\n className=\"DocSearch-Hit-action-button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { SuggestedQuestionHit } from './types';\n\nexport type NewConversationTranslations = Partial<{\n newConversationTitle: string;\n newConversationDescription: string;\n}>;\n\ninterface NewConversationProps {\n suggestedQuestions?: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationTranslations;\n}\n\nexport function NewConversationScreen({\n translations = {},\n suggestedQuestions = [],\n selectSuggestedQuestion,\n}: NewConversationProps): JSX.Element {\n const {\n newConversationTitle = 'How can I help you today?',\n newConversationDescription = 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.',\n } = translations;\n\n return (\n <div className=\"DocSearch-NewConversationScreen\">\n <h3 className=\"DocSearch-NewConversationScreen-Title\">\n {newConversationTitle}\n </h3>\n <p className=\"DocSearch-NewConversationScreen-Description\">\n {newConversationDescription}\n </p>\n\n <div className=\"DocSearch-NewConversationScreen-SuggestedQuestions\">\n {suggestedQuestions.map((question) => (\n <button\n key={question.objectID}\n type=\"button\"\n className=\"DocSearch-NewConversationScreen-SuggestedQuestion\"\n onClick={() => selectSuggestedQuestion(question)}\n >\n {question.question}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n BaseItem,\n} from '@algolia/autocomplete-core';\nimport type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { AskAiScreen } from './AskAiScreen';\nimport type { AskAiStartScreenTranslations } from './components/AskAiStartScreen';\nimport { AskAiStartScreen } from './components/AskAiStartScreen';\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { DocSearchProps } from './DocSearch';\nimport type { ErrorScreenTranslations } from './ErrorScreen';\nimport { ErrorScreen } from './ErrorScreen';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport type { NoResultsScreenTranslations } from './NoResultsScreen';\nimport { NoResultsScreen } from './NoResultsScreen';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport { ResultsScreen } from './ResultsScreen';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n StoredDocSearchHit,\n SuggestedQuestionHit,\n} from './types';\nimport type { AIMessage, AskAiState, ToolCalls } from './types/AskiAi';\nimport { isQueryEmpty } from './utils';\n\nexport type AskAiScreenStateTranslations = Partial<{\n errorScreen: ErrorScreenTranslations;\n startScreen: AskAiStartScreenTranslations;\n noResultsScreen: NoResultsScreenTranslations;\n resultsScreen: ResultsScreenTranslations;\n askAiScreen: AskAiScreenTranslations;\n newConversation: NewConversationTranslations;\n}>;\n\nexport interface AskAiScreenStateProps<\n TItem extends BaseItem,\n> extends AutocompleteApi<\n TItem,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<TItem>;\n recentSearches: StoredSearchPlugin<StoredDocSearchHit>;\n favoriteSearches: StoredSearchPlugin<StoredDocSearchHit>;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onItemClick: (\n item: InternalDocSearchHit,\n event: KeyboardEvent | MouseEvent\n ) => void;\n onAskAiToggle: (toggle: boolean) => void;\n isAskAiActive: boolean;\n canHandleAskAi: boolean;\n inputRef: React.MutableRefObject<HTMLInputElement | null>;\n hitComponent: DocSearchProps['hitComponent'];\n indexName: string;\n messages: UseChatHelpers<AIMessage>['messages'];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n disableUserPersonalization: boolean;\n resultsFooterComponent: DocSearchProps['resultsFooterComponent'];\n translations: AskAiScreenStateTranslations;\n getMissingResultsUrl?: DocSearchProps['getMissingResultsUrl'];\n hasCollections: boolean;\n onFeedback?: OnAskAiFeedback;\n askAiState: AskAiState;\n selectAskAiQuestion: (toggle: boolean, query: string) => void;\n suggestedQuestions: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n onNewConversation: () => void;\n memoryEnabled?: boolean;\n resultBadgeKey?: string;\n}\n\nexport const AskAiScreenState = React.memo(\n ({\n translations = {},\n selectAskAiQuestion,\n ...props\n }: AskAiScreenStateProps<InternalDocSearchHit>): JSX.Element => {\n const handleSelectPromptSuggestion = React.useCallback(\n (prompt: string) => {\n selectAskAiQuestion(true, prompt);\n },\n [selectAskAiQuestion]\n );\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'conversation-history'\n ) {\n return (\n <ConversationHistoryScreen\n selectAskAiQuestion={selectAskAiQuestion}\n {...props}\n />\n );\n }\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'new-conversation'\n ) {\n return (\n <NewConversationScreen\n translations={translations?.newConversation}\n selectSuggestedQuestion={props.selectSuggestedQuestion}\n suggestedQuestions={props.suggestedQuestions}\n />\n );\n }\n\n if (props.isAskAiActive && props.canHandleAskAi) {\n return (\n <AskAiScreen\n {...props}\n messages={props.messages}\n tools={props.tools}\n status={props.status}\n askAiError={props.askAiError}\n translations={translations?.askAiScreen}\n memoryEnabled={props.memoryEnabled}\n selectAskAiQuestion={selectAskAiQuestion}\n onSelectPromptSuggestion={handleSelectPromptSuggestion}\n />\n );\n }\n\n if (props.state?.status === 'error') {\n return <ErrorScreen translations={translations?.errorScreen} />;\n }\n\n if (isQueryEmpty(props.state.query)) {\n return (\n <AskAiStartScreen\n {...props}\n hasCollections={props.hasCollections}\n translations={translations?.startScreen}\n selectAskAiQuestion={selectAskAiQuestion}\n />\n );\n }\n\n if (!props.hasCollections && !props.canHandleAskAi) {\n return (\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n );\n }\n\n return (\n <>\n <ResultsScreen {...props} translations={translations?.resultsScreen} />\n {props.canHandleAskAi &&\n !props.hasCollections && (\n // if there's one collection it is the ask ai action, show the no results screen\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n )}\n </>\n );\n },\n function areEqual(prevProps, nextProps) {\n const askAiStateChanged =\n prevProps.isAskAiActive !== nextProps.isAskAiActive ||\n prevProps.askAiState !== nextProps.askAiState ||\n prevProps.canHandleAskAi !== nextProps.canHandleAskAi;\n\n // Something triggered an Ask AI related state change, perform a new render\n if (askAiStateChanged) {\n return false;\n }\n\n const isLoading =\n nextProps.state.status === 'loading' ||\n nextProps.state.status === 'stalled';\n\n const isWaitingForCollections =\n nextProps.state.status === 'idle' &&\n !isQueryEmpty(nextProps.state.query) &&\n prevProps.state.query !== nextProps.state.query &&\n prevProps.state.collections === nextProps.state.collections;\n\n return isLoading || isWaitingForCollections;\n }\n);\n","import React from 'react';\nimport type { JSX } from 'react';\n\ntype ModalHeadingProps = {\n heading: string;\n shimmer?: boolean;\n};\n\nexport function ModalHeading({\n heading,\n shimmer = false,\n}: ModalHeadingProps): JSX.Element {\n return (\n <span\n className={`DocSearch-Modal-heading${shimmer ? ' DocSearch-shimmer' : ''}`}\n >\n {heading}\n </span>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n} from '@algolia/autocomplete-core';\nimport React, { type JSX, type RefObject } from 'react';\n\nimport {\n ConversationHistoryIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n StopIcon,\n BackIcon,\n} from '../icons';\nimport { Menu } from '../Menu';\nimport { ModalHeading } from '../ModalHeading';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, AskAiState } from '../types/AskiAi';\nimport { getCollection, isQueryEmpty } from '../utils';\n\nimport { SearchBoxForm } from './ui/SearchBoxForm';\n\nexport type AskAiSearchBoxTranslations = Partial<{\n clearButtonTitle: string;\n clearButtonAriaLabel: string;\n closeButtonText: string;\n closeButtonAriaLabel: string;\n placeholderText: string;\n placeholderTextAskAi: string;\n placeholderTextAskAiStreaming: string;\n enterKeyHint: string;\n enterKeyHintAskAi: string;\n searchInputLabel: string;\n backToKeywordSearchButtonText: string;\n backToKeywordSearchButtonAriaLabel: string;\n newConversationPlaceholder: string;\n conversationHistoryTitle: string;\n startNewConversationText: string;\n viewConversationHistoryText: string;\n threadDepthErrorPlaceholder: string;\n}>;\n\ninterface AskAiSearchBoxProps extends AutocompleteApi<\n InternalDocSearchHit,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<InternalDocSearchHit>;\n autoFocus: boolean;\n inputRef: RefObject<HTMLInputElement | null>;\n onClose: () => void;\n onAskAiToggle: (toggle: boolean) => void;\n onAskAgain: (query: string) => void;\n onStopAskAiStreaming: () => Promise<void>;\n placeholder: string;\n isAskAiActive: boolean;\n askAiStatus: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n isFromSelection: boolean;\n translations?: AskAiSearchBoxTranslations;\n askAiState: AskAiState;\n setAskAiState: (state: AskAiState) => void;\n onNewConversation: () => void;\n onViewConversationHistory: () => void;\n isThreadDepthError?: boolean;\n}\n\nexport function AskAiSearchBox({\n translations = {},\n askAiState,\n onAskAiToggle,\n setAskAiState,\n ...props\n}: AskAiSearchBoxProps): JSX.Element {\n const {\n clearButtonTitle = 'Clear',\n clearButtonAriaLabel = 'Clear the query',\n closeButtonText = 'Close',\n closeButtonAriaLabel = 'Close',\n searchInputLabel = 'Search',\n backToKeywordSearchButtonText = 'Back to keyword search',\n backToKeywordSearchButtonAriaLabel = 'Back to keyword search',\n placeholderTextAskAiStreaming = 'Answering...',\n newConversationPlaceholder = 'Ask a question',\n conversationHistoryTitle = 'My conversation history',\n startNewConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n threadDepthErrorPlaceholder = 'Conversation limit reached',\n } = translations;\n\n const hasRecentConversations = React.useMemo(() => {\n const askAiSource = getCollection(props.state, 'recentConversations');\n\n if (!askAiSource) {\n return false;\n }\n\n return askAiSource.items.length > 0;\n }, [props.state]);\n\n const baseInputProps = props.getInputProps({\n inputElement: props.inputRef.current!,\n autoFocus: props.autoFocus,\n });\n const blockedKeys = new Set(['ArrowUp', 'ArrowDown', 'Enter']);\n const origOnKeyDown = baseInputProps.onKeyDown;\n const origOnChange = baseInputProps.onChange;\n const isAskAiStreaming =\n props.askAiStatus === 'streaming' || props.askAiStatus === 'submitted';\n const renderMoreOptions =\n props.isAskAiActive && askAiState !== 'conversation-history';\n\n // Use the thread depth error state passed from parent\n const isThreadDepthError = props.isThreadDepthError || false;\n let searchPlaceholder = props.placeholder;\n\n if (askAiState === 'new-conversation') {\n searchPlaceholder = newConversationPlaceholder;\n }\n\n // Override placeholder when thread depth error occurs (only in Ask AI mode)\n if (isThreadDepthError && props.isAskAiActive) {\n searchPlaceholder = threadDepthErrorPlaceholder;\n }\n\n let heading: string | null = null;\n\n if (isAskAiStreaming) {\n heading = placeholderTextAskAiStreaming;\n }\n\n if (askAiState === 'conversation-history') {\n heading = conversationHistoryTitle;\n }\n\n // when returning to another status than streaming or submitted, we focus on the input\n React.useEffect(() => {\n if (\n props.askAiStatus !== 'streaming' &&\n props.askAiStatus !== 'submitted' &&\n props.inputRef.current\n ) {\n props.inputRef.current.focus();\n }\n }, [props.askAiStatus, props.inputRef]);\n\n /**\n * We need to block the default behavior of the input when Ask AI is active.\n * This is because the input is used to ask another question when the user\n * presses enter.\n *\n * Learn more on default autocomplete behavior:\n * https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/getDefaultProps.ts.\n */\n const inputProps = {\n enterKeyHint: props.isAskAiActive\n ? ('enter' as const)\n : ('search' as const),\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void => {\n let askAiHandled = false;\n // block these up, down, enter listeners when Ask AI is active\n if (props.isAskAiActive && blockedKeys.has(e.key)) {\n // enter key asks another question\n if (\n e.key === 'Enter' &&\n !isAskAiStreaming &&\n !isQueryEmpty(props.state.query)\n ) {\n props.onAskAgain(props.state.query);\n }\n\n askAiHandled = true;\n }\n\n if (askAiHandled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n origOnKeyDown?.(e);\n },\n onChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n if (props.isAskAiActive) {\n props.setQuery(e.currentTarget.value);\n // block search when Ask AI is active\n // we don't want to trigger the search when the user types\n // we already know they are asking a question\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n origOnChange?.(e);\n },\n disabled: isAskAiStreaming || (isThreadDepthError && props.isAskAiActive),\n };\n\n const handleAskAiBackClick = React.useCallback((): void => {\n // If there's a thread depth error, start a new conversation instead of exiting\n if (isThreadDepthError) {\n props.onNewConversation();\n return;\n }\n\n if (askAiState === 'conversation-history') {\n onAskAiToggle(true);\n setAskAiState('initial');\n return;\n }\n\n onAskAiToggle(false);\n }, [askAiState, isThreadDepthError, onAskAiToggle, setAskAiState, props]);\n\n const leadingElement = props.isAskAiActive ? (\n <button\n type=\"button\"\n tabIndex={0}\n className=\"DocSearch-Action DocSearch-AskAi-Return\"\n title={backToKeywordSearchButtonText}\n aria-label={backToKeywordSearchButtonAriaLabel}\n onClick={handleAskAiBackClick}\n >\n <BackIcon />\n </button>\n ) : undefined;\n const inputOverlay = heading ? (\n <ModalHeading heading={heading} shimmer={isAskAiStreaming} />\n ) : null;\n const actionsBeforeClose = (\n <>\n {!props.isAskAiActive && (\n <>\n <button\n className=\"DocSearch-Clear\"\n type=\"reset\"\n aria-label={clearButtonAriaLabel}\n hidden={!props.state.query}\n tabIndex={props.state.query ? 0 : -1}\n aria-hidden={!props.state.query ? 'true' : 'false'}\n >\n {clearButtonTitle}\n </button>\n\n {props.state.query && <div className=\"DocSearch-Divider\" />}\n </>\n )}\n\n {isAskAiStreaming && (\n <>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-StopStreaming\"\n onClick={props.onStopAskAiStreaming}\n >\n <StopIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n\n {renderMoreOptions && (\n <>\n <Menu>\n <Menu.Trigger className=\"DocSearch-Action\">\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item onClick={props.onNewConversation}>\n <NewConversationIcon />\n {startNewConversationText}\n </Menu.Item>\n {hasRecentConversations && (\n <Menu.Item onClick={props.onViewConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n </>\n );\n\n return (\n <SearchBoxForm\n {...props}\n placeholder={searchPlaceholder}\n clearButtonTitle={clearButtonTitle}\n clearButtonAriaLabel={clearButtonAriaLabel}\n closeButtonText={closeButtonText}\n closeButtonAriaLabel={closeButtonAriaLabel}\n searchInputLabel={searchInputLabel}\n leadingElement={leadingElement}\n inputOverlay={inputOverlay}\n hideInput={Boolean(heading)}\n actionsBeforeClose={actionsBeforeClose}\n inputProps={inputProps}\n />\n );\n}\n","import type { AutocompleteSource } from '@algolia/autocomplete-core';\nimport type { SearchResponse } from 'algoliasearch/lite';\n\nimport type { DocSearchTransformClient } from '../DocSearch';\nimport type { PromptSuggestions } from '../DocSearchAI';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, PromptSuggestion } from '../types/AskiAi';\n\nimport { SOURCE_IDS } from './collections';\n\nconst MAX_RECENT_CONVERSATIONS_DISPLAYED = 3;\n\nconst EMPTY_RESULT_CONTENT = {\n value: '',\n matchLevel: 'none',\n matchedWords: [],\n} satisfies InternalDocSearchHit['_highlightResult']['content'];\nconst EMPTY_HIERARCHY_HIGHLIGHT_RESULT = {\n lvl0: EMPTY_RESULT_CONTENT,\n lvl1: EMPTY_RESULT_CONTENT,\n lvl2: EMPTY_RESULT_CONTENT,\n lvl3: EMPTY_RESULT_CONTENT,\n lvl4: EMPTY_RESULT_CONTENT,\n lvl5: EMPTY_RESULT_CONTENT,\n lvl6: EMPTY_RESULT_CONTENT,\n} satisfies InternalDocSearchHit['_highlightResult']['hierarchy'];\nconst EMPTY_HIGHLIGHT_RESULT: InternalDocSearchHit['_highlightResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\nconst EMPTY_SNIPPET_RESULT: InternalDocSearchHit['_snippetResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\n\nexport function buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n}: {\n conversations: { getAll: () => unknown[] };\n disableUserPersonalization: boolean;\n setMessages: (messages: AIMessage[]) => void;\n onAskAiToggle: (toggle: boolean) => void;\n}): Array<\n AutocompleteSource<InternalDocSearchHit & { messages?: AIMessage[] }>\n> {\n return [\n {\n sourceId: SOURCE_IDS.recentConversations,\n getItems(): InternalDocSearchHit[] {\n if (disableUserPersonalization) {\n return [];\n }\n return (\n conversations.getAll() as unknown as InternalDocSearchHit[]\n ).slice(0, MAX_RECENT_CONVERSATIONS_DISPLAYED);\n },\n onSelect({ item }): void {\n if (item.messages) {\n setMessages(item.messages);\n onAskAiToggle(true);\n }\n },\n },\n ];\n}\n\nfunction createAskAiHit({\n query,\n objectID,\n lvl0,\n}: {\n query: string;\n objectID: string;\n lvl0: string;\n}): InternalDocSearchHit {\n return {\n type: 'askAI',\n query,\n url_without_anchor: '',\n objectID,\n content: null,\n url: '',\n anchor: null,\n hierarchy: {\n lvl0,\n lvl1: query,\n lvl2: null,\n lvl3: null,\n lvl4: null,\n lvl5: null,\n lvl6: null,\n },\n _highlightResult: EMPTY_HIGHLIGHT_RESULT,\n _snippetResult: EMPTY_SNIPPET_RESULT,\n __docsearch_parent: null,\n };\n}\n\nasync function getPromptSuggestions({\n query,\n indexName,\n searchClient,\n hitsPerPage = 3,\n}: {\n query: string;\n indexName: string;\n searchClient: DocSearchTransformClient;\n hitsPerPage?: number;\n}): Promise<InternalDocSearchHit[]> {\n try {\n const { results } = await searchClient.search<PromptSuggestion>({\n requests: [\n {\n query,\n indexName,\n hitsPerPage,\n attributesToRetrieve: ['prompt'],\n },\n ],\n });\n\n const res = results[0] as SearchResponse<PromptSuggestion>;\n\n return res.hits.map((hit) =>\n createAskAiHit({\n query: hit.prompt,\n objectID: hit.objectID,\n lvl0: 'Prompt Suggestions',\n })\n );\n // NOTE: Not checking the exception here and just returning empty array since this isn't the hot path\n } catch {\n return [];\n }\n}\n\nexport async function buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions,\n searchClient,\n}: {\n query: string;\n handleSelectAskAiQuestion: (toggle: boolean, query: string) => void;\n promptSuggestionsOptions?: PromptSuggestions;\n searchClient: DocSearchTransformClient;\n}): Promise<Array<AutocompleteSource<InternalDocSearchHit>>> {\n const promptSuggestions = promptSuggestionsOptions\n ? await getPromptSuggestions({\n query,\n indexName: promptSuggestionsOptions.indexName,\n hitsPerPage: promptSuggestionsOptions.hitsPerPage,\n searchClient,\n })\n : [];\n\n return [\n {\n sourceId: SOURCE_IDS.askAI,\n getItems(): InternalDocSearchHit[] {\n return [\n createAskAiHit({ query, objectID: 'ask-ai-button', lvl0: 'Ask AI' }),\n ...promptSuggestions,\n ];\n },\n onSelect({ item }): void {\n if (item.type === 'askAI' && item.query) {\n handleSelectAskAiQuestion(true, item.query);\n }\n },\n },\n ];\n}\n","import { createAutocomplete } from '@algolia/autocomplete-core';\nimport type { InitialAskAiMessage, OnAskAiToggle } from '@docsearch/core';\nimport type { ChatRequestOptions } from 'ai';\nimport React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateTranslations } from './AskAiScreenState';\nimport { AskAiScreenState } from './AskAiScreenState';\nimport type { AskAiSearchBoxTranslations } from './components/AskAiSearchBox';\nimport { AskAiSearchBox } from './components/AskAiSearchBox';\nimport type { FacetBarTranslations } from './components/FacetBar';\nimport { FacetBar } from './components/FacetBar';\nimport { ModalShell } from './components/ui/ModalShell';\nimport type { DocSearchAIProps } from './DocSearchAI';\nimport type { FooterTranslations } from './Footer';\nimport { Footer } from './Footer';\nimport { Hit } from './Hit';\nimport { useDocSearchFacets } from './hooks/useDocSearchFacets';\nimport { useSendItemClickEvent } from './hooks/useDocSearchInsights';\nimport { useInitialModalQuery } from './hooks/useInitialModalQuery';\nimport { useModalEnvironment } from './hooks/useModalEnvironment';\nimport { useModalRefs } from './hooks/useModalRefs';\nimport { useRefreshOnInitialQuery } from './hooks/useRefreshOnInitialQuery';\nimport { useSaveRecentSearch } from './hooks/useSaveRecentSearch';\nimport { useStoredDocSearches } from './hooks/useStoredDocSearches';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport type {\n DocSearchState,\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiMessage,\n StoredAskAiState,\n SuggestedQuestionHit,\n} from './types';\nimport { type AskAiState } from './types/AskiAi';\nimport { useAskAi } from './useAskAi';\nimport { useSearchClient } from './useSearchClient';\nimport { useSuggestedQuestions } from './useSuggestedQuestions';\nimport {\n identity,\n isModifierEvent,\n isQueryEmpty,\n noop,\n scrollTo as scrollToUtils,\n SOURCE_IDS,\n} from './utils';\nimport {\n buildDummyAskAiHit,\n isThreadDepthError,\n EMPTY_TOOLS,\n} from './utils/ai';\nimport {\n buildAskAiActionSources,\n buildRecentConversationSources,\n} from './utils/createAskAiSources';\nimport {\n buildNoQuerySources,\n buildQuerySources,\n type BuildQuerySourcesState,\n} from './utils/createDocSearchSources';\nimport { normalizeDocSearchIndexes } from './utils/normalizeDocSearchIndexes';\n\nexport type DocSearchAskAiModalTranslations = AskAiScreenStateTranslations &\n Partial<{\n searchBox: AskAiSearchBoxTranslations;\n newConversation: NewConversationTranslations;\n footer: FooterTranslations;\n facets: FacetBarTranslations;\n }>;\n\nexport type DocSearchAskAiModalProps = DocSearchAIProps & {\n initialScrollY: number;\n onAskAiToggle: OnAskAiToggle;\n onClose?: () => void;\n isAskAiActive?: boolean;\n translations?: DocSearchAskAiModalTranslations;\n isHybridModeSupported?: boolean;\n};\n\nexport function DocSearchAskAiModal({\n appId,\n apiKey,\n askAi,\n maxResultsPerGroup,\n theme,\n onClose = noop,\n transformItems = identity,\n hitComponent = Hit,\n resultsFooterComponent = (): JSX.Element | null => null,\n navigator,\n initialScrollY = 0,\n transformSearchClient = identity,\n disableUserPersonalization = false,\n initialQuery: initialQueryFromProp = '',\n translations = {},\n getMissingResultsUrl,\n insights = false,\n onAskAiToggle,\n interceptAskAiEvent,\n isAskAiActive = false,\n recentSearchesLimit = 7,\n recentSearchesWithFavoritesLimit = 4,\n indices,\n facets,\n isHybridModeSupported = false,\n ...props\n}: DocSearchAskAiModalProps): JSX.Element {\n const {\n footer: footerTranslations,\n searchBox: searchBoxTranslations,\n facets: facetBarTranslations,\n ...screenStateTranslations\n } = translations;\n const [state, setState] = React.useState<\n DocSearchState<InternalDocSearchHit>\n >({\n query: '',\n collections: [],\n completion: null,\n context: {},\n isOpen: false,\n activeItemId: null,\n status: 'idle',\n });\n\n // check if the instance is configured to handle ask ai\n const canHandleAskAi = Boolean(askAi);\n\n let placeholder =\n translations?.searchBox?.placeholderText ||\n props.placeholder ||\n 'Search docs';\n\n if (canHandleAskAi) {\n placeholder =\n translations?.searchBox?.placeholderText ||\n 'Search docs or ask AI a question';\n }\n\n if (isAskAiActive) {\n placeholder =\n translations?.searchBox?.placeholderTextAskAi ||\n 'Ask another question...';\n }\n\n const {\n containerRef,\n modalRef,\n formElementRef,\n dropdownRef,\n inputRef,\n snippetLength,\n } = useModalRefs();\n const { initialQuery, initialQueryFromSelection } =\n useInitialModalQuery(initialQueryFromProp);\n\n const searchClient = useSearchClient(appId, apiKey, transformSearchClient);\n\n const askAiConfig = typeof askAi === 'object' ? askAi : null;\n const askAiConfigurationId = askAiConfig\n ? askAiConfig.agentId\n : (askAi as string);\n const askAiSearchParameters = askAiConfig?.searchParameters;\n const [askAiState, setAskAiState] = React.useState<AskAiState>('initial');\n const suggestedQuestions = useSuggestedQuestions({\n agentId: askAiConfigurationId,\n searchClient,\n suggestedQuestionsEnabled: askAiConfig?.suggestedQuestions,\n });\n const memoryEnabled = askAiConfig?.memory?.enabled ?? false;\n const tools = askAiConfig?.tools ?? EMPTY_TOOLS;\n\n const indexes = React.useMemo(\n () =>\n normalizeDocSearchIndexes({\n indices,\n }),\n [indices]\n );\n const defaultIndexName = indexes[0].name;\n\n const autocompleteRef =\n React.useRef<\n ReturnType<\n typeof createAutocomplete<\n InternalDocSearchHit,\n React.FormEvent<HTMLFormElement>,\n React.MouseEvent,\n React.KeyboardEvent\n >\n >\n >(undefined);\n\n const {\n visibleFacets,\n facetSelections,\n facetSelectionsRef,\n handleFacetSelectionChange,\n clearFacetSelections,\n } = useDocSearchFacets({\n facets,\n indexes,\n searchClient,\n onSelectionsChange: () => autocompleteRef.current?.refresh(),\n });\n\n const { favoriteSearches, recentSearches } = useStoredDocSearches({\n defaultIndexName,\n recentSearchesLimit,\n recentSearchesWithFavoritesLimit,\n });\n\n const [stoppedStream, setStoppedStream] = React.useState(false);\n\n const {\n chatId,\n messages,\n status,\n setMessages,\n sendMessage,\n stopAskAiStreaming,\n askAiError,\n sendFeedback,\n conversations,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n agentId: askAiConfigurationId,\n apiKey: askAiConfig?.apiKey || apiKey,\n appId: askAiConfig?.appId || appId,\n searchParameters: askAiSearchParameters,\n tools,\n memory: askAiConfig?.memory,\n indices: askAiConfig?.indices,\n });\n\n const prevStatus = React.useRef(status);\n React.useEffect(() => {\n if (disableUserPersonalization) {\n return;\n }\n // if we just transitioned from \"streaming\" → \"ready\", persist\n if (prevStatus.current === 'streaming' && status === 'ready') {\n // if we stopped the stream, store it on the most recent message\n if (stoppedStream && messages.at(-1)) {\n messages.at(-1)!.metadata = {\n stopped: true,\n };\n }\n\n for (const part of messages[0].parts) {\n if (part.type === 'text') {\n conversations.add(buildDummyAskAiHit(part.text, messages, chatId));\n }\n }\n }\n prevStatus.current = status;\n }, [\n status,\n messages,\n conversations,\n disableUserPersonalization,\n stoppedStream,\n chatId,\n ]);\n\n // Check if there's a thread depth error (AI-217)\n const hasThreadDepthError = React.useMemo(() => {\n return (\n status === 'error' && isThreadDepthError(askAiError as Error | undefined)\n );\n }, [status, askAiError]);\n\n const saveRecentSearch = useSaveRecentSearch({\n favoriteSearches,\n recentSearches,\n disableUserPersonalization,\n });\n const sendItemClickEvent = useSendItemClickEvent(state);\n\n const handleSelectAskAiQuestion = React.useCallback(\n (\n toggle: boolean,\n query: string,\n suggestedQuestion: SuggestedQuestionHit | undefined = undefined\n ) => {\n if (toggle) {\n const initialMessage: InitialAskAiMessage = {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n // Consumer handled it. Avoid *all* default Ask AI behavior.\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n return;\n }\n }\n\n if (toggle && askAiState === 'new-conversation') {\n setAskAiState('initial');\n }\n\n onAskAiToggle(toggle, {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n });\n\n // If we're in hybrid mode, we don't need to send the message,\n // it will be handled by the Sidepanel.\n if (isHybridModeSupported) return;\n\n setStoppedStream(false);\n\n const messageOptions: ChatRequestOptions = {};\n\n if (suggestedQuestion) {\n messageOptions.body = {\n suggestedQuestionId: suggestedQuestion.objectID,\n };\n }\n\n sendMessage(\n {\n role: 'user',\n parts: [\n {\n type: 'text',\n text: query,\n },\n ],\n },\n messageOptions\n );\n\n if (dropdownRef.current) {\n // some test environments (like jsdom) don't implement element.scrollTo\n const el = dropdownRef.current;\n if (typeof (el as any).scrollTo === 'function') {\n el.scrollTo({ top: 0, behavior: 'smooth' });\n } else {\n // fallback for environments without scrollTo support\n el.scrollTop = 0;\n }\n }\n\n // clear the query\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n },\n [\n askAiState,\n onAskAiToggle,\n isHybridModeSupported,\n sendMessage,\n dropdownRef,\n interceptAskAiEvent,\n ]\n );\n\n // feedback handler\n const handleFeedbackSubmit = React.useCallback<OnAskAiFeedback>(\n async (messageId, feedback): Promise<void> => {\n if (!askAiConfigurationId || !appId) return;\n await sendFeedback(messageId, feedback);\n },\n [askAiConfigurationId, appId, sendFeedback]\n );\n\n if (!autocompleteRef.current) {\n autocompleteRef.current = createAutocomplete({\n id: 'docsearch',\n defaultActiveItemId: 0,\n openOnFocus: true,\n initialState: {\n query: initialQuery,\n context: {\n searchSuggestions: [],\n },\n },\n insights: Boolean(insights),\n navigator,\n onStateChange(changes) {\n setState(changes.state);\n },\n async getSources({ query, state: sourcesState, setContext, setStatus }) {\n if (isQueryEmpty(query)) {\n const noQuerySources = buildNoQuerySources({\n recentSearches,\n favoriteSearches,\n saveRecentSearch,\n onClose,\n disableUserPersonalization,\n });\n\n const recentConversationSource = canHandleAskAi\n ? buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n })\n : [];\n return [...recentConversationSource, ...noQuerySources];\n }\n\n const querySourcesState: BuildQuerySourcesState = {\n context: sourcesState.context,\n };\n\n const algoliaSourcesPromise = buildQuerySources({\n query,\n state: querySourcesState,\n setContext,\n setStatus,\n searchClient,\n indexes,\n snippetLength,\n insights: Boolean(insights),\n appId,\n apiKey,\n maxResultsPerGroup,\n transformItems,\n saveRecentSearch,\n onClose,\n facetSelections: facetSelectionsRef,\n });\n\n const askAiSourcesPromise = canHandleAskAi\n ? buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions: askAiConfig?.promptSuggestions,\n searchClient,\n })\n : Promise.resolve([]);\n\n const [askAiSources, algoliaSources] = await Promise.all([\n askAiSourcesPromise,\n algoliaSourcesPromise,\n ]);\n\n // Combine Algolia results (once resolved) with the Ask AI source\n return [...askAiSources, ...algoliaSources];\n },\n });\n }\n\n const autocomplete = autocompleteRef.current;\n\n const { getEnvironmentProps, getRootProps, refresh } = autocomplete;\n\n useModalEnvironment({\n getEnvironmentProps,\n containerRef,\n dropdownRef,\n formElementRef,\n inputRef,\n initialScrollY,\n modalRef,\n snippetLength,\n theme,\n });\n\n React.useEffect(() => {\n if (dropdownRef.current && !isAskAiActive) {\n scrollToUtils(dropdownRef.current);\n }\n }, [state.query, isAskAiActive, dropdownRef]);\n\n useRefreshOnInitialQuery({ initialQuery, inputRef, refresh });\n\n const hasCurrentMessages = messages.length > 0;\n\n // Refresh the autocomplete results when ask ai is toggled off\n // helps return to the previous ac state and start screen\n React.useEffect(() => {\n if (!isAskAiActive) {\n autocomplete.refresh();\n\n if (hasCurrentMessages) {\n startNewConversation();\n }\n }\n }, [isAskAiActive, autocomplete, startNewConversation, hasCurrentMessages]);\n\n // Track external state in order to manage internal askAiState\n React.useEffect(() => {\n setAskAiState('initial');\n }, [isAskAiActive, setAskAiState]);\n\n const onStopAskAiStreaming = async (): Promise<void> => {\n setStoppedStream(true);\n\n await stopAskAiStreaming();\n };\n\n const handleNewConversation = (): void => {\n startNewConversation();\n setAskAiState('new-conversation');\n };\n\n const handleViewConversationHistory = (): void => {\n setAskAiState('conversation-history');\n };\n\n const selectSuggestedQuestion = (\n suggestedQuestion: SuggestedQuestionHit\n ): void => {\n handleSelectAskAiQuestion(\n true,\n suggestedQuestion.question,\n suggestedQuestion\n );\n };\n\n // hide the dropdown on idle and no collections\n let showDocsearchDropdown = true;\n const hasCollections = state.collections.some(\n (collection) =>\n collection.source.sourceId !== SOURCE_IDS.askAI &&\n collection.items.length > 0\n );\n if (\n state.status === 'idle' &&\n hasCollections === false &&\n isQueryEmpty(state.query) &&\n !isAskAiActive\n ) {\n showDocsearchDropdown = false;\n }\n\n return (\n <ModalShell\n state={state}\n containerRef={containerRef}\n modalRef={modalRef}\n formElementRef={formElementRef}\n dropdownRef={dropdownRef}\n getRootProps={getRootProps}\n showDropdown={showDocsearchDropdown}\n searchBox={\n <AskAiSearchBox\n {...autocomplete}\n state={state}\n placeholder={placeholder || 'Search docs'}\n autoFocus={isQueryEmpty(initialQuery)}\n inputRef={inputRef}\n isFromSelection={\n Boolean(initialQuery) && initialQuery === initialQueryFromSelection\n }\n translations={searchBoxTranslations}\n isAskAiActive={isAskAiActive}\n askAiStatus={status}\n askAiError={askAiError}\n askAiState={askAiState}\n setAskAiState={setAskAiState}\n isThreadDepthError={\n hasThreadDepthError && askAiState !== 'new-conversation'\n }\n onClose={onClose}\n onAskAiToggle={onAskAiToggle}\n onAskAgain={(query) => {\n handleSelectAskAiQuestion(true, query);\n }}\n onStopAskAiStreaming={onStopAskAiStreaming}\n onNewConversation={handleNewConversation}\n onViewConversationHistory={handleViewConversationHistory}\n />\n }\n filterBar={\n !isAskAiActive && !isQueryEmpty(state.query) ? (\n <FacetBar\n facets={visibleFacets}\n selections={facetSelections}\n translations={facetBarTranslations}\n clearSelections={clearFacetSelections}\n onSelectionChange={handleFacetSelectionChange}\n />\n ) : null\n }\n screenState={\n <AskAiScreenState\n {...autocomplete}\n indexName={defaultIndexName}\n state={state}\n hitComponent={hitComponent}\n resultsFooterComponent={resultsFooterComponent}\n disableUserPersonalization={disableUserPersonalization}\n recentSearches={recentSearches}\n favoriteSearches={favoriteSearches}\n conversations={conversations}\n inputRef={inputRef}\n translations={screenStateTranslations}\n getMissingResultsUrl={getMissingResultsUrl}\n isAskAiActive={isAskAiActive}\n canHandleAskAi={canHandleAskAi}\n messages={messages}\n tools={tools}\n askAiError={askAiError}\n status={status}\n hasCollections={hasCollections}\n askAiState={askAiState}\n selectAskAiQuestion={handleSelectAskAiQuestion}\n suggestedQuestions={suggestedQuestions}\n selectSuggestedQuestion={selectSuggestedQuestion}\n memoryEnabled={memoryEnabled}\n resultBadgeKey={props.resultBadgeKey}\n onAskAiToggle={onAskAiToggle}\n onNewConversation={handleNewConversation}\n onItemClick={(item, event) => {\n if (item.type === 'askAI' && item.query) {\n if (item.anchor === 'stored' && 'messages' in item) {\n const hitMessages = item.messages as StoredAskAiMessage[];\n restoreConversation(\n hitMessages,\n (item as StoredAskAiState).chatId\n );\n const initialMessage: InitialAskAiMessage = {\n query: item.query,\n messageId: hitMessages[0].id,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n event.preventDefault();\n return;\n }\n\n onAskAiToggle(true, initialMessage);\n } else {\n handleSelectAskAiQuestion(true, item.query);\n }\n setAskAiState('initial');\n event.preventDefault();\n return;\n }\n\n sendItemClickEvent(item);\n saveRecentSearch(item);\n if (!isModifierEvent(event)) {\n onClose();\n }\n }}\n onFeedback={handleFeedbackSubmit}\n />\n }\n footer={\n <Footer\n translations={footerTranslations}\n isAskAiActive={isAskAiActive}\n />\n }\n onClose={onClose}\n />\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DocSearchAskAiModal-C_sH1j8Y.js","names":[],"sources":["../../src/icons/MessageIcon.tsx","../../src/AggregatedSearchBlock.tsx","../../src/AskAiScreen.tsx","../../src/components/ui/RecentConversationsResults.tsx","../../src/components/AskAiStartScreen.tsx","../../src/ConversationHistoryScreen.tsx","../../src/NewConversationScreen.tsx","../../src/AskAiScreenState.tsx","../../src/ModalHeading.tsx","../../src/components/AskAiSearchBox.tsx","../../src/utils/createAskAiSources.ts","../../src/DocSearchAskAiModal.tsx"],"sourcesContent":["import React, { type JSX } from 'react';\n\nexport function MessageIcon(): JSX.Element {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"13\"\n height=\"13\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n );\n}\n","import React, { type JSX, Fragment } from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { SearchIcon } from './icons';\n\ninterface AggregatedSearchBlockProps {\n queries: string[];\n translations: AskAiScreenTranslations;\n onSearchQueryClick: (query: string) => void;\n}\n\n// allow translators to return either simple string parts or a fully custom node\nexport interface AggregatedToolCallParts {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n}\n\n// default english implementation (\"Searched for \\\"A\\\", \\\"B\\\" and \\\"C\\\"\")\nconst defaultAggregatedToolCallParts: AggregatedToolCallParts = {\n before: 'Searched for ',\n separator: ', ',\n lastSeparator: ' and ',\n after: '',\n};\n\nexport function AggregatedSearchBlock({\n queries,\n translations,\n onSearchQueryClick,\n}: AggregatedSearchBlockProps): JSX.Element | null {\n // no queries? no render\n if (queries.length === 0) return null;\n\n // if the translator provides a fully custom node, render it and bail out.\n if (typeof translations.aggregatedToolCallNode === 'function') {\n return (\n <>{translations.aggregatedToolCallNode(queries, onSearchQueryClick)}</>\n );\n }\n\n // otherwise fall back to the classic english-pattern renderer.\n const parts = translations.aggregatedToolCallText\n ? translations.aggregatedToolCallText(queries)\n : defaultAggregatedToolCallParts;\n\n const {\n before = '',\n separator = ', ',\n lastSeparator = ' and ',\n after = '',\n } = parts || {};\n\n return (\n <div className=\"DocSearch-AskAiScreen-MessageContent-Tool Tool--AggregatedResult\">\n <SearchIcon size={18} />\n <span>\n {before && <span>{before}</span>}\n {queries.map((q, idx) => (\n // eslint-disable-next-line react/no-array-index-key\n <Fragment key={q + idx}>\n <span\n role=\"button\"\n tabIndex={0}\n className=\"DocSearch-AskAiScreen-MessageContent-Tool-Query\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n onSearchQueryClick(q);\n }\n }}\n onClick={() => onSearchQueryClick(q)}\n >\n &quot;{q}&quot;\n </span>\n {idx < queries.length - 2 && separator}\n {idx === queries.length - 2 && lastSeparator}\n </Fragment>\n ))}\n {after && <span>{after}</span>}\n </span>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport React, { type JSX, useMemo } from 'react';\n\nimport { AggregatedSearchBlock } from './AggregatedSearchBlock';\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { ConversationPromptSuggestions } from './components/ConversationPromptSuggestions';\nimport { FeedbackActions } from './components/FeedbackActions';\nimport { SourcesPanel } from './components/SourcesPanel';\nimport { ToolCall, type ToolCallTranslations } from './components/ToolCall';\nimport { AlertIcon, LoadingIcon, SparklesIcon } from './icons';\nimport { MemoizedMarkdown } from './MemoizedMarkdown';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n} from './types';\nimport { type AIMessage, type ToolCalls } from './types/AskiAi';\nimport {\n extractLinksFromMessage,\n getMessageContent,\n isThreadDepthError,\n isAIToolPart,\n getAgentPromptSuggestions,\n} from './utils/ai';\nimport { groupConsecutiveToolResults } from './utils/groupConsecutiveToolResults';\n\nexport type AskAiScreenTranslations = Partial<\n // Inherit the shared tool-call translations, but expose the search-related\n // keys under AskAiScreen's own public names (see mapping below).\n Omit<ToolCallTranslations, 'searchingText' | 'toolCallResultText'> & {\n // Misc texts\n disclaimerText: string;\n /** Text shown describing a singular related source. */\n relatedSourcesText: string;\n /** Text shown describing multiple related sources. */\n relatedSourcesTextPlural: string;\n thinkingText: string;\n copyButtonText: string;\n copyButtonCopiedText: string;\n // Feedback buttons\n copyButtonTitle: string;\n likeButtonTitle: string;\n dislikeButtonTitle: string;\n thanksForFeedbackText: string;\n // Negative feedback note panel\n feedbackPanelTitle: string;\n feedbackDetailsPlaceholder: string;\n feedbackDisclaimerText: string;\n feedbackSubmitButtonText: string;\n feedbackCloseButtonTitle: string;\n feedbackTagIncorrect: string;\n feedbackTagNotWhatIAsked: string;\n feedbackTagSlowOrBuggy: string;\n feedbackTagStyleOrTone: string;\n feedbackTagSafetyOrLegal: string;\n feedbackTagOther: string;\n // Tool call texts\n /**\n * Text shown while assistant is performing search tool call. Maps to\n * `ToolCallTranslations.searchingText`.\n */\n duringToolCallText: string;\n /**\n * Text shown while assistant is finished performing tool call. Maps to\n * `ToolCallTranslations.toolCallResultText`.\n */\n afterToolCallText: string;\n /**\n * Build the full jsx element for the aggregated search block. If provided,\n * completely overrides the default english renderer.\n */\n aggregatedToolCallNode?: (\n queries: string[],\n onSearchQueryClick: (query: string) => void\n ) => React.ReactNode;\n /**\n * Generate the list connective parts only (backwards compatibility).\n * Receives full list of queries and should return translation parts for\n * before/after/separators. Example: (qs) => ({ before: 'searched for ',\n * separator: ', ', lastSeparator: ' and ', after: '' }).\n */\n aggregatedToolCallText?: (queries: string[]) => {\n before?: string;\n separator?: string;\n lastSeparator?: string;\n after?: string;\n };\n /** Message that's shown when user has stopped the streaming of a message. */\n stoppedStreamingText: string;\n /** Error title shown if there is an error while chatting. */\n errorTitleText: string;\n /** Message shown when thread depth limit is exceeded (AI-217 error). */\n threadDepthExceededMessage: string;\n /** Button text for starting a new conversation after thread depth error. */\n startNewConversationButtonText: string;\n suggestedPromptsTitleText: string;\n }\n>;\n\n/**\n * Maps AskAiScreen's public translation keys to the shared\n * `ToolCallTranslations` shape consumed by the `ToolCall` component, applying\n * default English values.\n */\nfunction toToolCallTranslations(\n translations: AskAiScreenTranslations\n): ToolCallTranslations {\n const {\n preToolCallText = 'Searching...',\n duringToolCallText = 'Searching...',\n afterToolCallText = 'Searched for',\n savedMemoryToolResultText = 'Saved to memory',\n memoryToolResultText = 'Used memory to enhance results',\n } = translations;\n\n return {\n preToolCallText,\n searchingText: duringToolCallText,\n toolCallResultText: afterToolCallText,\n savedMemoryToolResultText,\n memoryToolResultText,\n };\n}\n\ntype AskAiScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n messages: AIMessage[];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n translations?: AskAiScreenTranslations;\n onNewConversation: () => void;\n onSelectPromptSuggestion: (prompt: string) => void;\n memoryEnabled?: boolean;\n};\n\ninterface AskAiScreenHeaderProps {\n disclaimerText: string;\n}\n\nexport interface Exchange {\n id: string;\n userMessage: AIMessage;\n assistantMessage: AIMessage | null;\n}\n\nfunction AskAiScreenDisclaimer({\n disclaimerText,\n}: AskAiScreenHeaderProps): JSX.Element {\n return (\n <p className=\"DocSearch-AskAiScreen-Disclaimer\">\n <SparklesIcon /> {disclaimerText}\n </p>\n );\n}\n\ninterface AskAiExchangeCardProps {\n exchange: Exchange;\n askAiError?: Error;\n isLastExchange: boolean;\n loadingStatus: UseChatHelpers<AIMessage>['status'];\n onSearchQueryClick: (query: string) => void;\n translations: AskAiScreenTranslations;\n tools: ToolCalls;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onFeedback?: OnAskAiFeedback;\n memoryEnabled?: boolean;\n onSelectPromptSuggestion: (prompt: string) => void;\n}\n\nfunction AskAiExchangeCard({\n exchange,\n askAiError,\n isLastExchange,\n loadingStatus,\n onSearchQueryClick,\n translations,\n tools,\n conversations,\n onFeedback,\n memoryEnabled,\n onSelectPromptSuggestion,\n}: AskAiExchangeCardProps): JSX.Element {\n const { userMessage, assistantMessage } = exchange;\n\n const {\n stoppedStreamingText = 'You stopped this response',\n errorTitleText = 'Chat error',\n relatedSourcesText,\n relatedSourcesTextPlural,\n suggestedPromptsTitleText = 'Suggested prompts',\n } = translations;\n\n const toolCallTranslations = useMemo(\n () => toToolCallTranslations(translations),\n [translations]\n );\n\n const isThreadDepth = isThreadDepthError(askAiError);\n\n const assistantContent = useMemo(\n () => getMessageContent(assistantMessage),\n [assistantMessage]\n );\n const userContent = useMemo(\n () => getMessageContent(userMessage),\n [userMessage]\n );\n\n const urlsToDisplay = React.useMemo(\n () => extractLinksFromMessage(assistantMessage),\n [assistantMessage]\n );\n\n const displayParts = React.useMemo(() => {\n return groupConsecutiveToolResults(assistantMessage?.parts || []);\n }, [assistantMessage]);\n\n const promptSuggestions = useMemo(() => {\n if (!isLastExchange) return [];\n return getAgentPromptSuggestions(assistantMessage?.parts || []);\n }, [assistantMessage, isLastExchange]);\n\n const wasStopped =\n userMessage.metadata?.stopped || assistantMessage?.metadata?.stopped;\n\n const showActions =\n !wasStopped &&\n (!isLastExchange ||\n (isLastExchange &&\n loadingStatus === 'ready' &&\n Boolean(assistantMessage)));\n\n const isThinking =\n ['submitted', 'streaming'].includes(loadingStatus) &&\n isLastExchange &&\n !displayParts.some((part) => part.type !== 'step-start');\n\n const messageId = assistantMessage?.id || exchange.id;\n\n return (\n <div className=\"DocSearch-AskAiScreen-Response-Container\">\n <div className=\"DocSearch-AskAiScreen-Response\">\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--user\">\n <p className=\"DocSearch-AskAiScreen-Query\">{userContent ?? ''}</p>\n </div>\n <div className=\"DocSearch-AskAiScreen-Message DocSearch-AskAiScreen-Message--assistant\">\n <div className=\"DocSearch-AskAiScreen-MessageContent\">\n {loadingStatus === 'error' &&\n askAiError &&\n isLastExchange &&\n !isThreadDepth && (\n <div className=\"DocSearch-AskAiScreen-Error\" role=\"alert\">\n <AlertIcon aria-hidden=\"true\" />\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <h4 className=\"DocSearch-AskAiScreen-Error-Title\">\n {errorTitleText}\n </h4>\n <MemoizedMarkdown\n content={askAiError.message}\n copyButtonText=\"\"\n copyButtonCopiedText=\"\"\n isStreaming={false}\n />\n </div>\n </div>\n )}\n {isThinking && (\n <div\n className=\"DocSearch-AskAiScreen-MessageContent-Thinking\"\n role=\"status\"\n >\n <span className=\"DocSearch-shimmer\">\n {translations.thinkingText || 'Thinking...'}\n </span>\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-shimmer\" />\n <span className=\"DocSearch-AskAi-Thinking-Skeleton DocSearch-AskAi-Thinking-Skeleton--short DocSearch-shimmer\" />\n </div>\n )}\n {displayParts.map((part, idx) => {\n const index = idx;\n\n if (typeof part === 'string') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={loadingStatus === 'streaming'}\n />\n );\n }\n\n if (isAIToolPart(part)) {\n return (\n <ToolCall\n key={index}\n translations={toolCallTranslations}\n part={part}\n tools={tools}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'aggregated-tool-call') {\n return (\n <AggregatedSearchBlock\n key={index}\n queries={part.queries}\n translations={translations}\n onSearchQueryClick={onSearchQueryClick}\n />\n );\n }\n\n if (part.type === 'reasoning' && part.state === 'streaming') {\n return (\n <div\n key={index}\n className=\"DocSearch-AskAiScreen-MessageContent-Reasoning DocSearch-shimmer\"\n >\n <LoadingIcon className=\"DocSearch-AskAiScreen-SmallerLoadingIcon\" />\n <span className=\"DocSearch-shimmer\">Reasoning...</span>\n </div>\n );\n }\n\n if (part.type === 'text') {\n return (\n <MemoizedMarkdown\n key={index}\n content={part.text}\n copyButtonText={translations.copyButtonText || 'Copy'}\n copyButtonCopiedText={\n translations.copyButtonCopiedText || 'Copied!'\n }\n isStreaming={part.state === 'streaming'}\n />\n );\n }\n\n // fallback for unknown part type\n return null;\n })}\n </div>\n\n {wasStopped && (\n <p className=\"DocSearch-AskAiScreen-MessageContent-Stopped\">\n {stoppedStreamingText}\n </p>\n )}\n </div>\n <div className=\"DocSearch-AskAiScreen-Answer-Footer\">\n <SourcesPanel\n links={urlsToDisplay}\n titleText={relatedSourcesText}\n pluralTitleText={relatedSourcesTextPlural}\n />\n <FeedbackActions\n id={messageId}\n showActions={showActions}\n latestAssistantMessageContent={assistantContent || null}\n translations={translations}\n conversations={conversations}\n onFeedback={onFeedback}\n />\n </div>\n\n {promptSuggestions.length > 0 && (\n <ConversationPromptSuggestions\n title={suggestedPromptsTitleText}\n suggestions={promptSuggestions}\n onSelectPromptSuggestion={onSelectPromptSuggestion}\n />\n )}\n </div>\n </div>\n );\n}\n\nexport function AskAiScreen({\n translations = {},\n ...props\n}: AskAiScreenProps): JSX.Element | null {\n const {\n disclaimerText = 'Answers are generated with AI which can make mistakes.',\n threadDepthExceededMessage = 'This conversation is now closed to keep responses accurate.',\n startNewConversationButtonText = 'Start a new conversation',\n } = translations;\n\n const { messages, tools, askAiError, status, memoryEnabled } = props;\n\n // Check if there's a thread depth error\n const hasThreadDepthError = useMemo(() => {\n return status === 'error' && isThreadDepthError(askAiError);\n }, [status, askAiError]);\n\n // Group messages into exchanges (user + assistant pairs)\n const exchanges: Exchange[] = useMemo(() => {\n const grouped: Exchange[] = [];\n for (let i = 0; i < messages.length; i++) {\n if (messages[i].role === 'user') {\n const userMessage = messages[i];\n const assistantMessage =\n messages[i + 1]?.role === 'assistant' ? messages[i + 1] : null;\n grouped.push({ id: userMessage.id, userMessage, assistantMessage });\n if (assistantMessage) {\n i++;\n }\n }\n }\n\n // If there's a thread depth error, remove the last exchange (the one that triggered the error)\n // We only want to show successful exchanges\n if (hasThreadDepthError && grouped.length > 0) {\n // Check if the last exchange has no assistant message (failed to complete)\n const lastExchange = grouped[grouped.length - 1];\n if (!lastExchange.assistantMessage) {\n grouped.pop();\n }\n }\n\n return grouped;\n }, [messages, hasThreadDepthError]);\n\n const handleSearchQueryClick = (query: string): void => {\n props.onAskAiToggle(false);\n props.setQuery(query);\n };\n\n // Only show the thread depth error if we have assistant messages\n const showThreadDepthError =\n hasThreadDepthError && messages.some((m) => m.role === 'assistant');\n\n return (\n <div className=\"DocSearch-AskAiScreen DocSearch-AskAiScreen-Container\">\n {/* Thread Depth Error */}\n {showThreadDepthError && (\n <div className=\"DocSearch-AskAiScreen-MessageContent DocSearch-AskAiScreen-Error DocSearch-AskAiScreen-Error--ThreadDepth\">\n <div className=\"DocSearch-AskAiScreen-Error-Content\">\n <p>\n {threadDepthExceededMessage}{' '}\n <button\n type=\"button\"\n className=\"DocSearch-ThreadDepthError-Link\"\n onClick={props.onNewConversation}\n >\n {startNewConversationButtonText}\n </button>{' '}\n to continue.\n </p>\n </div>\n </div>\n )}\n\n <AskAiScreenDisclaimer disclaimerText={disclaimerText} />\n\n <div className=\"DocSearch-AskAiScreen-Body\">\n <div className=\"DocSearch-AskAiScreen-ExchangesList\">\n {exchanges\n .slice()\n .reverse()\n .map((exchange, index) => (\n <AskAiExchangeCard\n key={exchange.id}\n exchange={exchange}\n askAiError={props.askAiError}\n isLastExchange={index === 0}\n loadingStatus={props.status}\n translations={translations}\n tools={tools}\n conversations={props.conversations}\n memoryEnabled={memoryEnabled}\n onSearchQueryClick={handleSearchQueryClick}\n onFeedback={props.onFeedback}\n onSelectPromptSuggestion={props.onSelectPromptSuggestion}\n />\n ))}\n </div>\n </div>\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../../AskAiScreenState';\nimport { CloseIcon, MessageIcon } from '../../icons';\nimport { Results } from '../../Results';\nimport type { InternalDocSearchHit } from '../../types';\nimport { getCollection } from '../../utils';\n\nexport type RecentConversationsResultsTranslations = Partial<{\n recentConversationsTitle: string;\n removeRecentConversationButtonTitle: string;\n}>;\n\ntype RecentConversationsResultsProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: RecentConversationsResultsTranslations;\n};\n\nexport function RecentConversationsResults({\n translations = {},\n ...props\n}: RecentConversationsResultsProps): JSX.Element | null {\n const {\n recentConversationsTitle = 'Resume AI conversations',\n removeRecentConversationButtonTitle = 'Remove this conversation from history',\n } = translations;\n const recentConversations = getCollection(props.state, 'recentConversations');\n\n if (!recentConversations) {\n return null;\n }\n\n return (\n <Results\n {...props}\n title={recentConversationsTitle}\n collection={recentConversations}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon DocSearch-Hit-icon--start\">\n <MessageIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n className=\"DocSearch-Hit-action-button\"\n title={removeRecentConversationButtonTitle}\n type=\"submit\"\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateProps } from '../AskAiScreenState';\nimport type { InternalDocSearchHit } from '../types';\n\nimport type { RecentConversationsResultsTranslations } from './ui/RecentConversationsResults';\nimport { RecentConversationsResults } from './ui/RecentConversationsResults';\nimport type { StoredSearchesSectionsTranslations } from './ui/StoredSearchesSections';\nimport { StoredSearchesSections } from './ui/StoredSearchesSections';\n\nexport type AskAiStartScreenTranslations =\n RecentConversationsResultsTranslations & StoredSearchesSectionsTranslations;\n\ntype AskAiStartScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n hasCollections: boolean;\n translations?: AskAiStartScreenTranslations;\n};\n\nexport function AskAiStartScreen({\n translations = {},\n ...props\n}: AskAiStartScreenProps): JSX.Element | null {\n return (\n <div className=\"DocSearch-Dropdown-Container\">\n <RecentConversationsResults {...props} translations={translations} />\n <StoredSearchesSections {...props} translations={translations} />\n </div>\n );\n}\n","import type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenStateProps } from './AskAiScreenState';\nimport { CloseIcon, SparklesIcon } from './icons';\nimport { Results } from './Results';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport type { InternalDocSearchHit } from './types';\nimport { getCollection } from './utils';\n\ntype ConversationHistoryScreenProps = Omit<\n AskAiScreenStateProps<InternalDocSearchHit>,\n 'translations'\n> & {\n translations?: ResultsScreenTranslations;\n};\n\nexport function ConversationHistoryScreen({\n onAskAiToggle,\n ...props\n}: ConversationHistoryScreenProps): JSX.Element | null {\n const collection = React.useMemo(\n () => getCollection(props.state, 'recentConversations'),\n [props.state]\n );\n\n React.useEffect(() => {\n if (!collection || collection.items.length === 0) {\n onAskAiToggle(true);\n }\n }, [collection, onAskAiToggle]);\n\n if (!collection) {\n return null;\n }\n\n return (\n <div className=\"DocSearch-Dropdown-Container DocSearch-Conversation-History\">\n <Results\n {...props}\n key={collection.source.sourceId}\n title=\"\"\n translations={props.translations}\n collection={collection}\n renderIcon={() => (\n <div className=\"DocSearch-Hit-icon\">\n <SparklesIcon />\n </div>\n )}\n renderAction={({ item }) => (\n <div className=\"DocSearch-Hit-action\">\n <button\n type=\"button\"\n className=\"DocSearch-Hit-action-button\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n props.conversations.remove(item);\n props.refresh();\n }}\n >\n <CloseIcon />\n </button>\n </div>\n )}\n />\n </div>\n );\n}\n","import React, { type JSX } from 'react';\n\nimport type { SuggestedQuestionHit } from './types';\n\nexport type NewConversationTranslations = Partial<{\n newConversationTitle: string;\n newConversationDescription: string;\n}>;\n\ninterface NewConversationProps {\n suggestedQuestions?: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n translations?: NewConversationTranslations;\n}\n\nexport function NewConversationScreen({\n translations = {},\n suggestedQuestions = [],\n selectSuggestedQuestion,\n}: NewConversationProps): JSX.Element {\n const {\n newConversationTitle = 'How can I help you today?',\n newConversationDescription = 'I search through your documentation to help you find setup guides, feature details and troubleshooting tips, fast.',\n } = translations;\n\n return (\n <div className=\"DocSearch-NewConversationScreen\">\n <h3 className=\"DocSearch-NewConversationScreen-Title\">\n {newConversationTitle}\n </h3>\n <p className=\"DocSearch-NewConversationScreen-Description\">\n {newConversationDescription}\n </p>\n\n <div className=\"DocSearch-NewConversationScreen-SuggestedQuestions\">\n {suggestedQuestions.map((question) => (\n <button\n key={question.objectID}\n type=\"button\"\n className=\"DocSearch-NewConversationScreen-SuggestedQuestion\"\n onClick={() => selectSuggestedQuestion(question)}\n >\n {question.question}\n </button>\n ))}\n </div>\n </div>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n BaseItem,\n} from '@algolia/autocomplete-core';\nimport type { JSX } from 'react';\nimport React from 'react';\n\nimport type { AskAiScreenTranslations } from './AskAiScreen';\nimport { AskAiScreen } from './AskAiScreen';\nimport type { AskAiStartScreenTranslations } from './components/AskAiStartScreen';\nimport { AskAiStartScreen } from './components/AskAiStartScreen';\nimport { ConversationHistoryScreen } from './ConversationHistoryScreen';\nimport type { DocSearchProps } from './DocSearch';\nimport type { ErrorScreenTranslations } from './ErrorScreen';\nimport { ErrorScreen } from './ErrorScreen';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport { NewConversationScreen } from './NewConversationScreen';\nimport type { NoResultsScreenTranslations } from './NoResultsScreen';\nimport { NoResultsScreen } from './NoResultsScreen';\nimport type { ResultsScreenTranslations } from './ResultsScreen';\nimport { ResultsScreen } from './ResultsScreen';\nimport type { StoredSearchPlugin } from './stored-searches';\nimport type {\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiState,\n StoredDocSearchHit,\n SuggestedQuestionHit,\n} from './types';\nimport type { AIMessage, AskAiState, ToolCalls } from './types/AskiAi';\nimport { isQueryEmpty } from './utils';\n\nexport type AskAiScreenStateTranslations = Partial<{\n errorScreen: ErrorScreenTranslations;\n startScreen: AskAiStartScreenTranslations;\n noResultsScreen: NoResultsScreenTranslations;\n resultsScreen: ResultsScreenTranslations;\n askAiScreen: AskAiScreenTranslations;\n newConversation: NewConversationTranslations;\n}>;\n\nexport interface AskAiScreenStateProps<\n TItem extends BaseItem,\n> extends AutocompleteApi<\n TItem,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<TItem>;\n recentSearches: StoredSearchPlugin<StoredDocSearchHit>;\n favoriteSearches: StoredSearchPlugin<StoredDocSearchHit>;\n conversations: StoredSearchPlugin<StoredAskAiState>;\n onItemClick: (\n item: InternalDocSearchHit,\n event: KeyboardEvent | MouseEvent\n ) => void;\n onAskAiToggle: (toggle: boolean) => void;\n isAskAiActive: boolean;\n canHandleAskAi: boolean;\n inputRef: React.MutableRefObject<HTMLInputElement | null>;\n hitComponent: DocSearchProps['hitComponent'];\n indexName: string;\n messages: UseChatHelpers<AIMessage>['messages'];\n tools: ToolCalls;\n status: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n disableUserPersonalization: boolean;\n resultsFooterComponent: DocSearchProps['resultsFooterComponent'];\n translations: AskAiScreenStateTranslations;\n getMissingResultsUrl?: DocSearchProps['getMissingResultsUrl'];\n hasCollections: boolean;\n onFeedback?: OnAskAiFeedback;\n askAiState: AskAiState;\n selectAskAiQuestion: (toggle: boolean, query: string) => void;\n suggestedQuestions: SuggestedQuestionHit[];\n selectSuggestedQuestion: (question: SuggestedQuestionHit) => void;\n onNewConversation: () => void;\n memoryEnabled?: boolean;\n resultBadgeKey?: string;\n}\n\nexport const AskAiScreenState = React.memo(\n ({\n translations = {},\n selectAskAiQuestion,\n ...props\n }: AskAiScreenStateProps<InternalDocSearchHit>): JSX.Element => {\n const handleSelectPromptSuggestion = React.useCallback(\n (prompt: string) => {\n selectAskAiQuestion(true, prompt);\n },\n [selectAskAiQuestion]\n );\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'conversation-history'\n ) {\n return (\n <ConversationHistoryScreen\n selectAskAiQuestion={selectAskAiQuestion}\n {...props}\n />\n );\n }\n\n if (\n props.canHandleAskAi &&\n props.isAskAiActive &&\n props.askAiState === 'new-conversation'\n ) {\n return (\n <NewConversationScreen\n translations={translations?.newConversation}\n selectSuggestedQuestion={props.selectSuggestedQuestion}\n suggestedQuestions={props.suggestedQuestions}\n />\n );\n }\n\n if (props.isAskAiActive && props.canHandleAskAi) {\n return (\n <AskAiScreen\n {...props}\n messages={props.messages}\n tools={props.tools}\n status={props.status}\n askAiError={props.askAiError}\n translations={translations?.askAiScreen}\n memoryEnabled={props.memoryEnabled}\n selectAskAiQuestion={selectAskAiQuestion}\n onSelectPromptSuggestion={handleSelectPromptSuggestion}\n />\n );\n }\n\n if (props.state?.status === 'error') {\n return <ErrorScreen translations={translations?.errorScreen} />;\n }\n\n if (isQueryEmpty(props.state.query)) {\n return (\n <AskAiStartScreen\n {...props}\n hasCollections={props.hasCollections}\n translations={translations?.startScreen}\n selectAskAiQuestion={selectAskAiQuestion}\n />\n );\n }\n\n if (!props.hasCollections && !props.canHandleAskAi) {\n return (\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n );\n }\n\n return (\n <>\n <ResultsScreen {...props} translations={translations?.resultsScreen} />\n {props.canHandleAskAi &&\n !props.hasCollections && (\n // if there's one collection it is the ask ai action, show the no results screen\n <NoResultsScreen\n {...props}\n translations={translations?.noResultsScreen}\n />\n )}\n </>\n );\n },\n function areEqual(prevProps, nextProps) {\n const askAiStateChanged =\n prevProps.isAskAiActive !== nextProps.isAskAiActive ||\n prevProps.askAiState !== nextProps.askAiState ||\n prevProps.canHandleAskAi !== nextProps.canHandleAskAi;\n\n // Something triggered an Ask AI related state change, perform a new render\n if (askAiStateChanged) {\n return false;\n }\n\n const isLoading =\n nextProps.state.status === 'loading' ||\n nextProps.state.status === 'stalled';\n\n const isWaitingForCollections =\n nextProps.state.status === 'idle' &&\n !isQueryEmpty(nextProps.state.query) &&\n prevProps.state.query !== nextProps.state.query &&\n prevProps.state.collections === nextProps.state.collections;\n\n return isLoading || isWaitingForCollections;\n }\n);\n","import React from 'react';\nimport type { JSX } from 'react';\n\ntype ModalHeadingProps = {\n heading: string;\n shimmer?: boolean;\n};\n\nexport function ModalHeading({\n heading,\n shimmer = false,\n}: ModalHeadingProps): JSX.Element {\n return (\n <span\n className={`DocSearch-Modal-heading${shimmer ? ' DocSearch-shimmer' : ''}`}\n >\n {heading}\n </span>\n );\n}\n","import type { UseChatHelpers } from '@ai-sdk/react';\nimport type {\n AutocompleteApi,\n AutocompleteState,\n} from '@algolia/autocomplete-core';\nimport React, { type JSX, type RefObject } from 'react';\n\nimport {\n ConversationHistoryIcon,\n MoreVerticalIcon,\n NewConversationIcon,\n StopIcon,\n BackIcon,\n} from '../icons';\nimport { Menu } from '../Menu';\nimport { ModalHeading } from '../ModalHeading';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, AskAiState } from '../types/AskiAi';\nimport { getCollection, isQueryEmpty } from '../utils';\n\nimport { SearchBoxForm } from './ui/SearchBoxForm';\n\nexport type AskAiSearchBoxTranslations = Partial<{\n clearButtonTitle: string;\n clearButtonAriaLabel: string;\n closeButtonText: string;\n closeButtonAriaLabel: string;\n placeholderText: string;\n placeholderTextAskAi: string;\n placeholderTextAskAiStreaming: string;\n enterKeyHint: string;\n enterKeyHintAskAi: string;\n searchInputLabel: string;\n backToKeywordSearchButtonText: string;\n backToKeywordSearchButtonAriaLabel: string;\n newConversationPlaceholder: string;\n conversationHistoryTitle: string;\n startNewConversationText: string;\n viewConversationHistoryText: string;\n threadDepthErrorPlaceholder: string;\n}>;\n\ninterface AskAiSearchBoxProps extends AutocompleteApi<\n InternalDocSearchHit,\n React.FormEvent,\n React.MouseEvent,\n React.KeyboardEvent\n> {\n state: AutocompleteState<InternalDocSearchHit>;\n autoFocus: boolean;\n inputRef: RefObject<HTMLInputElement | null>;\n onClose: () => void;\n onAskAiToggle: (toggle: boolean) => void;\n onAskAgain: (query: string) => void;\n onStopAskAiStreaming: () => Promise<void>;\n placeholder: string;\n isAskAiActive: boolean;\n askAiStatus: UseChatHelpers<AIMessage>['status'];\n askAiError?: Error;\n isFromSelection: boolean;\n translations?: AskAiSearchBoxTranslations;\n askAiState: AskAiState;\n setAskAiState: (state: AskAiState) => void;\n onNewConversation: () => void;\n onViewConversationHistory: () => void;\n isThreadDepthError?: boolean;\n}\n\nexport function AskAiSearchBox({\n translations = {},\n askAiState,\n onAskAiToggle,\n setAskAiState,\n ...props\n}: AskAiSearchBoxProps): JSX.Element {\n const {\n clearButtonTitle = 'Clear',\n clearButtonAriaLabel = 'Clear the query',\n closeButtonText = 'Close',\n closeButtonAriaLabel = 'Close',\n searchInputLabel = 'Search',\n backToKeywordSearchButtonText = 'Back to keyword search',\n backToKeywordSearchButtonAriaLabel = 'Back to keyword search',\n placeholderTextAskAiStreaming = 'Answering...',\n newConversationPlaceholder = 'Ask a question',\n conversationHistoryTitle = 'My conversation history',\n startNewConversationText = 'Start a new conversation',\n viewConversationHistoryText = 'Conversation history',\n threadDepthErrorPlaceholder = 'Conversation limit reached',\n } = translations;\n\n const hasRecentConversations = React.useMemo(() => {\n const askAiSource = getCollection(props.state, 'recentConversations');\n\n if (!askAiSource) {\n return false;\n }\n\n return askAiSource.items.length > 0;\n }, [props.state]);\n\n const baseInputProps = props.getInputProps({\n inputElement: props.inputRef.current!,\n autoFocus: props.autoFocus,\n });\n const blockedKeys = new Set(['ArrowUp', 'ArrowDown', 'Enter']);\n const origOnKeyDown = baseInputProps.onKeyDown;\n const origOnChange = baseInputProps.onChange;\n const isAskAiStreaming =\n props.askAiStatus === 'streaming' || props.askAiStatus === 'submitted';\n const renderMoreOptions =\n props.isAskAiActive && askAiState !== 'conversation-history';\n\n // Use the thread depth error state passed from parent\n const isThreadDepthError = props.isThreadDepthError || false;\n let searchPlaceholder = props.placeholder;\n\n if (askAiState === 'new-conversation') {\n searchPlaceholder = newConversationPlaceholder;\n }\n\n // Override placeholder when thread depth error occurs (only in Ask AI mode)\n if (isThreadDepthError && props.isAskAiActive) {\n searchPlaceholder = threadDepthErrorPlaceholder;\n }\n\n let heading: string | null = null;\n\n if (isAskAiStreaming) {\n heading = placeholderTextAskAiStreaming;\n }\n\n if (askAiState === 'conversation-history') {\n heading = conversationHistoryTitle;\n }\n\n // when returning to another status than streaming or submitted, we focus on the input\n React.useEffect(() => {\n if (\n props.askAiStatus !== 'streaming' &&\n props.askAiStatus !== 'submitted' &&\n props.inputRef.current\n ) {\n props.inputRef.current.focus();\n }\n }, [props.askAiStatus, props.inputRef]);\n\n /**\n * We need to block the default behavior of the input when Ask AI is active.\n * This is because the input is used to ask another question when the user\n * presses enter.\n *\n * Learn more on default autocomplete behavior:\n * https://github.com/algolia/autocomplete/blob/next/packages/autocomplete-core/src/getDefaultProps.ts.\n */\n const inputProps = {\n enterKeyHint: props.isAskAiActive\n ? ('enter' as const)\n : ('search' as const),\n onKeyDown: (e: React.KeyboardEvent<HTMLInputElement>): void => {\n let askAiHandled = false;\n // block these up, down, enter listeners when Ask AI is active\n if (props.isAskAiActive && blockedKeys.has(e.key)) {\n // enter key asks another question\n if (\n e.key === 'Enter' &&\n !isAskAiStreaming &&\n !isQueryEmpty(props.state.query)\n ) {\n props.onAskAgain(props.state.query);\n }\n\n askAiHandled = true;\n }\n\n if (askAiHandled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n\n origOnKeyDown?.(e);\n },\n onChange: (e: React.ChangeEvent<HTMLInputElement>): void => {\n if (props.isAskAiActive) {\n props.setQuery(e.currentTarget.value);\n // block search when Ask AI is active\n // we don't want to trigger the search when the user types\n // we already know they are asking a question\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n origOnChange?.(e);\n },\n disabled: isAskAiStreaming || (isThreadDepthError && props.isAskAiActive),\n };\n\n const handleAskAiBackClick = React.useCallback((): void => {\n // If there's a thread depth error, start a new conversation instead of exiting\n if (isThreadDepthError) {\n props.onNewConversation();\n return;\n }\n\n if (askAiState === 'conversation-history') {\n onAskAiToggle(true);\n setAskAiState('initial');\n return;\n }\n\n onAskAiToggle(false);\n }, [askAiState, isThreadDepthError, onAskAiToggle, setAskAiState, props]);\n\n const leadingElement = props.isAskAiActive ? (\n <button\n type=\"button\"\n tabIndex={0}\n className=\"DocSearch-Action DocSearch-AskAi-Return\"\n title={backToKeywordSearchButtonText}\n aria-label={backToKeywordSearchButtonAriaLabel}\n onClick={handleAskAiBackClick}\n >\n <BackIcon />\n </button>\n ) : undefined;\n const inputOverlay = heading ? (\n <ModalHeading heading={heading} shimmer={isAskAiStreaming} />\n ) : null;\n const actionsBeforeClose = (\n <>\n {!props.isAskAiActive && (\n <>\n <button\n className=\"DocSearch-Clear\"\n type=\"reset\"\n aria-label={clearButtonAriaLabel}\n hidden={!props.state.query}\n tabIndex={props.state.query ? 0 : -1}\n aria-hidden={!props.state.query ? 'true' : 'false'}\n >\n {clearButtonTitle}\n </button>\n\n {props.state.query && <div className=\"DocSearch-Divider\" />}\n </>\n )}\n\n {isAskAiStreaming && (\n <>\n <button\n type=\"button\"\n className=\"DocSearch-Action DocSearch-StopStreaming\"\n onClick={props.onStopAskAiStreaming}\n >\n <StopIcon />\n </button>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n\n {renderMoreOptions && (\n <>\n <Menu>\n <Menu.Trigger className=\"DocSearch-Action\">\n <MoreVerticalIcon />\n </Menu.Trigger>\n <Menu.Content>\n <Menu.Item onClick={props.onNewConversation}>\n <NewConversationIcon />\n {startNewConversationText}\n </Menu.Item>\n {hasRecentConversations && (\n <Menu.Item onClick={props.onViewConversationHistory}>\n <ConversationHistoryIcon />\n {viewConversationHistoryText}\n </Menu.Item>\n )}\n </Menu.Content>\n </Menu>\n\n <div className=\"DocSearch-Divider\" />\n </>\n )}\n </>\n );\n\n return (\n <SearchBoxForm\n {...props}\n placeholder={searchPlaceholder}\n clearButtonTitle={clearButtonTitle}\n clearButtonAriaLabel={clearButtonAriaLabel}\n closeButtonText={closeButtonText}\n closeButtonAriaLabel={closeButtonAriaLabel}\n searchInputLabel={searchInputLabel}\n leadingElement={leadingElement}\n inputOverlay={inputOverlay}\n hideInput={Boolean(heading)}\n actionsBeforeClose={actionsBeforeClose}\n inputProps={inputProps}\n />\n );\n}\n","import type { AutocompleteSource } from '@algolia/autocomplete-core';\nimport type { SearchResponse } from 'algoliasearch/lite';\n\nimport type { DocSearchTransformClient } from '../DocSearch';\nimport type { PromptSuggestions } from '../DocSearchAI';\nimport type { InternalDocSearchHit } from '../types';\nimport type { AIMessage, PromptSuggestion } from '../types/AskiAi';\n\nimport { SOURCE_IDS } from './collections';\n\nconst MAX_RECENT_CONVERSATIONS_DISPLAYED = 3;\n\nconst EMPTY_RESULT_CONTENT = {\n value: '',\n matchLevel: 'none',\n matchedWords: [],\n} satisfies InternalDocSearchHit['_highlightResult']['content'];\nconst EMPTY_HIERARCHY_HIGHLIGHT_RESULT = {\n lvl0: EMPTY_RESULT_CONTENT,\n lvl1: EMPTY_RESULT_CONTENT,\n lvl2: EMPTY_RESULT_CONTENT,\n lvl3: EMPTY_RESULT_CONTENT,\n lvl4: EMPTY_RESULT_CONTENT,\n lvl5: EMPTY_RESULT_CONTENT,\n lvl6: EMPTY_RESULT_CONTENT,\n} satisfies InternalDocSearchHit['_highlightResult']['hierarchy'];\nconst EMPTY_HIGHLIGHT_RESULT: InternalDocSearchHit['_highlightResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\nconst EMPTY_SNIPPET_RESULT: InternalDocSearchHit['_snippetResult'] = {\n content: EMPTY_RESULT_CONTENT,\n hierarchy: EMPTY_HIERARCHY_HIGHLIGHT_RESULT,\n hierarchy_camel: [],\n};\n\nexport function buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n}: {\n conversations: { getAll: () => unknown[] };\n disableUserPersonalization: boolean;\n setMessages: (messages: AIMessage[]) => void;\n onAskAiToggle: (toggle: boolean) => void;\n}): Array<\n AutocompleteSource<InternalDocSearchHit & { messages?: AIMessage[] }>\n> {\n return [\n {\n sourceId: SOURCE_IDS.recentConversations,\n getItems(): InternalDocSearchHit[] {\n if (disableUserPersonalization) {\n return [];\n }\n return (\n conversations.getAll() as unknown as InternalDocSearchHit[]\n ).slice(0, MAX_RECENT_CONVERSATIONS_DISPLAYED);\n },\n onSelect({ item }): void {\n if (item.messages) {\n setMessages(item.messages);\n onAskAiToggle(true);\n }\n },\n },\n ];\n}\n\nfunction createAskAiHit({\n query,\n objectID,\n lvl0,\n}: {\n query: string;\n objectID: string;\n lvl0: string;\n}): InternalDocSearchHit {\n return {\n type: 'askAI',\n query,\n url_without_anchor: '',\n objectID,\n content: null,\n url: '',\n anchor: null,\n hierarchy: {\n lvl0,\n lvl1: query,\n lvl2: null,\n lvl3: null,\n lvl4: null,\n lvl5: null,\n lvl6: null,\n },\n _highlightResult: EMPTY_HIGHLIGHT_RESULT,\n _snippetResult: EMPTY_SNIPPET_RESULT,\n __docsearch_parent: null,\n };\n}\n\nasync function getPromptSuggestions({\n query,\n indexName,\n searchClient,\n hitsPerPage = 3,\n}: {\n query: string;\n indexName: string;\n searchClient: DocSearchTransformClient;\n hitsPerPage?: number;\n}): Promise<InternalDocSearchHit[]> {\n try {\n const { results } = await searchClient.search<PromptSuggestion>({\n requests: [\n {\n query,\n indexName,\n hitsPerPage,\n attributesToRetrieve: ['prompt'],\n },\n ],\n });\n\n const res = results[0] as SearchResponse<PromptSuggestion>;\n\n return res.hits.map((hit) =>\n createAskAiHit({\n query: hit.prompt,\n objectID: hit.objectID,\n lvl0: 'Prompt Suggestions',\n })\n );\n // NOTE: Not checking the exception here and just returning empty array since this isn't the hot path\n } catch {\n return [];\n }\n}\n\nexport async function buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions,\n searchClient,\n}: {\n query: string;\n handleSelectAskAiQuestion: (toggle: boolean, query: string) => void;\n promptSuggestionsOptions?: PromptSuggestions;\n searchClient: DocSearchTransformClient;\n}): Promise<Array<AutocompleteSource<InternalDocSearchHit>>> {\n const promptSuggestions = promptSuggestionsOptions\n ? await getPromptSuggestions({\n query,\n indexName: promptSuggestionsOptions.indexName,\n hitsPerPage: promptSuggestionsOptions.hitsPerPage,\n searchClient,\n })\n : [];\n\n return [\n {\n sourceId: SOURCE_IDS.askAI,\n getItems(): InternalDocSearchHit[] {\n return [\n createAskAiHit({ query, objectID: 'ask-ai-button', lvl0: 'Ask AI' }),\n ...promptSuggestions,\n ];\n },\n onSelect({ item }): void {\n if (item.type === 'askAI' && item.query) {\n handleSelectAskAiQuestion(true, item.query);\n }\n },\n },\n ];\n}\n","import { createAutocomplete } from '@algolia/autocomplete-core';\nimport type { InitialAskAiMessage, OnAskAiToggle } from '@docsearch/core';\nimport type { ChatRequestOptions } from 'ai';\nimport React, { type JSX } from 'react';\n\nimport type { AskAiScreenStateTranslations } from './AskAiScreenState';\nimport { AskAiScreenState } from './AskAiScreenState';\nimport type { AskAiSearchBoxTranslations } from './components/AskAiSearchBox';\nimport { AskAiSearchBox } from './components/AskAiSearchBox';\nimport type { FacetBarTranslations } from './components/FacetBar';\nimport { FacetBar } from './components/FacetBar';\nimport { ModalShell } from './components/ui/ModalShell';\nimport type { DocSearchAIProps } from './DocSearchAI';\nimport type { FooterTranslations } from './Footer';\nimport { Footer } from './Footer';\nimport { Hit } from './Hit';\nimport { useDocSearchFacets } from './hooks/useDocSearchFacets';\nimport { useSendItemClickEvent } from './hooks/useDocSearchInsights';\nimport { useInitialModalQuery } from './hooks/useInitialModalQuery';\nimport { useModalEnvironment } from './hooks/useModalEnvironment';\nimport { useModalRefs } from './hooks/useModalRefs';\nimport { useRefreshOnInitialQuery } from './hooks/useRefreshOnInitialQuery';\nimport { useSaveRecentSearch } from './hooks/useSaveRecentSearch';\nimport { useStoredDocSearches } from './hooks/useStoredDocSearches';\nimport type { NewConversationTranslations } from './NewConversationScreen';\nimport type {\n DocSearchState,\n InternalDocSearchHit,\n OnAskAiFeedback,\n StoredAskAiMessage,\n StoredAskAiState,\n SuggestedQuestionHit,\n} from './types';\nimport { type AskAiState } from './types/AskiAi';\nimport { useAskAi } from './useAskAi';\nimport { useSearchClient } from './useSearchClient';\nimport { useSuggestedQuestions } from './useSuggestedQuestions';\nimport {\n identity,\n isModifierEvent,\n isQueryEmpty,\n noop,\n scrollTo as scrollToUtils,\n SOURCE_IDS,\n} from './utils';\nimport {\n buildDummyAskAiHit,\n isThreadDepthError,\n EMPTY_TOOLS,\n} from './utils/ai';\nimport {\n buildAskAiActionSources,\n buildRecentConversationSources,\n} from './utils/createAskAiSources';\nimport {\n buildNoQuerySources,\n buildQuerySources,\n type BuildQuerySourcesState,\n} from './utils/createDocSearchSources';\nimport { normalizeDocSearchIndexes } from './utils/normalizeDocSearchIndexes';\n\nexport type DocSearchAskAiModalTranslations = AskAiScreenStateTranslations &\n Partial<{\n searchBox: AskAiSearchBoxTranslations;\n newConversation: NewConversationTranslations;\n footer: FooterTranslations;\n facets: FacetBarTranslations;\n }>;\n\nexport type DocSearchAskAiModalProps = DocSearchAIProps & {\n initialScrollY: number;\n onAskAiToggle: OnAskAiToggle;\n onClose?: () => void;\n isAskAiActive?: boolean;\n translations?: DocSearchAskAiModalTranslations;\n isHybridModeSupported?: boolean;\n};\n\nexport function DocSearchAskAiModal({\n appId,\n apiKey,\n askAi,\n maxResultsPerGroup,\n theme,\n onClose = noop,\n transformItems = identity,\n hitComponent = Hit,\n resultsFooterComponent = (): JSX.Element | null => null,\n navigator,\n initialScrollY = 0,\n transformSearchClient = identity,\n disableUserPersonalization = false,\n initialQuery: initialQueryFromProp = '',\n translations = {},\n getMissingResultsUrl,\n insights = false,\n onAskAiToggle,\n interceptAskAiEvent,\n isAskAiActive = false,\n recentSearchesLimit = 7,\n recentSearchesWithFavoritesLimit = 4,\n indices,\n facets,\n isHybridModeSupported = false,\n footerAction,\n ...props\n}: DocSearchAskAiModalProps): JSX.Element {\n const {\n footer: footerTranslations,\n searchBox: searchBoxTranslations,\n facets: facetBarTranslations,\n ...screenStateTranslations\n } = translations;\n const [state, setState] = React.useState<\n DocSearchState<InternalDocSearchHit>\n >({\n query: '',\n collections: [],\n completion: null,\n context: {},\n isOpen: false,\n activeItemId: null,\n status: 'idle',\n });\n\n // check if the instance is configured to handle ask ai\n const canHandleAskAi = Boolean(askAi);\n\n let placeholder =\n translations?.searchBox?.placeholderText ||\n props.placeholder ||\n 'Search docs';\n\n if (canHandleAskAi) {\n placeholder =\n translations?.searchBox?.placeholderText ||\n 'Search docs or ask AI a question';\n }\n\n if (isAskAiActive) {\n placeholder =\n translations?.searchBox?.placeholderTextAskAi ||\n 'Ask another question...';\n }\n\n const { containerRef, modalRef, formElementRef, dropdownRef, inputRef } =\n useModalRefs();\n const { initialQuery, initialQueryFromSelection } =\n useInitialModalQuery(initialQueryFromProp);\n\n const searchClient = useSearchClient(appId, apiKey, transformSearchClient);\n\n const askAiConfig = typeof askAi === 'object' ? askAi : null;\n const askAiConfigurationId = askAiConfig\n ? askAiConfig.agentId\n : (askAi as string);\n const askAiSearchParameters = askAiConfig?.searchParameters;\n const [askAiState, setAskAiState] = React.useState<AskAiState>('initial');\n const suggestedQuestions = useSuggestedQuestions({\n agentId: askAiConfigurationId,\n searchClient,\n suggestedQuestionsEnabled: askAiConfig?.suggestedQuestions,\n });\n const memoryEnabled = askAiConfig?.memory?.enabled ?? false;\n const tools = askAiConfig?.tools ?? EMPTY_TOOLS;\n\n const indexes = React.useMemo(\n () =>\n normalizeDocSearchIndexes({\n indices,\n }),\n [indices]\n );\n const defaultIndexName = indexes[0].name;\n\n const autocompleteRef =\n React.useRef<\n ReturnType<\n typeof createAutocomplete<\n InternalDocSearchHit,\n React.FormEvent<HTMLFormElement>,\n React.MouseEvent,\n React.KeyboardEvent\n >\n >\n >(undefined);\n\n const {\n visibleFacets,\n facetSelections,\n facetSelectionsRef,\n handleFacetSelectionChange,\n clearFacetSelections,\n } = useDocSearchFacets({\n facets,\n indexes,\n searchClient,\n onSelectionsChange: () => autocompleteRef.current?.refresh(),\n });\n\n const { favoriteSearches, recentSearches } = useStoredDocSearches({\n defaultIndexName,\n recentSearchesLimit,\n recentSearchesWithFavoritesLimit,\n });\n\n const [stoppedStream, setStoppedStream] = React.useState(false);\n\n const {\n chatId,\n messages,\n status,\n setMessages,\n sendMessage,\n stopAskAiStreaming,\n askAiError,\n sendFeedback,\n conversations,\n startNewConversation,\n restoreConversation,\n } = useAskAi({\n agentId: askAiConfigurationId,\n apiKey: askAiConfig?.apiKey || apiKey,\n appId: askAiConfig?.appId || appId,\n searchParameters: askAiSearchParameters,\n tools,\n memory: askAiConfig?.memory,\n indices: askAiConfig?.indices,\n });\n\n const prevStatus = React.useRef(status);\n React.useEffect(() => {\n if (disableUserPersonalization) {\n return;\n }\n // if we just transitioned from \"streaming\" → \"ready\", persist\n if (prevStatus.current === 'streaming' && status === 'ready') {\n // if we stopped the stream, store it on the most recent message\n if (stoppedStream && messages.at(-1)) {\n messages.at(-1)!.metadata = {\n stopped: true,\n };\n }\n\n for (const part of messages[0].parts) {\n if (part.type === 'text') {\n conversations.add(buildDummyAskAiHit(part.text, messages, chatId));\n }\n }\n }\n prevStatus.current = status;\n }, [\n status,\n messages,\n conversations,\n disableUserPersonalization,\n stoppedStream,\n chatId,\n ]);\n\n // Check if there's a thread depth error (AI-217)\n const hasThreadDepthError = React.useMemo(() => {\n return (\n status === 'error' && isThreadDepthError(askAiError as Error | undefined)\n );\n }, [status, askAiError]);\n\n const saveRecentSearch = useSaveRecentSearch({\n favoriteSearches,\n recentSearches,\n disableUserPersonalization,\n });\n const sendItemClickEvent = useSendItemClickEvent(state);\n\n const handleSelectAskAiQuestion = React.useCallback(\n (\n toggle: boolean,\n query: string,\n suggestedQuestion: SuggestedQuestionHit | undefined = undefined\n ) => {\n if (toggle) {\n const initialMessage: InitialAskAiMessage = {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n // Consumer handled it. Avoid *all* default Ask AI behavior.\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n return;\n }\n }\n\n if (toggle && askAiState === 'new-conversation') {\n setAskAiState('initial');\n }\n\n onAskAiToggle(toggle, {\n query,\n suggestedQuestionId: suggestedQuestion?.objectID,\n });\n\n // If we're in hybrid mode, we don't need to send the message,\n // it will be handled by the Sidepanel.\n if (isHybridModeSupported) return;\n\n setStoppedStream(false);\n\n const messageOptions: ChatRequestOptions = {};\n\n if (suggestedQuestion) {\n messageOptions.body = {\n suggestedQuestionId: suggestedQuestion.objectID,\n };\n }\n\n sendMessage(\n {\n role: 'user',\n parts: [\n {\n type: 'text',\n text: query,\n },\n ],\n },\n messageOptions\n );\n\n if (dropdownRef.current) {\n // some test environments (like jsdom) don't implement element.scrollTo\n const el = dropdownRef.current;\n if (typeof (el as any).scrollTo === 'function') {\n el.scrollTo({ top: 0, behavior: 'smooth' });\n } else {\n // fallback for environments without scrollTo support\n el.scrollTop = 0;\n }\n }\n\n // clear the query\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n },\n [\n askAiState,\n onAskAiToggle,\n isHybridModeSupported,\n sendMessage,\n dropdownRef,\n interceptAskAiEvent,\n ]\n );\n\n // feedback handler\n const handleFeedbackSubmit = React.useCallback<OnAskAiFeedback>(\n async (messageId, feedback): Promise<void> => {\n if (!askAiConfigurationId || !appId) return;\n await sendFeedback(messageId, feedback);\n },\n [askAiConfigurationId, appId, sendFeedback]\n );\n\n if (!autocompleteRef.current) {\n autocompleteRef.current = createAutocomplete({\n id: 'docsearch',\n defaultActiveItemId: 0,\n openOnFocus: true,\n initialState: {\n query: initialQuery,\n context: {\n searchSuggestions: [],\n },\n },\n insights: Boolean(insights),\n navigator,\n onStateChange(changes) {\n setState(changes.state);\n },\n async getSources({ query, state: sourcesState, setContext, setStatus }) {\n if (isQueryEmpty(query)) {\n const noQuerySources = buildNoQuerySources({\n recentSearches,\n favoriteSearches,\n saveRecentSearch,\n onClose,\n disableUserPersonalization,\n });\n\n const recentConversationSource = canHandleAskAi\n ? buildRecentConversationSources({\n conversations,\n disableUserPersonalization,\n setMessages,\n onAskAiToggle,\n })\n : [];\n return [...recentConversationSource, ...noQuerySources];\n }\n\n const querySourcesState: BuildQuerySourcesState = {\n context: sourcesState.context,\n };\n\n const algoliaSourcesPromise = buildQuerySources({\n query,\n state: querySourcesState,\n setContext,\n setStatus,\n searchClient,\n indexes,\n insights: Boolean(insights),\n appId,\n apiKey,\n maxResultsPerGroup,\n transformItems,\n saveRecentSearch,\n onClose,\n facetSelections: facetSelectionsRef,\n });\n\n const askAiSourcesPromise = canHandleAskAi\n ? buildAskAiActionSources({\n query,\n handleSelectAskAiQuestion,\n promptSuggestionsOptions: askAiConfig?.promptSuggestions,\n searchClient,\n })\n : Promise.resolve([]);\n\n const [askAiSources, algoliaSources] = await Promise.all([\n askAiSourcesPromise,\n algoliaSourcesPromise,\n ]);\n\n // Combine Algolia results (once resolved) with the Ask AI source\n return [...askAiSources, ...algoliaSources];\n },\n });\n }\n\n const autocomplete = autocompleteRef.current;\n\n const { getEnvironmentProps, getRootProps, refresh } = autocomplete;\n\n useModalEnvironment({\n getEnvironmentProps,\n containerRef,\n dropdownRef,\n formElementRef,\n inputRef,\n initialScrollY,\n modalRef,\n theme,\n });\n\n React.useEffect(() => {\n if (dropdownRef.current && !isAskAiActive) {\n scrollToUtils(dropdownRef.current);\n }\n }, [state.query, isAskAiActive, dropdownRef]);\n\n useRefreshOnInitialQuery({ initialQuery, inputRef, refresh });\n\n const hasCurrentMessages = messages.length > 0;\n\n // Refresh the autocomplete results when ask ai is toggled off\n // helps return to the previous ac state and start screen\n React.useEffect(() => {\n if (!isAskAiActive) {\n autocomplete.refresh();\n\n if (hasCurrentMessages) {\n startNewConversation();\n }\n }\n }, [isAskAiActive, autocomplete, startNewConversation, hasCurrentMessages]);\n\n // Track external state in order to manage internal askAiState\n React.useEffect(() => {\n setAskAiState('initial');\n }, [isAskAiActive, setAskAiState]);\n\n const onStopAskAiStreaming = async (): Promise<void> => {\n setStoppedStream(true);\n\n await stopAskAiStreaming();\n };\n\n const handleNewConversation = (): void => {\n startNewConversation();\n setAskAiState('new-conversation');\n };\n\n const handleViewConversationHistory = (): void => {\n setAskAiState('conversation-history');\n };\n\n const selectSuggestedQuestion = (\n suggestedQuestion: SuggestedQuestionHit\n ): void => {\n handleSelectAskAiQuestion(\n true,\n suggestedQuestion.question,\n suggestedQuestion\n );\n };\n\n // hide the dropdown on idle and no collections\n let showDocsearchDropdown = true;\n const hasCollections = state.collections.some(\n (collection) =>\n collection.source.sourceId !== SOURCE_IDS.askAI &&\n collection.items.length > 0\n );\n if (\n state.status === 'idle' &&\n hasCollections === false &&\n isQueryEmpty(state.query) &&\n !isAskAiActive\n ) {\n showDocsearchDropdown = false;\n }\n\n return (\n <ModalShell\n state={state}\n containerRef={containerRef}\n modalRef={modalRef}\n formElementRef={formElementRef}\n dropdownRef={dropdownRef}\n getRootProps={getRootProps}\n showDropdown={showDocsearchDropdown}\n searchBox={\n <AskAiSearchBox\n {...autocomplete}\n state={state}\n placeholder={placeholder || 'Search docs'}\n autoFocus={isQueryEmpty(initialQuery)}\n inputRef={inputRef}\n isFromSelection={\n Boolean(initialQuery) && initialQuery === initialQueryFromSelection\n }\n translations={searchBoxTranslations}\n isAskAiActive={isAskAiActive}\n askAiStatus={status}\n askAiError={askAiError}\n askAiState={askAiState}\n setAskAiState={setAskAiState}\n isThreadDepthError={\n hasThreadDepthError && askAiState !== 'new-conversation'\n }\n onClose={onClose}\n onAskAiToggle={onAskAiToggle}\n onAskAgain={(query) => {\n handleSelectAskAiQuestion(true, query);\n }}\n onStopAskAiStreaming={onStopAskAiStreaming}\n onNewConversation={handleNewConversation}\n onViewConversationHistory={handleViewConversationHistory}\n />\n }\n filterBar={\n !isAskAiActive && !isQueryEmpty(state.query) ? (\n <FacetBar\n facets={visibleFacets}\n selections={facetSelections}\n translations={facetBarTranslations}\n clearSelections={clearFacetSelections}\n onSelectionChange={handleFacetSelectionChange}\n />\n ) : null\n }\n screenState={\n <AskAiScreenState\n {...autocomplete}\n indexName={defaultIndexName}\n state={state}\n hitComponent={hitComponent}\n resultsFooterComponent={resultsFooterComponent}\n disableUserPersonalization={disableUserPersonalization}\n recentSearches={recentSearches}\n favoriteSearches={favoriteSearches}\n conversations={conversations}\n inputRef={inputRef}\n translations={screenStateTranslations}\n getMissingResultsUrl={getMissingResultsUrl}\n isAskAiActive={isAskAiActive}\n canHandleAskAi={canHandleAskAi}\n messages={messages}\n tools={tools}\n askAiError={askAiError}\n status={status}\n hasCollections={hasCollections}\n askAiState={askAiState}\n selectAskAiQuestion={handleSelectAskAiQuestion}\n suggestedQuestions={suggestedQuestions}\n selectSuggestedQuestion={selectSuggestedQuestion}\n memoryEnabled={memoryEnabled}\n resultBadgeKey={props.resultBadgeKey}\n onAskAiToggle={onAskAiToggle}\n onNewConversation={handleNewConversation}\n onItemClick={(item, event) => {\n if (item.type === 'askAI' && item.query) {\n if (item.anchor === 'stored' && 'messages' in item) {\n const hitMessages = item.messages as StoredAskAiMessage[];\n restoreConversation(\n hitMessages,\n (item as StoredAskAiState).chatId\n );\n const initialMessage: InitialAskAiMessage = {\n query: item.query,\n messageId: hitMessages[0].id,\n };\n\n if (interceptAskAiEvent?.(initialMessage)) {\n if (autocompleteRef.current) {\n autocompleteRef.current.setQuery('');\n }\n event.preventDefault();\n return;\n }\n\n onAskAiToggle(true, initialMessage);\n } else {\n handleSelectAskAiQuestion(true, item.query);\n }\n setAskAiState('initial');\n event.preventDefault();\n return;\n }\n\n sendItemClickEvent(item);\n saveRecentSearch(item);\n if (!isModifierEvent(event)) {\n onClose();\n }\n }}\n onFeedback={handleFeedbackSubmit}\n />\n }\n footer={\n <Footer\n translations={footerTranslations}\n isAskAiActive={isAskAiActive}\n footerAction={footerAction}\n />\n }\n onClose={onClose}\n />\n );\n}\n"],"mappings":"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"}