feat(search): Implement OpenSearch support
This commit is contained in:
parent
e55f5ac941
commit
641968cf6a
6 changed files with 35 additions and 10 deletions
9
public/opensearch.xml
Normal file
9
public/opensearch.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
|
||||||
|
<ShortName>Perplexica</ShortName>
|
||||||
|
<Description>Search with Perplexica AI</Description>
|
||||||
|
<InputEncoding>UTF-8</InputEncoding>
|
||||||
|
<Image width="16" height="16" type="image/x-icon">/favicon.ico</Image>
|
||||||
|
<Url type="text/html" template="/?q={searchTerms}"/>
|
||||||
|
<Url type="application/opensearchdescription+xml" rel="self" template="/opensearch.xml"/>
|
||||||
|
</OpenSearchDescription>
|
||||||
|
|
@ -7,7 +7,7 @@ import db from '@/lib/db';
|
||||||
import { chats, messages as messagesSchema } from '@/lib/db/schema';
|
import { chats, messages as messagesSchema } from '@/lib/db/schema';
|
||||||
import {
|
import {
|
||||||
getAvailableChatModelProviders,
|
getAvailableChatModelProviders,
|
||||||
getAvailableEmbeddingModelProviders
|
getAvailableEmbeddingModelProviders,
|
||||||
} from '@/lib/providers';
|
} from '@/lib/providers';
|
||||||
import { searchHandlers } from '@/lib/search';
|
import { searchHandlers } from '@/lib/search';
|
||||||
import { getFileDetails } from '@/lib/utils/files';
|
import { getFileDetails } from '@/lib/utils/files';
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ export default function RootLayout({
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html className="h-full" lang="en" suppressHydrationWarning>
|
<html className="h-full" lang="en" suppressHydrationWarning>
|
||||||
|
<head>
|
||||||
|
<link
|
||||||
|
rel="search"
|
||||||
|
type="application/opensearchdescription+xml"
|
||||||
|
title="Perplexica Search"
|
||||||
|
href="/opensearch.xml"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
<body className={cn('h-full', montserrat.className)}>
|
<body className={cn('h-full', montserrat.className)}>
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<Sidebar>{children}</Sidebar>
|
<Sidebar>{children}</Sidebar>
|
||||||
|
|
|
||||||
|
|
@ -280,8 +280,12 @@ const MessageBox = ({
|
||||||
</div>
|
</div>
|
||||||
{message.searchQuery && (
|
{message.searchQuery && (
|
||||||
<div className="mb-2 text-sm bg-light-secondary dark:bg-dark-secondary rounded-lg p-3">
|
<div className="mb-2 text-sm bg-light-secondary dark:bg-dark-secondary rounded-lg p-3">
|
||||||
<span className="font-medium text-black/70 dark:text-white/70">Search query:</span>{' '}
|
<span className="font-medium text-black/70 dark:text-white/70">
|
||||||
<span className="text-black dark:text-white">{message.searchQuery}</span>
|
Search query:
|
||||||
|
</span>{' '}
|
||||||
|
<span className="text-black dark:text-white">
|
||||||
|
{message.searchQuery}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<MessageSources sources={message.sources} />
|
<MessageSources sources={message.sources} />
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ const MessageInput = ({
|
||||||
setMessage('');
|
setMessage('');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
@ -107,7 +107,7 @@ const MessageInput = ({
|
||||||
onChange={(e) => setMessage(e.target.value)}
|
onChange={(e) => setMessage(e.target.value)}
|
||||||
minRows={2}
|
minRows={2}
|
||||||
className="bg-transparent placeholder:text-black/50 dark:placeholder:text-white/50 text-sm text-black dark:text-white resize-none focus:outline-none w-full max-h-24 lg:max-h-36 xl:max-h-48"
|
className="bg-transparent placeholder:text-black/50 dark:placeholder:text-white/50 text-sm text-black dark:text-white resize-none focus:outline-none w-full max-h-24 lg:max-h-36 xl:max-h-48"
|
||||||
placeholder={firstMessage ? "Ask anything..." :"Ask a follow-up"}
|
placeholder={firstMessage ? 'Ask anything...' : 'Ask a follow-up'}
|
||||||
/>
|
/>
|
||||||
<div className="flex flex-row items-center justify-between mt-4">
|
<div className="flex flex-row items-center justify-between mt-4">
|
||||||
<div className="flex flex-row items-center space-x-2 lg:space-x-4">
|
<div className="flex flex-row items-center space-x-2 lg:space-x-4">
|
||||||
|
|
@ -134,7 +134,11 @@ const MessageInput = ({
|
||||||
className="bg-[#24A0ED] text-white disabled:text-black/50 dark:disabled:text-white/50 disabled:bg-[#e0e0dc] dark:disabled:bg-[#ececec21] hover:bg-opacity-85 transition duration-100 rounded-full p-2"
|
className="bg-[#24A0ED] text-white disabled:text-black/50 dark:disabled:text-white/50 disabled:bg-[#e0e0dc] dark:disabled:bg-[#ececec21] hover:bg-opacity-85 transition duration-100 rounded-full p-2"
|
||||||
type="submit"
|
type="submit"
|
||||||
>
|
>
|
||||||
{firstMessage ? <ArrowRight className="bg-background" size={17} /> : <ArrowUp className="bg-background" size={17} />}
|
{firstMessage ? (
|
||||||
|
<ArrowRight className="bg-background" size={17} />
|
||||||
|
) : (
|
||||||
|
<ArrowUp className="bg-background" size={17} />
|
||||||
|
)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ class MetaSearchAgent implements MetaSearchAgentType {
|
||||||
|
|
||||||
query = searchRetrieverResult.query;
|
query = searchRetrieverResult.query;
|
||||||
docs = searchRetrieverResult.docs;
|
docs = searchRetrieverResult.docs;
|
||||||
|
|
||||||
// Store the search query in the context for emitting to the client
|
// Store the search query in the context for emitting to the client
|
||||||
if (searchRetrieverResult.searchQuery) {
|
if (searchRetrieverResult.searchQuery) {
|
||||||
this.searchQuery = searchRetrieverResult.searchQuery;
|
this.searchQuery = searchRetrieverResult.searchQuery;
|
||||||
|
|
@ -453,10 +453,10 @@ class MetaSearchAgent implements MetaSearchAgentType {
|
||||||
if (this.searchQuery) {
|
if (this.searchQuery) {
|
||||||
emitter.emit(
|
emitter.emit(
|
||||||
'data',
|
'data',
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: 'sources',
|
type: 'sources',
|
||||||
data: sourcesData,
|
data: sourcesData,
|
||||||
searchQuery: this.searchQuery
|
searchQuery: this.searchQuery,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue