import React, { useEffect, useRef, useState } from "react";
import Admin from "@/models/admin";
import SerpApiIcon from "./icons/serpapi.png";
import SearchApiIcon from "./icons/searchapi.png";
import SerperDotDevIcon from "./icons/serper.png";
import BingSearchIcon from "./icons/bing.png";
import BaiduSearchIcon from "./icons/baidu.png";
import SerplySearchIcon from "./icons/serply.png";
import SearXNGSearchIcon from "./icons/searxng.png";
import TavilySearchIcon from "./icons/tavily.svg";
import DuckDuckGoIcon from "./icons/duckduckgo.png";
import ExaIcon from "./icons/exa.png";
import PerplexitySearchIcon from "./icons/perplexity.png";
import {
CaretUpDown,
MagnifyingGlass,
X,
ListMagnifyingGlass,
} from "@phosphor-icons/react";
import Toggle from "@/components/lib/Toggle";
import SearchProviderItem from "./SearchProviderItem";
import WebSearchImage from "@/media/agents/scrape-websites.png";
import {
SerpApiOptions,
SearchApiOptions,
SerperDotDevOptions,
BingSearchOptions,
BaiduSearchOptions,
SerplySearchOptions,
SearXNGOptions,
TavilySearchOptions,
DuckDuckGoOptions,
ExaSearchOptions,
PerplexitySearchOptions,
} from "./SearchProviderOptions";
const SEARCH_PROVIDERS = [
{
name: "DuckDuckGo",
value: "duckduckgo-engine",
logo: DuckDuckGoIcon,
options: () => ,
description: "Free and privacy-focused web search using DuckDuckGo.",
},
{
name: "SerpApi",
value: "serpapi",
logo: SerpApiIcon,
options: (settings) => ,
description:
"Scrape Google and several other search engines with SerpApi. 250 free searches every month, and then paid.",
},
{
name: "SearchApi",
value: "searchapi",
logo: SearchApiIcon,
options: (settings) => ,
description:
"SearchApi delivers structured data from multiple search engines. Free for 100 queries, but then paid. ",
},
{
name: "Serper.dev",
value: "serper-dot-dev",
logo: SerperDotDevIcon,
options: (settings) => ,
description:
"Serper.dev web-search. Free account with a 2,500 calls, but then paid.",
},
{
name: "Bing Search",
value: "bing-search",
logo: BingSearchIcon,
options: (settings) => ,
description: "Web search powered by the Bing Search API (paid service).",
},
{
name: "Baidu Search",
value: "baidu-search",
logo: BaiduSearchIcon,
options: (settings) => ,
description:
"Web search powered by Baidu Search for stronger zh-CN retrieval.",
},
{
name: "Serply.io",
value: "serply-engine",
logo: SerplySearchIcon,
options: (settings) => ,
description:
"Serply.io web-search. Free account with a 100 calls/month forever.",
},
{
name: "SearXNG",
value: "searxng-engine",
logo: SearXNGSearchIcon,
options: (settings) => ,
description:
"Free, open-source, internet meta-search engine with no tracking.",
},
{
name: "Tavily Search",
value: "tavily-search",
logo: TavilySearchIcon,
options: (settings) => ,
description:
"Tavily Search API. Offers a free tier with 1000 queries per month.",
},
{
name: "Exa Search",
value: "exa-search",
logo: ExaIcon,
options: (settings) => ,
description:
"One of the best web search APIs for AI agents with real-time results and full page contents.",
},
{
name: "Perplexity Search",
value: "perplexity-search",
logo: PerplexitySearchIcon,
options: (settings) => ,
description: "AI-powered web search using the Perplexity Search API.",
},
];
export default function AgentWebSearchSelection({
skill,
title,
description,
settings,
toggleSkill,
enabled = false,
setHasChanges,
}) {
const searchInputRef = useRef(null);
const [filteredResults, setFilteredResults] = useState([]);
const [selectedProvider, setSelectedProvider] = useState("duckduckgo-engine");
const [searchQuery, setSearchQuery] = useState("");
const [searchMenuOpen, setSearchMenuOpen] = useState(false);
function updateChoice(selection) {
setSearchQuery("");
setSelectedProvider(selection);
setSearchMenuOpen(false);
setHasChanges(true);
}
function handleXButton() {
if (searchQuery.length > 0) {
setSearchQuery("");
if (searchInputRef.current) searchInputRef.current.value = "";
} else {
setSearchMenuOpen(!searchMenuOpen);
}
}
useEffect(() => {
const filtered = SEARCH_PROVIDERS.filter((provider) =>
provider.name.toLowerCase().includes(searchQuery.toLowerCase())
);
setFilteredResults(filtered);
}, [searchQuery, selectedProvider]);
useEffect(() => {
Admin.systemPreferencesByFields(["agent_search_provider"])
.then((res) =>
setSelectedProvider(
res?.settings?.agent_search_provider ?? "duckduckgo-engine"
)
)
.catch(() => setSelectedProvider("duckduckgo-engine"));
}, []);
const selectedSearchProviderObject =
SEARCH_PROVIDERS.find((provider) => provider.value === selectedProvider) ??
SEARCH_PROVIDERS[1];
return (
toggleSkill(skill)}
/>
{description}
{searchMenuOpen && (
setSearchMenuOpen(false)}
/>
)}
{searchMenuOpen ? (
) : (
)}
{selectedSearchProviderObject.options(settings)}
);
}