mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-09-13 23:48:53 +00:00
fix(firecrawl): pass tool base_url to FirecrawlApp as api_url (#5392)
_get_firecrawl_client only read api_key from the tool config and ignored base_url, so self-hosted Firecrawl deployments were unreachable: the SDK defaulted to https://api.firecrawl.dev and raised 'No API key provided'. Now base_url is forwarded as api_url; api_url is omitted when unset so cloud behavior is unchanged. Also document the optional self-hosted base_url on both Firecrawl entries in config.example.yaml and reconcile their headers to the fastCRW house style (Cloud requires FIRECRAWL_API_KEY; self-host may need no key.).
This commit is contained in:
parent
dfe9a520b9
commit
b448c02bbe
@ -9,9 +9,16 @@ from deerflow.config import get_app_config
|
||||
def _get_firecrawl_client(tool_name: str = "web_search") -> FirecrawlApp:
|
||||
config = get_app_config().get_tool_config(tool_name)
|
||||
api_key = None
|
||||
if config is not None and "api_key" in config.model_extra:
|
||||
api_key = config.model_extra.get("api_key")
|
||||
return FirecrawlApp(api_key=api_key) # type: ignore[arg-type]
|
||||
api_url = None
|
||||
if config is not None:
|
||||
if "api_key" in config.model_extra:
|
||||
api_key = config.model_extra.get("api_key")
|
||||
if "base_url" in config.model_extra:
|
||||
api_url = config.model_extra.get("base_url")
|
||||
kwargs = {"api_key": api_key}
|
||||
if api_url:
|
||||
kwargs["api_url"] = api_url
|
||||
return FirecrawlApp(**kwargs) # type: ignore[arg-type]
|
||||
|
||||
|
||||
@tool("web_search", parse_docstring=True)
|
||||
|
||||
@ -64,3 +64,51 @@ class TestWebFetchTool:
|
||||
"https://example.com",
|
||||
formats=["markdown"],
|
||||
)
|
||||
|
||||
|
||||
class TestFirecrawlBaseUrl:
|
||||
@patch("deerflow.community.firecrawl.tools.FirecrawlApp")
|
||||
@patch("deerflow.community.firecrawl.tools.get_app_config")
|
||||
def test_fetch_passes_base_url_as_api_url(self, mock_get_app_config, mock_firecrawl_cls):
|
||||
fetch_config = MagicMock()
|
||||
fetch_config.model_extra = {"base_url": "http://192.168.0.47:3002"}
|
||||
|
||||
def get_tool_config(name):
|
||||
if name == "web_fetch":
|
||||
return fetch_config
|
||||
return None
|
||||
|
||||
mock_get_app_config.return_value.get_tool_config.side_effect = get_tool_config
|
||||
|
||||
mock_scrape_result = MagicMock()
|
||||
mock_scrape_result.markdown = "Fetched markdown"
|
||||
mock_scrape_result.metadata = MagicMock(title="Fetched Page")
|
||||
mock_firecrawl_cls.return_value.scrape.return_value = mock_scrape_result
|
||||
|
||||
from deerflow.community.firecrawl.tools import web_fetch_tool
|
||||
|
||||
result = web_fetch_tool.invoke({"url": "https://example.com"})
|
||||
|
||||
assert result == "# Fetched Page\n\nFetched markdown"
|
||||
mock_firecrawl_cls.assert_called_once_with(api_key=None, api_url="http://192.168.0.47:3002")
|
||||
|
||||
@patch("deerflow.community.firecrawl.tools.FirecrawlApp")
|
||||
@patch("deerflow.community.firecrawl.tools.get_app_config")
|
||||
def test_search_passes_base_url_and_api_key(self, mock_get_app_config, mock_firecrawl_cls):
|
||||
search_config = MagicMock()
|
||||
search_config.model_extra = {
|
||||
"api_key": "firecrawl-key",
|
||||
"base_url": "http://192.168.0.47:3002",
|
||||
"max_results": 5,
|
||||
}
|
||||
mock_get_app_config.return_value.get_tool_config.return_value = search_config
|
||||
|
||||
mock_result = MagicMock()
|
||||
mock_result.web = []
|
||||
mock_firecrawl_cls.return_value.search.return_value = mock_result
|
||||
|
||||
from deerflow.community.firecrawl.tools import web_search_tool
|
||||
|
||||
web_search_tool.invoke({"query": "test query"})
|
||||
|
||||
mock_firecrawl_cls.assert_called_once_with(api_key="firecrawl-key", api_url="http://192.168.0.47:3002")
|
||||
|
||||
@ -868,12 +868,13 @@ tools:
|
||||
# contents_max_characters: 1000
|
||||
# # api_key: $EXA_API_KEY
|
||||
|
||||
# Web search tool (uses Firecrawl, requires FIRECRAWL_API_KEY)
|
||||
# Web search tool (uses Firecrawl. Cloud requires FIRECRAWL_API_KEY; self-host may need no key.)
|
||||
# - name: web_search
|
||||
# group: web
|
||||
# use: deerflow.community.firecrawl.tools:web_search_tool
|
||||
# max_results: 5
|
||||
# # api_key: $FIRECRAWL_API_KEY
|
||||
# # base_url: http://<host>:3002 # optional: self-hosted Firecrawl; no cloud API key needed
|
||||
|
||||
# Web search tool (uses GroundRoute, requires GROUNDROUTE_API_KEY)
|
||||
# GroundRoute is a meta search layer: one API in front of six engines (Serper,
|
||||
@ -1059,11 +1060,12 @@ tools:
|
||||
# # Timeout for navigating to the page (in seconds). Set to positive value to enable, -1 to disable
|
||||
# navigation_timeout: 30
|
||||
|
||||
# Web fetch tool (uses Firecrawl, requires FIRECRAWL_API_KEY)
|
||||
# Web fetch tool (uses Firecrawl. Cloud requires FIRECRAWL_API_KEY; self-host may need no key.)
|
||||
# - name: web_fetch
|
||||
# group: web
|
||||
# use: deerflow.community.firecrawl.tools:web_fetch_tool
|
||||
# # api_key: $FIRECRAWL_API_KEY
|
||||
# # base_url: http://<host>:3002 # optional: self-hosted Firecrawl; no cloud API key needed
|
||||
|
||||
# Web fetch tool (uses GroundRoute, requires GROUNDROUTE_API_KEY)
|
||||
# Fetches a page's extracted text via GroundRoute mode=page.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user