From c067df4e1bd465e3a75693188a4c3d58c41fce50 Mon Sep 17 00:00:00 2001
From: JOJO <1498581755@qq.com>
Date: Sat, 7 Mar 2026 17:50:35 +0800
Subject: [PATCH] feat: add include_domains search filter and UI display
---
core/main_terminal.py | 10 +++-
core/web_terminal.py | 3 ++
modules/search_engine.py | 49 ++++++++++++++++---
static/src/App.vue | 1 +
static/src/app.ts | 2 +
static/src/components/chat/ChatArea.vue | 6 ++-
static/src/components/chat/StackedBlocks.vue | 2 +
.../components/chat/actions/ToolAction.vue | 2 +
static/src/utils/chatDisplay.ts | 11 +++++
9 files changed, 78 insertions(+), 8 deletions(-)
diff --git a/core/main_terminal.py b/core/main_terminal.py
index 787ac7c..92115e6 100644
--- a/core/main_terminal.py
+++ b/core/main_terminal.py
@@ -1647,6 +1647,13 @@ class MainTerminal:
"country": {
"type": "string",
"description": "国家过滤,仅 topic=general 可用,使用英文小写国名"
+ },
+ "include_domains": {
+ "type": "array",
+ "description": "仅包含这些域名(可选,最多300个)",
+ "items": {
+ "type": "string"
+ }
}
}),
"required": ["query"]
@@ -2209,7 +2216,8 @@ class MainTerminal:
days=arguments.get("days"),
start_date=arguments.get("start_date"),
end_date=arguments.get("end_date"),
- country=arguments.get("country")
+ country=arguments.get("country"),
+ include_domains=arguments.get("include_domains")
)
if search_response["success"]:
diff --git a/core/web_terminal.py b/core/web_terminal.py
index d2d1b04..76daf3a 100644
--- a/core/web_terminal.py
+++ b/core/web_terminal.py
@@ -424,6 +424,9 @@ class WebTerminal(MainTerminal):
filters.append(f"{arguments.get('start_date')}~{arguments.get('end_date')}")
if arguments.get("country"):
filters.append(f"country={arguments.get('country')}")
+ include_domains = arguments.get("include_domains")
+ if isinstance(include_domains, list) and include_domains:
+ filters.append(f"include_domains={len(include_domains)}")
filter_text = " | ".join(filter_item for filter_item in filters if filter_item)
self.broadcast('tool_status', {
'tool': tool_name,
diff --git a/modules/search_engine.py b/modules/search_engine.py
index 85800f2..356ed9a 100644
--- a/modules/search_engine.py
+++ b/modules/search_engine.py
@@ -2,7 +2,7 @@
import httpx
import json
-from typing import Dict, Optional, Any
+from typing import Dict, Optional, Any, List
from datetime import datetime
import re
try:
@@ -42,7 +42,8 @@ class SearchEngine:
days: Optional[int] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
- country: Optional[str] = None
+ country: Optional[str] = None,
+ include_domains: Optional[List[str]] = None
) -> Dict:
"""
执行网络搜索
@@ -56,6 +57,7 @@ class SearchEngine:
start_date: 起始日期,格式YYYY-MM-DD
end_date: 结束日期,格式YYYY-MM-DD
country: 国家过滤,仅topic=general可用
+ include_domains: 仅包含这些域名(最多300个)
Returns:
搜索结果字典
@@ -75,7 +77,8 @@ class SearchEngine:
days=days,
start_date=start_date,
end_date=end_date,
- country=country
+ country=country,
+ include_domains=include_domains
)
if not validation["success"]:
@@ -165,7 +168,8 @@ class SearchEngine:
days: Optional[int] = None,
start_date: Optional[str] = None,
end_date: Optional[str] = None,
- country: Optional[str] = None
+ country: Optional[str] = None,
+ include_domains: Optional[List[str]] = None
) -> Dict[str, Any]:
"""
搜索并返回格式化的摘要
@@ -185,7 +189,8 @@ class SearchEngine:
days=days,
start_date=start_date,
end_date=end_date,
- country=country
+ country=country,
+ include_domains=include_domains
)
if not results["success"]:
@@ -326,7 +331,8 @@ class SearchEngine:
days: Optional[int],
start_date: Optional[str],
end_date: Optional[str],
- country: Optional[str]
+ country: Optional[str],
+ include_domains: Optional[List[str]]
) -> Dict[str, Any]:
"""验证并构建 Tavily 请求参数"""
payload: Dict[str, Any] = {
@@ -458,6 +464,35 @@ class SearchEngine:
}
payload["country"] = normalized_country
filters["country"] = normalized_country
+
+ # 域名白名单
+ if include_domains is not None:
+ if not isinstance(include_domains, list):
+ return {
+ "success": False,
+ "error": "include_domains 必须是字符串数组",
+ "results": []
+ }
+ cleaned_domains = []
+ for item in include_domains:
+ if not isinstance(item, str):
+ return {
+ "success": False,
+ "error": "include_domains 中每一项都必须是字符串",
+ "results": []
+ }
+ domain = item.strip().lower()
+ if domain:
+ cleaned_domains.append(domain)
+ if len(cleaned_domains) > 300:
+ return {
+ "success": False,
+ "error": f"include_domains 最多支持300个域名,当前: {len(cleaned_domains)}",
+ "results": []
+ }
+ if cleaned_domains:
+ payload["include_domains"] = cleaned_domains
+ filters["include_domains"] = cleaned_domains
return {
"success": True,
@@ -485,6 +520,8 @@ class SearchEngine:
if "country" in filters:
parts.append(f"Country: {filters['country']}")
+ if "include_domains" in filters:
+ parts.append(f"Domains: {len(filters['include_domains'])}")
if not parts:
return ""
diff --git a/static/src/App.vue b/static/src/App.vue
index 4d60a66..34da366 100644
--- a/static/src/App.vue
+++ b/static/src/App.vue
@@ -196,6 +196,7 @@
:get-tool-description="getToolDescription"
:format-search-topic="formatSearchTopic"
:format-search-time="formatSearchTime"
+ :format-search-domains="formatSearchDomains"
/>