fix: update related sources
This commit is contained in:
parent
68b66aff77
commit
a2146c5910
5 changed files with 182 additions and 35 deletions
|
|
@ -12,8 +12,8 @@ function App(): JSX.Element {
|
|||
indexName="beta-react"
|
||||
appId="betaHAXPMHIMMC"
|
||||
apiKey="8b00405cba281a7d800ccec393e9af24"
|
||||
dataSourceId="crawler_rag_beta-react-rag"
|
||||
promptId="crawler_rag_beta-react-rag"
|
||||
dataSourceId="crawler-beta-react-rag"
|
||||
promptId="crawler-betaHAXPMHIMMC-TDE"
|
||||
insights={true}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -787,15 +787,14 @@ assistive tech users */
|
|||
|
||||
.DocSearch-AskAiScreen-Response-Container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
flex-direction: column;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.DocSearch-AskAiScreen-Response {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 70%;
|
||||
width: 100%;
|
||||
gap: 16px;
|
||||
font-size: 0.8em;
|
||||
margin-bottom: 8px;
|
||||
|
|
@ -884,7 +883,15 @@ assistive tech users */
|
|||
.DocSearch-AskAiScreen-RelatedSources {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 30%;
|
||||
width: 100%;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.DocSearch-AskAiScreen-RelatedSources-List {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
|
|
@ -938,6 +945,12 @@ assistive tech users */
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.DocSearch-AskAiScreen-ExchangesList {
|
||||
gap: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.DocSearch-AskAiScreen-RelatedSources-Item-Link:hover {
|
||||
background: var(--docsearch-hit-highlight-color);
|
||||
}
|
||||
|
|
@ -1117,7 +1130,6 @@ assistive tech users */
|
|||
|
||||
.DocSearch-AskAiScreen-Response-Container {
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.DocSearch-AskAiScreen-Response {
|
||||
|
|
|
|||
81
packages/docsearch-react/rollup.config-1747292357362.cjs
Normal file
81
packages/docsearch-react/rollup.config-1747292357362.cjs
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
var replace = require('@rollup/plugin-replace');
|
||||
var pluginBabel = require('@rollup/plugin-babel');
|
||||
var json = require('@rollup/plugin-json');
|
||||
var resolve = require('@rollup/plugin-node-resolve');
|
||||
var terser = require('@rollup/plugin-terser');
|
||||
var rollupPluginDts = require('rollup-plugin-dts');
|
||||
var filesize = require('rollup-plugin-filesize');
|
||||
var child_process = require('child_process');
|
||||
var pkg = require('./package.json');
|
||||
|
||||
const plugins = [
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
__DEV__: JSON.stringify(process.env.NODE_ENV === 'development'),
|
||||
}),
|
||||
json(),
|
||||
resolve({
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
|
||||
browser: true,
|
||||
}),
|
||||
pluginBabel.babel({
|
||||
babelHelpers: 'bundled',
|
||||
exclude: 'node_modules/**',
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json'],
|
||||
rootMode: 'upward',
|
||||
}),
|
||||
terser(),
|
||||
filesize({
|
||||
showMinifiedSize: false,
|
||||
showGzippedSize: true,
|
||||
}),
|
||||
];
|
||||
|
||||
const typesConfig = {
|
||||
input: 'dist/esm/types/index.d.ts',
|
||||
output: [{ file: 'dist/esm/index.d.ts', format: 'es' }],
|
||||
plugins: [rollupPluginDts.dts()],
|
||||
};
|
||||
|
||||
function getBundleBanner(pkg) {
|
||||
const lastCommitHash = child_process.execSync('git rev-parse --short HEAD').toString().trim();
|
||||
const version = process.env.SHIPJS ? pkg.version : `${pkg.version} (UNRELEASED ${lastCommitHash})`;
|
||||
const authors = '© Algolia, Inc. and contributors';
|
||||
|
||||
return `/*! ${pkg.name} ${version} | MIT License | ${authors} | ${pkg.homepage} */`;
|
||||
}
|
||||
|
||||
var rollup_config = [
|
||||
{
|
||||
input: 'src/index.ts',
|
||||
external: ['react', 'react-dom'],
|
||||
output: [
|
||||
{
|
||||
globals: {
|
||||
react: 'React',
|
||||
'react-dom': 'ReactDOM',
|
||||
},
|
||||
file: 'dist/umd/index.js',
|
||||
format: 'umd',
|
||||
sourcemap: true,
|
||||
name: pkg.name,
|
||||
banner: getBundleBanner(pkg),
|
||||
},
|
||||
{ dir: 'dist/esm', format: 'es' },
|
||||
],
|
||||
plugins: [
|
||||
...plugins,
|
||||
replace({
|
||||
preventAssignment: true,
|
||||
'process.env.NODE_ENV': JSON.stringify('production'),
|
||||
}),
|
||||
],
|
||||
},
|
||||
typesConfig,
|
||||
];
|
||||
|
||||
exports.default = rollup_config;
|
||||
|
|
@ -10,6 +10,7 @@ interface Message {
|
|||
id: string;
|
||||
role: 'assistant' | 'user';
|
||||
content: string;
|
||||
urls?: Array<{ url: string; title?: string }>;
|
||||
context?: AskAiResponse['context'];
|
||||
}
|
||||
|
||||
|
|
@ -77,7 +78,7 @@ function AskAiExchangeCard({
|
|||
const isStreaming = isLastExchange && loadingStatus === 'streaming';
|
||||
const showError = isLastExchange && loadingStatus === 'error' && error;
|
||||
const showActions = !isLastExchange || (isLastExchange && loadingStatus === 'idle' && Boolean(assistantMessage));
|
||||
const contextToDisplay = assistantMessage?.context || [];
|
||||
const urlsToDisplay = assistantMessage?.urls || [];
|
||||
|
||||
return (
|
||||
<div className="DocSearch-AskAiScreen-Response-Container">
|
||||
|
|
@ -110,13 +111,20 @@ function AskAiExchangeCard({
|
|||
</div>
|
||||
|
||||
{/* Sources for this exchange */}
|
||||
<AskAiSourcesPanel
|
||||
contextToDisplay={contextToDisplay}
|
||||
loadingStatus={loadingStatus}
|
||||
relatedSourcesText={translations.relatedSourcesText}
|
||||
hasHadAssistantResponse={globalHasHadAssistantResponse}
|
||||
isExchangeLoading={isLastExchange && (loadingStatus === 'loading' || loadingStatus === 'streaming')}
|
||||
/>
|
||||
{urlsToDisplay.length > 0 ||
|
||||
(urlsToDisplay.length === 0 &&
|
||||
loadingStatus === 'loading' &&
|
||||
!globalHasHadAssistantResponse &&
|
||||
isLastExchange &&
|
||||
(loadingStatus === 'loading' || loadingStatus === 'streaming')) ? (
|
||||
<AskAiSourcesPanel
|
||||
urlsToDisplay={urlsToDisplay}
|
||||
loadingStatus={loadingStatus}
|
||||
relatedSourcesText={translations.relatedSourcesText}
|
||||
hasHadAssistantResponse={globalHasHadAssistantResponse}
|
||||
isExchangeLoading={isLastExchange && (loadingStatus === 'loading' || loadingStatus === 'streaming')}
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -143,7 +151,7 @@ function AskAiScreenFooterActions({
|
|||
}
|
||||
|
||||
interface AskAiSourcesPanelProps {
|
||||
contextToDisplay: AskAiResponse['context'];
|
||||
urlsToDisplay: Array<{ url: string; title?: string }>;
|
||||
loadingStatus: LoadingStatus;
|
||||
relatedSourcesText: string;
|
||||
hasHadAssistantResponse: boolean;
|
||||
|
|
@ -151,7 +159,7 @@ interface AskAiSourcesPanelProps {
|
|||
}
|
||||
|
||||
function AskAiSourcesPanel({
|
||||
contextToDisplay,
|
||||
urlsToDisplay,
|
||||
loadingStatus,
|
||||
relatedSourcesText,
|
||||
hasHadAssistantResponse,
|
||||
|
|
@ -160,32 +168,36 @@ function AskAiSourcesPanel({
|
|||
return (
|
||||
<div className="DocSearch-AskAiScreen-RelatedSources">
|
||||
<p className="DocSearch-AskAiScreen-RelatedSources-Title">{relatedSourcesText}</p>
|
||||
{contextToDisplay.length > 0 &&
|
||||
contextToDisplay.map((source) => (
|
||||
<a
|
||||
key={source.objectID}
|
||||
href={source.url || source.objectID || '#'}
|
||||
className="DocSearch-AskAiScreen-RelatedSources-Item-Link"
|
||||
>
|
||||
<RelatedSourceIcon />
|
||||
<span>{source.title || source.url || source.objectID}</span>
|
||||
</a>
|
||||
))}
|
||||
{contextToDisplay.length === 0 &&
|
||||
<div className="DocSearch-AskAiScreen-RelatedSources-List">
|
||||
{urlsToDisplay.length > 0 &&
|
||||
urlsToDisplay.map((link) => (
|
||||
<a
|
||||
key={link.url}
|
||||
href={link.url}
|
||||
className="DocSearch-AskAiScreen-RelatedSources-Item-Link"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<RelatedSourceIcon />
|
||||
<span>{link.title || link.url}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
{urlsToDisplay.length === 0 &&
|
||||
loadingStatus === 'loading' &&
|
||||
!hasHadAssistantResponse &&
|
||||
isExchangeLoading &&
|
||||
// eslint-disable-next-line react/no-array-index-key
|
||||
Array.from({ length: 3 }).map((_, index) => <SkeletonSource key={index} />)}
|
||||
|
||||
{contextToDisplay.length === 0 &&
|
||||
{urlsToDisplay.length === 0 &&
|
||||
(loadingStatus === 'idle' || loadingStatus === 'streaming') &&
|
||||
hasHadAssistantResponse &&
|
||||
!isExchangeLoading && (
|
||||
<p className="DocSearch-AskAiScreen-RelatedSources-NoResults">No related sources for the latest answer.</p>
|
||||
<p className="DocSearch-AskAiScreen-RelatedSources-NoResults">no related sources for the latest answer.</p>
|
||||
)}
|
||||
{contextToDisplay.length === 0 && loadingStatus === 'error' && (
|
||||
<p className="DocSearch-AskAiScreen-RelatedSources-Error">Could not load related sources.</p>
|
||||
{urlsToDisplay.length === 0 && loadingStatus === 'error' && (
|
||||
<p className="DocSearch-AskAiScreen-RelatedSources-Error">could not load related sources.</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ interface Message {
|
|||
role: 'assistant' | 'user';
|
||||
content: string;
|
||||
context?: AskAiResponse['context'];
|
||||
urls?: Array<{ url: string; title?: string }>;
|
||||
}
|
||||
|
||||
export interface AskAiState {
|
||||
|
|
@ -96,7 +97,7 @@ export function useAskAi({ genAiClient, conversations }: UseAskAiParams): AskAiS
|
|||
messages: [
|
||||
...(prevState.conversationId ? prevState.messages : []), // keep history if we have a conversationId
|
||||
{ id: userMessageId, role: 'user', content: query },
|
||||
{ id: assistantMessageId, role: 'assistant', content: '', context: [] },
|
||||
{ id: assistantMessageId, role: 'assistant', content: '', context: [], urls: [] },
|
||||
],
|
||||
loadingStatus: 'loading',
|
||||
query,
|
||||
|
|
@ -112,7 +113,14 @@ export function useAskAi({ genAiClient, conversations }: UseAskAiParams): AskAiS
|
|||
setState((prevState) => ({
|
||||
...prevState,
|
||||
messages: prevState.messages.map((m) =>
|
||||
m.id === assistantMessageId ? { ...m, content: chunk.response, context: chunk.context } : m,
|
||||
m.id === assistantMessageId
|
||||
? {
|
||||
...m,
|
||||
content: chunk.response,
|
||||
context: chunk.context,
|
||||
urls: extractLinksFromText(chunk.response),
|
||||
}
|
||||
: m,
|
||||
),
|
||||
loadingStatus: 'streaming',
|
||||
}));
|
||||
|
|
@ -215,3 +223,37 @@ export function useGenAiClient(
|
|||
|
||||
return genAiClient;
|
||||
}
|
||||
|
||||
// utility to extract links (markdown and bare urls) from a string
|
||||
function extractLinksFromText(text: string): Array<{ url: string; title?: string }> {
|
||||
// match [title](url) and bare urls
|
||||
const markdownLinkRegex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
|
||||
const urlRegex = /https?:\/\/[^\s)]+/g;
|
||||
const links: Array<{ url: string; title?: string }> = [];
|
||||
const seen = new Set<string>();
|
||||
|
||||
// extract markdown links first
|
||||
let match;
|
||||
while ((match = markdownLinkRegex.exec(text)) !== null) {
|
||||
let url = match[2];
|
||||
const title = match[1];
|
||||
// trim trailing punctuation
|
||||
url = url.replace(/[).,;!?]+$/, '');
|
||||
if (!seen.has(url)) {
|
||||
links.push({ url, title });
|
||||
seen.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
// extract bare urls
|
||||
while ((match = urlRegex.exec(text)) !== null) {
|
||||
let url = match[0];
|
||||
url = url.replace(/[).,;!?]+$/, '');
|
||||
if (!seen.has(url)) {
|
||||
links.push({ url });
|
||||
seen.add(url);
|
||||
}
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue