feat(tools): add support for self-hosted firecrawl
Adds optional FIRECRAWL_API_URL environment variable to support self-hosted Firecrawl deployments alongside the cloud service. - Add FIRECRAWL_API_URL to optional env vars in hermes_cli/config.py - Update _get_firecrawl_client() in tools/web_tools.py to accept custom API URL - Add tests for client initialization with/without URL - Document new env var in installation and config guides
This commit is contained in:
parent
21d61bdd71
commit
d7d10b14cd
7 changed files with 68 additions and 2 deletions
|
|
@ -421,6 +421,7 @@ The system uses `_config_version` to detect outdated configs:
|
||||||
API keys are loaded from `~/.hermes/.env`:
|
API keys are loaded from `~/.hermes/.env`:
|
||||||
- `OPENROUTER_API_KEY` - Main LLM API access (primary provider)
|
- `OPENROUTER_API_KEY` - Main LLM API access (primary provider)
|
||||||
- `FIRECRAWL_API_KEY` - Web search/extract tools
|
- `FIRECRAWL_API_KEY` - Web search/extract tools
|
||||||
|
- `FIRECRAWL_API_URL` - Self-hosted Firecrawl endpoint (optional)
|
||||||
- `BROWSERBASE_API_KEY` / `BROWSERBASE_PROJECT_ID` - Browser automation
|
- `BROWSERBASE_API_KEY` / `BROWSERBASE_PROJECT_ID` - Browser automation
|
||||||
- `FAL_KEY` - Image generation (FLUX model)
|
- `FAL_KEY` - Image generation (FLUX model)
|
||||||
- `NOUS_API_KEY` - Vision and Mixture-of-Agents tools
|
- `NOUS_API_KEY` - Vision and Mixture-of-Agents tools
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,14 @@ OPTIONAL_ENV_VARS = {
|
||||||
"password": True,
|
"password": True,
|
||||||
"category": "tool",
|
"category": "tool",
|
||||||
},
|
},
|
||||||
|
"FIRECRAWL_API_URL": {
|
||||||
|
"description": "Firecrawl API URL for self-hosted instances (optional)",
|
||||||
|
"prompt": "Firecrawl API URL (leave empty for cloud)",
|
||||||
|
"url": None,
|
||||||
|
"password": False,
|
||||||
|
"category": "tool",
|
||||||
|
"advanced": True,
|
||||||
|
},
|
||||||
"BROWSERBASE_API_KEY": {
|
"BROWSERBASE_API_KEY": {
|
||||||
"description": "Browserbase API key for browser automation",
|
"description": "Browserbase API key for browser automation",
|
||||||
"prompt": "Browserbase API key",
|
"prompt": "Browserbase API key",
|
||||||
|
|
@ -821,7 +829,7 @@ def set_config_value(key: str, value: str):
|
||||||
# Check if it's an API key (goes to .env)
|
# Check if it's an API key (goes to .env)
|
||||||
api_keys = [
|
api_keys = [
|
||||||
'OPENROUTER_API_KEY', 'ANTHROPIC_API_KEY', 'VOICE_TOOLS_OPENAI_KEY',
|
'OPENROUTER_API_KEY', 'ANTHROPIC_API_KEY', 'VOICE_TOOLS_OPENAI_KEY',
|
||||||
'FIRECRAWL_API_KEY', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID',
|
'FIRECRAWL_API_KEY', 'FIRECRAWL_API_URL', 'BROWSERBASE_API_KEY', 'BROWSERBASE_PROJECT_ID',
|
||||||
'FAL_KEY', 'TELEGRAM_BOT_TOKEN', 'DISCORD_BOT_TOKEN',
|
'FAL_KEY', 'TELEGRAM_BOT_TOKEN', 'DISCORD_BOT_TOKEN',
|
||||||
'TERMINAL_SSH_HOST', 'TERMINAL_SSH_USER', 'TERMINAL_SSH_KEY',
|
'TERMINAL_SSH_HOST', 'TERMINAL_SSH_USER', 'TERMINAL_SSH_KEY',
|
||||||
'SUDO_PASSWORD', 'SLACK_BOT_TOKEN', 'SLACK_APP_TOKEN',
|
'SUDO_PASSWORD', 'SLACK_BOT_TOKEN', 'SLACK_APP_TOKEN',
|
||||||
|
|
|
||||||
49
tests/tools/test_web_tools_config.py
Normal file
49
tests/tools/test_web_tools_config.py
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
"""Tests for Firecrawl client configuration."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
|
||||||
|
class TestFirecrawlClientConfig:
|
||||||
|
"""Test suite for Firecrawl client initialization with API URL support."""
|
||||||
|
|
||||||
|
def teardown_method(self):
|
||||||
|
"""Reset client between tests."""
|
||||||
|
import tools.web_tools
|
||||||
|
|
||||||
|
tools.web_tools._firecrawl_client = None
|
||||||
|
|
||||||
|
def test_client_with_api_key_only(self):
|
||||||
|
"""Test client initialization with only API key (no custom URL)."""
|
||||||
|
env_vars = {"FIRECRAWL_API_KEY": "test-key"}
|
||||||
|
env_vars.pop("FIRECRAWL_API_URL", None)
|
||||||
|
|
||||||
|
with patch.dict(os.environ, env_vars, clear=False):
|
||||||
|
# Remove FIRECRAWL_API_URL from env if it exists
|
||||||
|
if "FIRECRAWL_API_URL" in os.environ:
|
||||||
|
del os.environ["FIRECRAWL_API_URL"]
|
||||||
|
|
||||||
|
with patch("tools.web_tools.Firecrawl") as mock_firecrawl:
|
||||||
|
from tools.web_tools import _get_firecrawl_client
|
||||||
|
|
||||||
|
_get_firecrawl_client()
|
||||||
|
mock_firecrawl.assert_called_once_with(api_key="test-key")
|
||||||
|
|
||||||
|
def test_client_with_api_key_and_url(self):
|
||||||
|
"""Test client initialization with API key and custom URL."""
|
||||||
|
with patch.dict(
|
||||||
|
os.environ,
|
||||||
|
{
|
||||||
|
"FIRECRAWL_API_KEY": "test-key",
|
||||||
|
"FIRECRAWL_API_URL": "http://localhost:3002",
|
||||||
|
},
|
||||||
|
clear=False,
|
||||||
|
):
|
||||||
|
with patch("tools.web_tools.Firecrawl") as mock_firecrawl:
|
||||||
|
from tools.web_tools import _get_firecrawl_client
|
||||||
|
|
||||||
|
_get_firecrawl_client()
|
||||||
|
mock_firecrawl.assert_called_once_with(
|
||||||
|
api_key="test-key", api_url="http://localhost:3002"
|
||||||
|
)
|
||||||
|
|
@ -62,7 +62,12 @@ def _get_firecrawl_client():
|
||||||
api_key = os.getenv("FIRECRAWL_API_KEY")
|
api_key = os.getenv("FIRECRAWL_API_KEY")
|
||||||
if not api_key:
|
if not api_key:
|
||||||
raise ValueError("FIRECRAWL_API_KEY environment variable not set")
|
raise ValueError("FIRECRAWL_API_KEY environment variable not set")
|
||||||
_firecrawl_client = Firecrawl(api_key=api_key)
|
|
||||||
|
api_url = os.getenv("FIRECRAWL_API_URL")
|
||||||
|
if api_url:
|
||||||
|
_firecrawl_client = Firecrawl(api_key=api_key, api_url=api_url)
|
||||||
|
else:
|
||||||
|
_firecrawl_client = Firecrawl(api_key=api_key)
|
||||||
return _firecrawl_client
|
return _firecrawl_client
|
||||||
|
|
||||||
DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION = 5000
|
DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION = 5000
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,7 @@ OPENROUTER_API_KEY=sk-or-v1-your-key-here
|
||||||
|
|
||||||
# Optional — enable additional tools:
|
# Optional — enable additional tools:
|
||||||
FIRECRAWL_API_KEY=fc-your-key # Web search & scraping
|
FIRECRAWL_API_KEY=fc-your-key # Web search & scraping
|
||||||
|
FIRECRAWL_API_URL=http://localhost:3002 # Self-hosted Firecrawl (optional)
|
||||||
FAL_KEY=your-fal-key # Image generation (FLUX)
|
FAL_KEY=your-fal-key # Image generation (FLUX)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config
|
||||||
| Variable | Description |
|
| Variable | Description |
|
||||||
|----------|-------------|
|
|----------|-------------|
|
||||||
| `FIRECRAWL_API_KEY` | Web scraping ([firecrawl.dev](https://firecrawl.dev/)) |
|
| `FIRECRAWL_API_KEY` | Web scraping ([firecrawl.dev](https://firecrawl.dev/)) |
|
||||||
|
| `FIRECRAWL_API_URL` | Custom Firecrawl API endpoint for self-hosted instances (optional) |
|
||||||
| `BROWSERBASE_API_KEY` | Browser automation ([browserbase.com](https://browserbase.com/)) |
|
| `BROWSERBASE_API_KEY` | Browser automation ([browserbase.com](https://browserbase.com/)) |
|
||||||
| `BROWSERBASE_PROJECT_ID` | Browserbase project ID |
|
| `BROWSERBASE_PROJECT_ID` | Browserbase project ID |
|
||||||
| `BROWSER_INACTIVITY_TIMEOUT` | Browser session inactivity timeout in seconds |
|
| `BROWSER_INACTIVITY_TIMEOUT` | Browser session inactivity timeout in seconds |
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ Even when using Nous Portal, Codex, or a custom endpoint, some tools (vision, we
|
||||||
| Feature | Provider | Env Variable |
|
| Feature | Provider | Env Variable |
|
||||||
|---------|----------|--------------|
|
|---------|----------|--------------|
|
||||||
| Web scraping | [Firecrawl](https://firecrawl.dev/) | `FIRECRAWL_API_KEY` |
|
| Web scraping | [Firecrawl](https://firecrawl.dev/) | `FIRECRAWL_API_KEY` |
|
||||||
|
| Web scraping (self-hosted) | Firecrawl | `FIRECRAWL_API_URL` |
|
||||||
| Browser automation | [Browserbase](https://browserbase.com/) | `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` |
|
| Browser automation | [Browserbase](https://browserbase.com/) | `BROWSERBASE_API_KEY`, `BROWSERBASE_PROJECT_ID` |
|
||||||
| Image generation | [FAL](https://fal.ai/) | `FAL_KEY` |
|
| Image generation | [FAL](https://fal.ai/) | `FAL_KEY` |
|
||||||
| Premium TTS voices | [ElevenLabs](https://elevenlabs.io/) | `ELEVENLABS_API_KEY` |
|
| Premium TTS voices | [ElevenLabs](https://elevenlabs.io/) | `ELEVENLABS_API_KEY` |
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue