Skip to content

Commit 7e2fda0

Browse files
authored
feat: make google search and engin id optional (#361)
2 parents f28154c + 4767c6d commit 7e2fda0

File tree

5 files changed

+76
-112
lines changed

5 files changed

+76
-112
lines changed

backend/app/utils/agent.py

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -734,39 +734,43 @@ def search_agent(options: Chat):
734734
terminal_toolkit = message_integration.register_functions([terminal_toolkit.shell_exec])
735735
note_toolkit = NoteTakingToolkit(options.task_id, Agents.search_agent, working_directory=working_directory)
736736
note_toolkit = message_integration.register_toolkits(note_toolkit)
737-
search_toolkit = SearchToolkit(options.task_id)
738-
search_toolkit = message_integration.register_functions([search_toolkit.search_google])
737+
search_tools = SearchToolkit.get_can_use_tools(options.task_id)
738+
# Only register search tools if any are available
739+
if search_tools:
740+
search_tools = message_integration.register_functions(search_tools)
741+
else:
742+
search_tools = []
739743

740744
tools = [
741745
*HumanToolkit.get_can_use_tools(options.task_id, Agents.search_agent),
742746
*web_toolkit_custom.get_tools(),
743747
*terminal_toolkit,
744748
*note_toolkit.get_tools(),
745-
*search_toolkit,
749+
*search_tools,
746750
]
747751

748752
system_message = f"""
749753
<role>
750-
You are a Senior Research Analyst, a key member of a multi-agent team. Your
751-
primary responsibility is to conduct expert-level web research to gather,
752-
analyze, and document information required to solve the user's task. You
754+
You are a Senior Research Analyst, a key member of a multi-agent team. Your
755+
primary responsibility is to conduct expert-level web research to gather,
756+
analyze, and document information required to solve the user's task. You
753757
operate with precision, efficiency, and a commitment to data quality.
754758
You must use the search/browser tools to get the information you need.
755759
</role>
756760
757761
<team_structure>
758762
You collaborate with the following agents who can work in parallel:
759-
- **Developer Agent**: Writes and executes code, handles technical
763+
- **Developer Agent**: Writes and executes code, handles technical
760764
implementation.
761765
- **Document Agent**: Creates and manages documents and presentations.
762766
- **Multi-Modal Agent**: Processes and generates images and audio.
763-
Your research is the foundation of the team's work. Provide them with
767+
Your research is the foundation of the team's work. Provide them with
764768
comprehensive and well-documented information.
765769
</team_structure>
766770
767771
<operating_environment>
768772
- **System**: {platform.system()} ({platform.machine()})
769-
- **Working Directory**: `{working_directory}`. All local file operations must
773+
- **Working Directory**: `{working_directory}`. All local file operations must
770774
occur here, but you can access files from any place in the file system. For all file system operations, you MUST use absolute paths to ensure precision and avoid ambiguity.
771775
The current date is {datetime.date.today()}. For any date-related tasks, you MUST use this as the current date.
772776
</operating_environment>
@@ -786,13 +790,14 @@ def search_agent(options: Chat):
786790
you have discovered. High-quality, detailed notes are essential for the
787791
team's success.
788792
789-
- You MUST only use URLs from trusted sources. A trusted source is a URL
790-
that is either:
791-
1. Returned by a search tool (like `search_google`, `search_bing`,
792-
or `search_exa`).
793-
2. Found on a webpage you have visited.
794-
- You are strictly forbidden from inventing, guessing, or constructing URLs
795-
yourself. Fabricating URLs will be considered a critical error.
793+
- **CRITICAL URL POLICY**: You are STRICTLY FORBIDDEN from inventing,
794+
guessing, or constructing URLs yourself. You MUST only use URLs from
795+
trusted sources:
796+
1. URLs returned by search tools (like `search_google` or `search_exa`)
797+
2. URLs found on webpages you have visited through browser tools
798+
3. URLs provided by the user in their request
799+
Fabricating or guessing URLs is considered a critical error and must
800+
never be done under any circumstances.
796801
797802
- You MUST NOT answer from your own knowledge. All information
798803
MUST be sourced from the web using the available tools. If you don't know
@@ -816,26 +821,38 @@ def search_agent(options: Chat):
816821
</capabilities>
817822
818823
<web_search_workflow>
819-
- Initial Search: You MUST start with a search engine like `search_google` or
820-
`search_bing` to get a list of relevant URLs for your research, the URLs
821-
here will be used for `browser_visit_page`.
822-
- Browser-Based Exploration: Use the rich browser related toolset to
823-
investigate websites.
824-
- **Navigation and Exploration**: Use `browser_visit_page` to open a URL.
825-
`browser_visit_page` provides a snapshot of currently visible
826-
interactive elements, not the full page text. To see more content on
827-
long pages, Navigate with `browser_click`, `browser_back`, and
828-
`browser_forward`. Manage multiple pages with `browser_switch_tab`.
829-
- **Analysis**: Use `browser_get_som_screenshot` to understand the page
830-
layout and identify interactive elements. Since this is a heavy
831-
operation, only use it when visual analysis is necessary.
832-
- **Interaction**: Use `browser_type` to fill out forms and
833-
`browser_enter` to submit or confirm search.
834-
- Alternative Search: If you are unable to get sufficient
835-
information through browser-based exploration and scraping, use
836-
`search_exa`. This tool is best used for getting quick summaries or
837-
finding specific answers when visiting web page is could not find the
838-
information.
824+
Your approach depends on available search tools:
825+
826+
**If Google Search is Available:**
827+
- Initial Search: Start with `search_google` to get a list of relevant URLs
828+
- Browser-Based Exploration: Use the browser tools to investigate the URLs
829+
830+
**If Google Search is NOT Available:**
831+
- **MUST start with direct website search**: Use `browser_visit_page` to go
832+
directly to popular search engines and informational websites such as:
833+
* General search: google.com, bing.com, duckduckgo.com
834+
* Academic: scholar.google.com, pubmed.ncbi.nlm.nih.gov
835+
* News: news.google.com, bbc.com/news, reuters.com
836+
* Technical: stackoverflow.com, github.com
837+
* Reference: wikipedia.org, britannica.com
838+
- **Manual search process**: Type your query into the search boxes on these
839+
sites using `browser_type` and submit with `browser_enter`
840+
- **Extract URLs from results**: Only use URLs that appear in the search
841+
results on these websites
842+
- **Alternative Search**: If available, use `search_exa` for additional
843+
results
844+
845+
**Common Browser Operations (both scenarios):**
846+
- **Navigation and Exploration**: Use `browser_visit_page` to open URLs.
847+
`browser_visit_page` provides a snapshot of currently visible
848+
interactive elements, not the full page text. To see more content on
849+
long pages, Navigate with `browser_click`, `browser_back`, and
850+
`browser_forward`. Manage multiple pages with `browser_switch_tab`.
851+
- **Analysis**: Use `browser_get_som_screenshot` to understand the page
852+
layout and identify interactive elements. Since this is a heavy
853+
operation, only use it when visual analysis is necessary.
854+
- **Interaction**: Use `browser_type` to fill out forms and
855+
`browser_enter` to submit or confirm search.
839856
840857
- In your response, you should mention the URLs you have visited and processed.
841858

src/components/ChatBox/BottomInput.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ export const BottomInput = ({
312312
) : (
313313
<div className="mr-2 relative z-10 h-auto min-h-[82px] rounded-2xl bg-input-bg-default !px-2 !pb-2 gap-0 space-x-1 shadow-none border-solid border border-zinc-300">
314314
<Textarea
315-
disabled={!privacy || isPending || useCloudModelInDev}
315+
disabled={!privacy || isPending}
316316
ref={textareaRef}
317317
value={message}
318318
onChange={(e) => onMessageChange(e.target.value)}
@@ -386,7 +386,7 @@ export const BottomInput = ({
386386
<div className="flex items-center justify-between">
387387
<div className="flex items-center gap-1">
388388
<Button
389-
disabled={!privacy || isPending || useCloudModelInDev}
389+
disabled={!privacy || isPending}
390390
onClick={handleFileSelect}
391391
variant="ghost"
392392
size="icon"
@@ -400,7 +400,7 @@ export const BottomInput = ({
400400
</Button>
401401
</div>
402402
<Button
403-
disabled={!privacy || isPending || useCloudModelInDev}
403+
disabled={!privacy || isPending}
404404
onClick={() => {
405405
if (isPending) {
406406
if (isTakeControl) {

src/components/ChatBox/index.tsx

Lines changed: 3 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default function ChatBox(): JSX.Element {
2626
const { modelType } = useAuthStore();
2727
const [useCloudModelInDev, setUseCloudModelInDev] = useState(false);
2828
useEffect(() => {
29+
// Only show warning message, don't block functionality
2930
if (
3031
import.meta.env.VITE_USE_LOCAL_PROXY === "true" &&
3132
modelType === "cloud"
@@ -599,39 +600,8 @@ export default function ChatBox(): JSX.Element {
599600
</span>
600601
</div>
601602
</div>
602-
) : useCloudModelInDev ? (
603-
<div className="flex items-center gap-2">
604-
<div
605-
onClick={() => {
606-
navigate("/setting/models");
607-
}}
608-
className="cursor-pointer flex items-center gap-1 px-sm py-xs rounded-md bg-surface-information"
609-
>
610-
<span className="text-text-information text-sm font-medium leading-[22px]">
611-
{t("chat.you-are-using-self-hosted-mode")}
612-
</span>
613-
</div>
614-
</div>
615-
) : (
616-
!hasSearchKey &&
617-
modelType !== "cloud" && (
618-
<div className="flex items-center gap-2">
619-
<div
620-
onClick={() => {
621-
navigate("/setting/mcp");
622-
}}
623-
className="cursor-pointer flex items-center gap-1 px-sm py-xs rounded-md bg-surface-information"
624-
>
625-
<span className="text-text-information text-sm font-medium leading-[22px]">
626-
{t("chat.you-are-using-self-hosted-mode")}
627-
</span>
628-
</div>
629-
</div>
630-
)
631-
)}
632-
{!useCloudModelInDev &&
633-
privacy &&
634-
(hasSearchKey || modelType === "cloud") && (
603+
) : null}
604+
{privacy && (
635605
<div className="mr-2 flex flex-col items-center gap-2">
636606
{[
637607
{

src/i18n/locales/en-us/setting.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@
118118
"search-mcp": "Search MCPs",
119119
"installed": "Installed",
120120
"worker-name-cannot-be-empty": "Worker name cannot be empty",
121-
"worker-name-already-exists": "Worker name already exists"
121+
"worker-name-already-exists": "Worker name already exists",
122+
"warning-google-search-not-configured": "Warning: Google Search not configured",
123+
"search-functionality-may-be-limited-without-google-api": "Search functionality may be limited without Google API key and Search Engine ID. You can configure these in MCP & Tools settings."
122124
}
123125

src/pages/Setting/Models.tsx

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ import {
3636
} from "@/components/ui/tooltip";
3737
import { useAuthStore } from "@/store/authStore";
3838
import { toast } from "sonner";
39-
import {
40-
Dialog,
41-
DialogContent,
42-
DialogHeader,
43-
DialogTitle,
44-
DialogFooter,
45-
DialogDescription,
46-
} from "@/components/ui/dialog";
4739
import { useTranslation } from "react-i18next";
4840

4941
export default function SettingModels() {
@@ -93,7 +85,6 @@ export default function SettingModels() {
9385
const [localError, setLocalError] = useState<string | null>(null);
9486
const [localInputError, setLocalInputError] = useState(false);
9587
const [localPrefer, setLocalPrefer] = useState(false); // Local model prefer state
96-
const [dialogVisible, setDialogVisible] = useState<boolean>(false);
9788
const [localProviderId, setLocalProviderId] = useState<number | undefined>(
9889
undefined
9990
); // Local model provider_id
@@ -479,9 +470,13 @@ export default function SettingModels() {
479470
setLocalEnabled(true);
480471
return;
481472
}
482-
if (!(await checkHasSearchKey())) {
483-
setDialogVisible(true);
484-
return;
473+
const hasSearchKey = await checkHasSearchKey();
474+
if (!hasSearchKey) {
475+
// Show warning toast instead of blocking
476+
toast(t("setting.warning-google-search-not-configured"), {
477+
description: t("setting.search-functionality-may-be-limited-without-google-api"),
478+
closeButton: true,
479+
});
485480
}
486481
try {
487482
await proxyFetchPost("/api/provider/prefer", {
@@ -502,9 +497,13 @@ export default function SettingModels() {
502497
setLocalEnabled(false);
503498
return;
504499
}
505-
if (!(await checkHasSearchKey())) {
506-
setDialogVisible(true);
507-
return;
500+
const hasSearchKey = await checkHasSearchKey();
501+
if (!hasSearchKey) {
502+
// Show warning toast instead of blocking
503+
toast(t("setting.warning-google-search-not-configured"), {
504+
description: t("setting.search-functionality-may-be-limited-without-google-api"),
505+
closeButton: true,
506+
});
508507
}
509508
try {
510509
if (localProviderId === undefined) return;
@@ -1042,30 +1041,6 @@ export default function SettingModels() {
10421041
</Button>
10431042
</div>
10441043
</div>
1045-
{/* error dialog */}
1046-
<Dialog
1047-
open={dialogVisible}
1048-
onOpenChange={() => navigate("/setting/mcp")}
1049-
>
1050-
<DialogContent className="bg-white-100%">
1051-
<DialogHeader>
1052-
<DialogTitle>{t("setting.you-are-on-selft-host-mode")}</DialogTitle>
1053-
</DialogHeader>
1054-
<DialogDescription className="space-y-2">
1055-
<p className="indent-6">
1056-
{t("setting.you-are-using-self-hosted-mode")}
1057-
1058-
</p>
1059-
<p className="indent-6">
1060-
{t("setting.the-google-search-key-is-essential-for-delivering-accurate-search-results")}
1061-
1062-
</p>
1063-
</DialogDescription>
1064-
<DialogFooter>
1065-
<Button onClick={() => navigate("/setting/mcp")}>{t("setting.close")}</Button>
1066-
</DialogFooter>
1067-
</DialogContent>
1068-
</Dialog>
10691044
</div>
10701045
);
10711046
}

0 commit comments

Comments
 (0)