feat(web): use shared user-agent and send X-Keenable-Title

Drop the bespoke nanobot/<version> User-Agent in favor of self.user_agent
for consistency with every other search provider, and add an
X-Keenable-Title: nanobot header so Keenable can attribute traffic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ilya Gusev
2026-06-18 00:08:52 +08:00
committed by Xubin Ren
co-authored by Claude Opus 4.8
parent 83cb296cdc
commit 092b07c7aa
2 changed files with 7 additions and 4 deletions
+5 -3
View File
@@ -489,10 +489,12 @@ class WebSearchTool(Tool):
return f"Error: {e}"
async def _search_keenable(self, query: str, n: int) -> str:
from nanobot import __version__
api_key = self.config.api_key or os.environ.get("KEENABLE_API_KEY", "")
# First-party API: identify honestly instead of the spoofed browser UA.
headers = {"Content-Type": "application/json", "User-Agent": f"nanobot/{__version__}"}
headers = {
"Content-Type": "application/json",
"User-Agent": self.user_agent,
"X-Keenable-Title": "nanobot",
}
if api_key:
headers["X-API-Key"] = api_key
try:
+2 -1
View File
@@ -143,7 +143,8 @@ async def test_keenable_search(monkeypatch):
async def mock_post(self, url, **kw):
assert "keenable" in url
assert kw["headers"]["X-API-Key"] == "keen-key"
assert kw["headers"]["User-Agent"].startswith("nanobot/")
assert kw["headers"]["User-Agent"] == "nanobot-search-test"
assert kw["headers"]["X-Keenable-Title"] == "nanobot"
return _response(json={
"results": [{"title": "Keen", "url": "https://keenable.ai", "description": "short", "snippet": "longer excerpt"}]
})