diff --git a/src/app/api/chat/route.ts b/src/app/api/chat/route.ts
index 00b720b..d71856d 100644
--- a/src/app/api/chat/route.ts
+++ b/src/app/api/chat/route.ts
@@ -66,6 +66,7 @@ const handleEmitterEvents = async (
let recievedMessage = '';
let sources: any[] = [];
let searchQuery: string | undefined;
+ let searchUrl: string | undefined;
stream.on('data', (data) => {
const parsedData = JSON.parse(data);
@@ -86,6 +87,9 @@ const handleEmitterEvents = async (
if (parsedData.searchQuery) {
searchQuery = parsedData.searchQuery;
}
+ if (parsedData.searchUrl) {
+ searchUrl = parsedData.searchUrl;
+ }
writer.write(
encoder.encode(
@@ -94,6 +98,7 @@ const handleEmitterEvents = async (
data: parsedData.data,
searchQuery: parsedData.searchQuery,
messageId: aiMessageId,
+ searchUrl: searchUrl,
}) + '\n',
),
);
@@ -128,6 +133,7 @@ const handleEmitterEvents = async (
messageId: aiMessageId,
modelStats: modelStats,
searchQuery: searchQuery,
+ searchUrl: searchUrl,
}) + '\n',
),
);
@@ -144,6 +150,7 @@ const handleEmitterEvents = async (
...(sources && sources.length > 0 && { sources }),
...(searchQuery && { searchQuery }),
modelStats: modelStats,
+ ...(searchUrl && { searchUrl }),
}),
})
.execute();
diff --git a/src/components/ChatWindow.tsx b/src/components/ChatWindow.tsx
index 803d720..fa76796 100644
--- a/src/components/ChatWindow.tsx
+++ b/src/components/ChatWindow.tsx
@@ -28,6 +28,7 @@ export type Message = {
sources?: Document[];
modelStats?: ModelStats;
searchQuery?: string;
+ searchUrl?: string;
};
export interface File {
@@ -417,7 +418,6 @@ const ChatWindow = ({ id }: { id?: string }) => {
if (data.type === 'sources') {
sources = data.data;
- const searchQuery = data.searchQuery;
if (!added) {
setMessages((prevMessages) => [
...prevMessages,
@@ -427,7 +427,8 @@ const ChatWindow = ({ id }: { id?: string }) => {
chatId: chatId!,
role: 'assistant',
sources: sources,
- searchQuery: searchQuery,
+ searchQuery: data.searchQuery,
+ searchUrl: data.searchUrl,
createdAt: new Date(),
},
]);
@@ -486,6 +487,7 @@ const ChatWindow = ({ id }: { id?: string }) => {
modelStats: data.modelStats || null,
// Make sure the searchQuery is preserved (if available in the message data)
searchQuery: message.searchQuery || data.searchQuery,
+ searchUrl: message.searchUrl || data.searchUrl,
};
}
return message;
diff --git a/src/components/MessageBox.tsx b/src/components/MessageBox.tsx
index c657345..aff79c7 100644
--- a/src/components/MessageBox.tsx
+++ b/src/components/MessageBox.tsx
@@ -283,9 +283,20 @@ const MessageBox = ({
Search query:
{' '}
-
- {message.searchQuery}
-
+ {message.searchUrl ? (
+
+ {message.searchQuery}
+
+ ) : (
+
+ {message.searchQuery}
+
+ )}
)}
diff --git a/src/lib/search/metaSearchAgent.ts b/src/lib/search/metaSearchAgent.ts
index f452739..bf1c565 100644
--- a/src/lib/search/metaSearchAgent.ts
+++ b/src/lib/search/metaSearchAgent.ts
@@ -56,6 +56,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
private config: Config;
private strParser = new StringOutputParser();
private searchQuery?: string;
+ private searxngUrl?: string;
constructor(config: Config) {
this.config = config;
@@ -81,6 +82,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
let question = this.config.summarizer
? await questionOutputParser.parse(input)
: input;
+ console.log('question', question);
if (question === 'not_needed') {
return { query: '', docs: [] };
@@ -206,12 +208,15 @@ class MetaSearchAgent implements MetaSearchAgentType {
} else {
question = question.replace(/.*?<\/think>/g, '');
- const res = await searchSearxng(question, {
+ const searxngResult = await searchSearxng(question, {
language: 'en',
engines: this.config.activeEngines,
});
- const documents = res.results.map(
+ // Store the SearXNG URL for later use in emitting to the client
+ this.searxngUrl = searxngResult.searchUrl;
+
+ const documents = searxngResult.results.map(
(result) =>
new Document({
pageContent:
@@ -447,9 +452,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
event.event === 'on_chain_end' &&
event.name === 'FinalSourceRetriever'
) {
- // Add searchQuery to the sources data if it exists
const sourcesData = event.data.output;
- // @ts-ignore - we added searchQuery property
if (this.searchQuery) {
emitter.emit(
'data',
@@ -457,6 +460,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
type: 'sources',
data: sourcesData,
searchQuery: this.searchQuery,
+ searchUrl: this.searxngUrl,
}),
);
} else {
diff --git a/src/lib/searxng.ts b/src/lib/searxng.ts
index ae19db2..92dc2fc 100644
--- a/src/lib/searxng.ts
+++ b/src/lib/searxng.ts
@@ -19,6 +19,12 @@ interface SearxngSearchResult {
iframe_src?: string;
}
+interface SearxngResponse {
+ results: SearxngSearchResult[];
+ suggestions: string[];
+ searchUrl: string;
+}
+
export const searchSearxng = async (
query: string,
opts?: SearxngSearchOptions,
@@ -44,5 +50,16 @@ export const searchSearxng = async (
const results: SearxngSearchResult[] = res.data.results;
const suggestions: string[] = res.data.suggestions;
- return { results, suggestions };
+ // Create a URL for viewing the search results in the SearXNG web interface
+ const searchUrl = new URL(searxngURL);
+ searchUrl.pathname = '/search';
+ searchUrl.searchParams.append('q', query);
+ if (opts?.engines?.length) {
+ searchUrl.searchParams.append('engines', opts.engines.join(','));
+ }
+ if (opts?.language) {
+ searchUrl.searchParams.append('language', opts.language);
+ }
+
+ return { results, suggestions, searchUrl: searchUrl.toString() };
};