diff --git a/docs/bundles/ai-bundle.rst b/docs/bundles/ai-bundle.rst index 8ad5b3c56..d5ff521ed 100644 --- a/docs/bundles/ai-bundle.rst +++ b/docs/bundles/ai-bundle.rst @@ -787,7 +787,7 @@ To use existing tools, you can register them as a service: Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch: ~ Symfony\AI\Agent\Toolbox\Tool\Wikipedia: ~ Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber: ~ - Symfony\AI\Agent\Toolbox\Tool\Firecrawl: + Symfony\AI\Agent\Bridge\Firecrawl\Firecrawl: $endpoint: '%env(FIRECRAWL_ENDPOINT)%' $apiKey: '%env(FIRECRAWL_API_KEY)%' Symfony\AI\Agent\Bridge\Brave\Brave: diff --git a/examples/toolbox/firecrawl-crawl.php b/examples/toolbox/firecrawl-crawl.php index 114c781e6..cc86d1878 100644 --- a/examples/toolbox/firecrawl-crawl.php +++ b/examples/toolbox/firecrawl-crawl.php @@ -10,8 +10,8 @@ */ use Symfony\AI\Agent\Agent; +use Symfony\AI\Agent\Bridge\Firecrawl\Firecrawl; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Firecrawl; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; diff --git a/examples/toolbox/firecrawl-map.php b/examples/toolbox/firecrawl-map.php index 21084c8b7..9dfa34e38 100644 --- a/examples/toolbox/firecrawl-map.php +++ b/examples/toolbox/firecrawl-map.php @@ -10,8 +10,8 @@ */ use Symfony\AI\Agent\Agent; +use Symfony\AI\Agent\Bridge\Firecrawl\Firecrawl; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Firecrawl; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; diff --git a/examples/toolbox/firecrawl-scrape.php b/examples/toolbox/firecrawl-scrape.php index be9565fef..3aba4ff4d 100644 --- a/examples/toolbox/firecrawl-scrape.php +++ b/examples/toolbox/firecrawl-scrape.php @@ -10,8 +10,8 @@ */ use Symfony\AI\Agent\Agent; +use Symfony\AI\Agent\Bridge\Firecrawl\Firecrawl; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Firecrawl; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; diff --git a/src/agent/src/Bridge/Firecrawl/.gitattributes b/src/agent/src/Bridge/Firecrawl/.gitattributes new file mode 100644 index 000000000..14c3c3594 --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/.gitattributes @@ -0,0 +1,3 @@ +/Tests export-ignore +/phpunit.xml.dist export-ignore +/.git* export-ignore diff --git a/src/agent/src/Bridge/Firecrawl/.github/PULL_REQUEST_TEMPLATE.md b/src/agent/src/Bridge/Firecrawl/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..fcb87228a --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +Please do not submit any Pull Requests here. They will be closed. +--- + +Please submit your PR here instead: +https://github.com/symfony/ai + +This repository is what we call a "subtree split": a read-only subset of that main repository. +We're looking forward to your PR there! diff --git a/src/agent/src/Bridge/Firecrawl/.github/close-pull-request.yml b/src/agent/src/Bridge/Firecrawl/.github/close-pull-request.yml new file mode 100644 index 000000000..bb5a02835 --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/.github/close-pull-request.yml @@ -0,0 +1,20 @@ +name: Close Pull Request + +on: + pull_request_target: + types: [opened] + +jobs: + run: + runs-on: ubuntu-latest + steps: + - uses: superbrothers/close-pull-request@v3 + with: + comment: | + Thanks for your Pull Request! We love contributions. + + However, you should instead open your PR on the main repository: + https://github.com/symfony/ai + + This repository is what we call a "subtree split": a read-only subset of that main repository. + We're looking forward to your PR there! diff --git a/src/agent/src/Bridge/Firecrawl/.gitignore b/src/agent/src/Bridge/Firecrawl/.gitignore new file mode 100644 index 000000000..76367ee5b --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/.gitignore @@ -0,0 +1,4 @@ +vendor/ +composer.lock +phpunit.xml +.phpunit.result.cache diff --git a/src/agent/src/Bridge/Firecrawl/CHANGELOG.md b/src/agent/src/Bridge/Firecrawl/CHANGELOG.md new file mode 100644 index 000000000..0915f3546 --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +0.1 +--- + + * Add the bridge diff --git a/src/agent/src/Toolbox/Tool/Firecrawl.php b/src/agent/src/Bridge/Firecrawl/Firecrawl.php similarity index 98% rename from src/agent/src/Toolbox/Tool/Firecrawl.php rename to src/agent/src/Bridge/Firecrawl/Firecrawl.php index 20e2e9f73..b91a41276 100644 --- a/src/agent/src/Toolbox/Tool/Firecrawl.php +++ b/src/agent/src/Bridge/Firecrawl/Firecrawl.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Agent\Bridge\Firecrawl; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\Contracts\HttpClient\HttpClientInterface; diff --git a/src/agent/src/Bridge/Firecrawl/LICENSE b/src/agent/src/Bridge/Firecrawl/LICENSE new file mode 100644 index 000000000..bc38d714e --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2025-present Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/agent/tests/Toolbox/Tool/FirecrawlTest.php b/src/agent/src/Bridge/Firecrawl/Tests/FirecrawlTest.php similarity index 74% rename from src/agent/tests/Toolbox/Tool/FirecrawlTest.php rename to src/agent/src/Bridge/Firecrawl/Tests/FirecrawlTest.php index 9ef4d46ff..20153adfe 100644 --- a/src/agent/tests/Toolbox/Tool/FirecrawlTest.php +++ b/src/agent/src/Bridge/Firecrawl/Tests/FirecrawlTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace Symfony\AI\Agent\Bridge\Firecrawl\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Firecrawl; +use Symfony\AI\Agent\Bridge\Firecrawl\Firecrawl; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; @@ -21,7 +21,7 @@ final class FirecrawlTest extends TestCase public function testScrape() { $httpClient = new MockHttpClient([ - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-scrape.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/scrape.json'), ]); $firecrawl = new Firecrawl($httpClient, 'test', 'https://127.0.0.1:3002'); @@ -37,10 +37,10 @@ public function testScrape() public function testCrawl() { $httpClient = new MockHttpClient([ - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-crawl-wait.json'), - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-crawl-status.json'), - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-crawl-status-done.json'), - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-crawl.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/crawl-wait.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/crawl-status.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/crawl-status-done.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/crawl.json'), ]); $firecrawl = new Firecrawl($httpClient, 'test', 'https://127.0.0.1:3002'); @@ -60,7 +60,7 @@ public function testCrawl() public function testMap() { $httpClient = new MockHttpClient([ - JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/firecrawl-map.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/map.json'), ]); $firecrawl = new Firecrawl($httpClient, 'test', 'https://127.0.0.1:3002'); diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-status-done.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-status-done.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-status-done.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-status-done.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-status.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-status.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-status.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-status.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-wait.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-wait.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-wait.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl-wait.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/crawl.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-map.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/map.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-map.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/map.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-scrape.json b/src/agent/src/Bridge/Firecrawl/Tests/fixtures/scrape.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-scrape.json rename to src/agent/src/Bridge/Firecrawl/Tests/fixtures/scrape.json diff --git a/src/agent/src/Bridge/Firecrawl/composer.json b/src/agent/src/Bridge/Firecrawl/composer.json new file mode 100644 index 000000000..729f86d7d --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/composer.json @@ -0,0 +1,45 @@ +{ + "name": "symfony/ai-firecrawl-tool", + "description": "Firecrawl AI tool bridge for Symfony applications.", + "license": "MIT", + "type": "library", + "keywords": ["ai", "bridge", "firecrawl", "agent", "tool"], + "authors": [ + { + "name": "Guillaume Loulier", + "email": "personal@guillaumeloulier.fr" + }, + { + "name": "Oskar Stark", + "email": "oskarstark@googlemail.com" + } + ], + "require": { + "php": ">=8.2", + "symfony/ai-agent": "@dev", + "symfony/http-client": "^7.3|^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^11.5.13" + }, + "autoload": { + "psr-4": { + "Symfony\\AI\\Agent\\Bridge\\Firecrawl\\": "" + } + }, + "autoload-dev": { + "psr-4": { + "Symfony\\AI\\Agent\\Bridge\\Firecrawl\\Tests\\": "Tests/" + } + }, + "config": { + "sort-packages": true + }, + "extra": { + "thanks": { + "name": "symfony/ai", + "url": "https://github.com/symfony/ai" + } + }, + "minimum-stability": "dev" +} diff --git a/src/agent/src/Bridge/Firecrawl/phpunit.xml.dist b/src/agent/src/Bridge/Firecrawl/phpunit.xml.dist new file mode 100644 index 000000000..a4e94b2f4 --- /dev/null +++ b/src/agent/src/Bridge/Firecrawl/phpunit.xml.dist @@ -0,0 +1,32 @@ + + + + + + + + + + ./Tests/ + + + + + + ./ + + + ./Resources + ./Tests + ./vendor + + +