From 50a149b8ba687347e3754c2d13b5e21820711639 Mon Sep 17 00:00:00 2001 From: Christopher Hertel Date: Sat, 15 Nov 2025 01:23:48 +0100 Subject: [PATCH] Extract third party tools to extra component --- README.md | 1 + demo/composer.json | 1 + demo/config/packages/ai.yaml | 11 ++-- examples/aimlapi/toolcall.php | 2 +- examples/anthropic/toolcall.php | 3 +- examples/bedrock/toolcall-claude.php | 2 +- examples/bedrock/toolcall-nova.php | 2 +- examples/composer.json | 1 + examples/deepseek/structured-output-clock.php | 2 +- examples/deepseek/toolcall-stream.php | 2 +- examples/deepseek/toolcall.php | 2 +- examples/dockermodelrunner/toolcall.php | 2 +- examples/gemini/server-tools.php | 2 +- examples/gemini/structured-output-clock.php | 2 +- examples/gemini/toolcall.php | 2 +- examples/mistral/toolcall-stream.php | 2 +- examples/mistral/toolcall.php | 2 +- examples/ollama/stream-toolcall.php | 2 +- examples/ollama/toolcall.php | 2 +- examples/openai/agent-stream-sources.php | 4 +- examples/openai/structured-output-clock.php | 2 +- examples/openai/toolcall-stream.php | 2 +- examples/openai/toolcall.php | 2 +- examples/scaleway/toolcall-stream.php | 2 +- examples/scaleway/toolcall.php | 2 +- examples/toolbox/brave.php | 6 +- examples/toolbox/firecrawl-crawl.php | 2 +- examples/toolbox/firecrawl-map.php | 2 +- examples/toolbox/firecrawl-scrape.php | 2 +- examples/toolbox/mapbox-geocode.php | 2 +- examples/toolbox/mapbox-reverse-geocode.php | 2 +- examples/toolbox/serpapi.php | 6 +- examples/toolbox/tavily.php | 4 +- examples/toolbox/weather-event.php | 2 +- examples/vertexai/structured-output-clock.php | 2 +- examples/vertexai/toolcall.php | 2 +- src/agent/CHANGELOG.md | 9 --- src/tools/.gitattributes | 8 +++ src/tools/.gitignore | 3 + src/tools/CHANGELOG.md | 17 +++++ src/tools/LICENSE | 19 ++++++ src/tools/README.md | 24 +++++++ src/tools/composer.json | 65 +++++++++++++++++++ src/tools/phpstan.dist.neon | 11 ++++ src/tools/phpunit.xml.dist | 22 +++++++ .../src/Toolbox/Tool => tools/src}/Brave.php | 2 +- .../src/Toolbox/Tool => tools/src}/Clock.php | 2 +- .../Toolbox/Tool => tools/src}/Firecrawl.php | 2 +- .../src/Toolbox/Tool => tools/src}/Mapbox.php | 2 +- .../Toolbox/Tool => tools/src}/OpenMeteo.php | 2 +- .../Toolbox/Tool => tools/src}/Scraper.php | 2 +- .../Toolbox/Tool => tools/src}/SerpApi.php | 2 +- .../src/Toolbox/Tool => tools/src}/Tavily.php | 2 +- .../Toolbox/Tool => tools/src}/Wikipedia.php | 2 +- .../Tool => tools/src}/YouTubeTranscriber.php | 2 +- .../Tool => tools/tests}/BraveTest.php | 8 +-- .../Tool => tools/tests}/ClockTest.php | 4 +- .../Tool => tools/tests}/FirecrawlTest.php | 16 ++--- .../Tool => tools/tests}/MapboxTest.php | 14 ++-- .../Tool => tools/tests}/OpenMeteoTest.php | 8 +-- .../Tool => tools/tests}/WikipediaTest.php | 14 ++-- .../Tool => tools/tests/fixtures}/brave.json | 0 .../firecrawl-crawl-status-done.json | 0 .../fixtures}/firecrawl-crawl-status.json | 0 .../tests/fixtures}/firecrawl-crawl-wait.json | 0 .../tests/fixtures}/firecrawl-crawl.json | 0 .../tests/fixtures}/firecrawl-map.json | 0 .../tests/fixtures}/firecrawl-scrape.json | 0 .../tests/fixtures}/mapbox-geocode-empty.json | 0 .../fixtures}/mapbox-geocode-multiple.json | 0 .../fixtures}/mapbox-geocode-single.json | 0 .../mapbox-reverse-geocode-empty.json | 0 .../fixtures}/mapbox-reverse-geocode.json | 0 .../tests/fixtures}/openmeteo-current.json | 0 .../tests/fixtures}/openmeteo-forecast.json | 0 .../fixtures}/wikipedia-article-missing.json | 0 .../fixtures}/wikipedia-article-redirect.json | 0 .../tests/fixtures}/wikipedia-article.json | 0 .../fixtures}/wikipedia-search-empty.json | 0 .../fixtures}/wikipedia-search-result.json | 0 80 files changed, 258 insertions(+), 95 deletions(-) create mode 100644 src/tools/.gitattributes create mode 100644 src/tools/.gitignore create mode 100644 src/tools/CHANGELOG.md create mode 100644 src/tools/LICENSE create mode 100644 src/tools/README.md create mode 100644 src/tools/composer.json create mode 100644 src/tools/phpstan.dist.neon create mode 100644 src/tools/phpunit.xml.dist rename src/{agent/src/Toolbox/Tool => tools/src}/Brave.php (98%) rename src/{agent/src/Toolbox/Tool => tools/src}/Clock.php (97%) rename src/{agent/src/Toolbox/Tool => tools/src}/Firecrawl.php (98%) rename src/{agent/src/Toolbox/Tool => tools/src}/Mapbox.php (99%) rename src/{agent/src/Toolbox/Tool => tools/src}/OpenMeteo.php (99%) rename src/{agent/src/Toolbox/Tool => tools/src}/Scraper.php (97%) rename src/{agent/src/Toolbox/Tool => tools/src}/SerpApi.php (97%) rename src/{agent/src/Toolbox/Tool => tools/src}/Tavily.php (98%) rename src/{agent/src/Toolbox/Tool => tools/src}/Wikipedia.php (98%) rename src/{agent/src/Toolbox/Tool => tools/src}/YouTubeTranscriber.php (97%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/BraveTest.php (90%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/ClockTest.php (92%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/FirecrawlTest.php (74%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/MapboxTest.php (87%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/OpenMeteoTest.php (85%) rename src/{agent/tests/Toolbox/Tool => tools/tests}/WikipediaTest.php (85%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/brave.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-crawl-status-done.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-crawl-status.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-crawl-wait.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-crawl.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-map.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/firecrawl-scrape.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/mapbox-geocode-empty.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/mapbox-geocode-multiple.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/mapbox-geocode-single.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/mapbox-reverse-geocode-empty.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/mapbox-reverse-geocode.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/openmeteo-current.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/openmeteo-forecast.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/wikipedia-article-missing.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/wikipedia-article-redirect.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/wikipedia-article.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/wikipedia-search-empty.json (100%) rename src/{agent/tests/fixtures/Tool => tools/tests/fixtures}/wikipedia-search-result.json (100%) diff --git a/README.md b/README.md index ebc69ce13..e40916e98 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Symfony AI consists of several lower and higher level **components** and the res * **[Agent](src/agent/README.md)**: Framework for building AI agents that can interact with users and perform tasks. * **[Chat](src/chat/README.md)**: An unified interface to send messages to agents and store long-term context. * **[Store](src/store/README.md)**: Data storage abstraction with indexing and retrieval for AI applications. + * **[Tools](src/tools/README.md)**: Collection of third-party tools to be used with agents. * **Bundles** * **[AI Bundle](src/ai-bundle/README.md)**: Symfony integration for AI Platform, Store and Agent components. * **[MCP Bundle](src/mcp-bundle/README.md)**: Symfony integration for official MCP SDK, allowing them to act as MCP servers or clients. diff --git a/demo/composer.json b/demo/composer.json index 7036cf917..91f27bbd1 100644 --- a/demo/composer.json +++ b/demo/composer.json @@ -15,6 +15,7 @@ "php-http/discovery": "^1.20", "runtime/frankenphp-symfony": "^0.2.0", "symfony/ai-bundle": "@dev", + "symfony/ai-tools": "@dev", "symfony/asset": "~7.3.0", "symfony/asset-mapper": "~7.3.0", "symfony/clock": "~7.3.0", diff --git a/demo/config/packages/ai.yaml b/demo/config/packages/ai.yaml index 0f6e4521a..c9b410a2f 100644 --- a/demo/config/packages/ai.yaml +++ b/demo/config/packages/ai.yaml @@ -98,11 +98,6 @@ services: autowire: true autoconfigure: true - # Symfony\AI\Agent\Toolbox\Tool\Clock: ~ - # Symfony\AI\Agent\Toolbox\Tool\OpenMeteo: ~ - # Symfony\AI\Agent\Toolbox\Tool\SerpApi: - # $apiKey: '%env(SERP_API_KEY)%' - Symfony\AI\Agent\Toolbox\Tool\Wikipedia: ~ Symfony\AI\Agent\Toolbox\Tool\SimilaritySearch: $vectorizer: '@ai.vectorizer.openai' $store: '@ai.store.chroma_db.symfonycon' @@ -111,6 +106,12 @@ services: Symfony\AI\Store\Document\Transformer\TextSplitTransformer: ~ Symfony\AI\Store\Document\Transformer\TextTrimTransformer: ~ + # Symfony\AI\Tools\Clock: ~ + # Symfony\AI\Tools\OpenMeteo: ~ + # Symfony\AI\Tools\SerpApi: + # $apiKey: '%env(SERP_API_KEY)%' + Symfony\AI\Tools\Wikipedia: ~ + app.filter.week_of_symfony: class: 'Symfony\AI\Store\Document\Filter\TextContainsFilter' arguments: diff --git a/examples/aimlapi/toolcall.php b/examples/aimlapi/toolcall.php index 26709108f..d4ce6cea0 100644 --- a/examples/aimlapi/toolcall.php +++ b/examples/aimlapi/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\AiMlApi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/anthropic/toolcall.php b/examples/anthropic/toolcall.php index 8d5581ddd..c12315a78 100644 --- a/examples/anthropic/toolcall.php +++ b/examples/anthropic/toolcall.php @@ -11,12 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Source\Source; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Anthropic\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/bedrock/toolcall-claude.php b/examples/bedrock/toolcall-claude.php index 6370c2858..cc1e74060 100644 --- a/examples/bedrock/toolcall-claude.php +++ b/examples/bedrock/toolcall-claude.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/bedrock/toolcall-nova.php b/examples/bedrock/toolcall-nova.php index 67f375cfa..edbce36c5 100644 --- a/examples/bedrock/toolcall-nova.php +++ b/examples/bedrock/toolcall-nova.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Bedrock\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/composer.json b/examples/composer.json index a99c4cd3f..ff30ba8aa 100644 --- a/examples/composer.json +++ b/examples/composer.json @@ -21,6 +21,7 @@ "symfony/ai-chat": "@dev", "symfony/ai-platform": "@dev", "symfony/ai-store": "@dev", + "symfony/ai-tools": "@dev", "symfony/cache": "^7.3|^8.0", "symfony/clock": "^7.3|^8.0", "symfony/console": "^7.3|^8.0", diff --git a/examples/deepseek/structured-output-clock.php b/examples/deepseek/structured-output-clock.php index b80626a91..8aae118aa 100644 --- a/examples/deepseek/structured-output-clock.php +++ b/examples/deepseek/structured-output-clock.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\AI\Tools\Clock; use Symfony\Component\Clock\Clock as SymfonyClock; use Symfony\Component\EventDispatcher\EventDispatcher; diff --git a/examples/deepseek/toolcall-stream.php b/examples/deepseek/toolcall-stream.php index f404a6e22..78a84fdd6 100644 --- a/examples/deepseek/toolcall-stream.php +++ b/examples/deepseek/toolcall-stream.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/deepseek/toolcall.php b/examples/deepseek/toolcall.php index 767edf7ae..4643bd8a6 100644 --- a/examples/deepseek/toolcall.php +++ b/examples/deepseek/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\DeepSeek\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/dockermodelrunner/toolcall.php b/examples/dockermodelrunner/toolcall.php index 73b55b379..88b876cbe 100644 --- a/examples/dockermodelrunner/toolcall.php +++ b/examples/dockermodelrunner/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\DockerModelRunner\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/gemini/server-tools.php b/examples/gemini/server-tools.php index a51b194e9..e790c0674 100644 --- a/examples/gemini/server-tools.php +++ b/examples/gemini/server-tools.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/gemini/structured-output-clock.php b/examples/gemini/structured-output-clock.php index 443feca00..888b2fe29 100644 --- a/examples/gemini/structured-output-clock.php +++ b/examples/gemini/structured-output-clock.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\AI\Tools\Clock; use Symfony\Component\Clock\Clock as SymfonyClock; use Symfony\Component\EventDispatcher\EventDispatcher; diff --git a/examples/gemini/toolcall.php b/examples/gemini/toolcall.php index 368c632d8..195896a41 100644 --- a/examples/gemini/toolcall.php +++ b/examples/gemini/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Gemini\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/mistral/toolcall-stream.php b/examples/mistral/toolcall-stream.php index 2ae6c4660..a66b3fa1e 100644 --- a/examples/mistral/toolcall-stream.php +++ b/examples/mistral/toolcall-stream.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\YouTubeTranscriber; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/mistral/toolcall.php b/examples/mistral/toolcall.php index 13b1a2a38..ce256556c 100644 --- a/examples/mistral/toolcall.php +++ b/examples/mistral/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Mistral\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/ollama/stream-toolcall.php b/examples/ollama/stream-toolcall.php index da709829c..d4f4da56c 100644 --- a/examples/ollama/stream-toolcall.php +++ b/examples/ollama/stream-toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/ollama/toolcall.php b/examples/ollama/toolcall.php index 4b24c6d6a..233b40b71 100644 --- a/examples/ollama/toolcall.php +++ b/examples/ollama/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Ollama\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/openai/agent-stream-sources.php b/examples/openai/agent-stream-sources.php index 187243a7c..c80e975d6 100644 --- a/examples/openai/agent-stream-sources.php +++ b/examples/openai/agent-stream-sources.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; -use Symfony\AI\Agent\Toolbox\Tool\Tavily; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; +use Symfony\AI\Tools\Tavily; use Symfony\Component\Clock\Clock as SymfonyClock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/openai/structured-output-clock.php b/examples/openai/structured-output-clock.php index 2da321377..4ff2e23f2 100644 --- a/examples/openai/structured-output-clock.php +++ b/examples/openai/structured-output-clock.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\AI\Tools\Clock; use Symfony\Component\Clock\Clock as SymfonyClock; use Symfony\Component\EventDispatcher\EventDispatcher; diff --git a/examples/openai/toolcall-stream.php b/examples/openai/toolcall-stream.php index 03ca4657d..9f4b76150 100644 --- a/examples/openai/toolcall-stream.php +++ b/examples/openai/toolcall-stream.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Wikipedia; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/openai/toolcall.php b/examples/openai/toolcall.php index 1ea7d3359..1e80f7892 100644 --- a/examples/openai/toolcall.php +++ b/examples/openai/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\YouTubeTranscriber; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/scaleway/toolcall-stream.php b/examples/scaleway/toolcall-stream.php index 5a02b902c..6130f8eb7 100644 --- a/examples/scaleway/toolcall-stream.php +++ b/examples/scaleway/toolcall-stream.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Scaleway\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\YouTubeTranscriber; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/scaleway/toolcall.php b/examples/scaleway/toolcall.php index e11c4837b..df68068d7 100644 --- a/examples/scaleway/toolcall.php +++ b/examples/scaleway/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\YouTubeTranscriber; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\Scaleway\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\YouTubeTranscriber; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/brave.php b/examples/toolbox/brave.php index 633de0ada..4e96dd554 100644 --- a/examples/toolbox/brave.php +++ b/examples/toolbox/brave.php @@ -11,13 +11,13 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Brave; -use Symfony\AI\Agent\Toolbox\Tool\Clock; -use Symfony\AI\Agent\Toolbox\Tool\Scraper; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Brave; +use Symfony\AI\Tools\Clock; +use Symfony\AI\Tools\Scraper; use Symfony\Component\Clock\Clock as SymfonyClock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/firecrawl-crawl.php b/examples/toolbox/firecrawl-crawl.php index 114c781e6..3cde4f659 100644 --- a/examples/toolbox/firecrawl-crawl.php +++ b/examples/toolbox/firecrawl-crawl.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; 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; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Firecrawl; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/firecrawl-map.php b/examples/toolbox/firecrawl-map.php index 21084c8b7..8d405ba97 100644 --- a/examples/toolbox/firecrawl-map.php +++ b/examples/toolbox/firecrawl-map.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; 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; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Firecrawl; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/firecrawl-scrape.php b/examples/toolbox/firecrawl-scrape.php index be9565fef..7ef8787dd 100644 --- a/examples/toolbox/firecrawl-scrape.php +++ b/examples/toolbox/firecrawl-scrape.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; 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; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Firecrawl; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/mapbox-geocode.php b/examples/toolbox/mapbox-geocode.php index 2b43033a0..1f0905fa8 100644 --- a/examples/toolbox/mapbox-geocode.php +++ b/examples/toolbox/mapbox-geocode.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Mapbox; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Mapbox; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/mapbox-reverse-geocode.php b/examples/toolbox/mapbox-reverse-geocode.php index b205b4c45..17a844d6a 100644 --- a/examples/toolbox/mapbox-reverse-geocode.php +++ b/examples/toolbox/mapbox-reverse-geocode.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Mapbox; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Mapbox; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/serpapi.php b/examples/toolbox/serpapi.php index e64881f37..3de719c95 100644 --- a/examples/toolbox/serpapi.php +++ b/examples/toolbox/serpapi.php @@ -11,13 +11,13 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; -use Symfony\AI\Agent\Toolbox\Tool\Scraper; -use Symfony\AI\Agent\Toolbox\Tool\SerpApi; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; +use Symfony\AI\Tools\Scraper; +use Symfony\AI\Tools\SerpApi; use Symfony\Component\Clock\Clock as SymfonyClock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/tavily.php b/examples/toolbox/tavily.php index f31d4729b..5d2d31672 100644 --- a/examples/toolbox/tavily.php +++ b/examples/toolbox/tavily.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; -use Symfony\AI\Agent\Toolbox\Tool\Tavily; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; +use Symfony\AI\Tools\Tavily; use Symfony\Component\Clock\Clock as SymfonyClock; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/toolbox/weather-event.php b/examples/toolbox/weather-event.php index 03d4156f1..a11190a1f 100644 --- a/examples/toolbox/weather-event.php +++ b/examples/toolbox/weather-event.php @@ -12,12 +12,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; use Symfony\AI\Agent\Toolbox\Event\ToolCallsExecuted; -use Symfony\AI\Agent\Toolbox\Tool\OpenMeteo; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; use Symfony\AI\Platform\Result\ObjectResult; +use Symfony\AI\Tools\OpenMeteo; use Symfony\Component\EventDispatcher\EventDispatcher; require_once dirname(__DIR__).'/bootstrap.php'; diff --git a/examples/vertexai/structured-output-clock.php b/examples/vertexai/structured-output-clock.php index b832b4e57..e1b638a91 100644 --- a/examples/vertexai/structured-output-clock.php +++ b/examples/vertexai/structured-output-clock.php @@ -11,12 +11,12 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; use Symfony\AI\Platform\StructuredOutput\PlatformSubscriber; +use Symfony\AI\Tools\Clock; use Symfony\Component\Clock\Clock as SymfonyClock; use Symfony\Component\EventDispatcher\EventDispatcher; diff --git a/examples/vertexai/toolcall.php b/examples/vertexai/toolcall.php index 09cb98167..d87a68e19 100644 --- a/examples/vertexai/toolcall.php +++ b/examples/vertexai/toolcall.php @@ -11,11 +11,11 @@ use Symfony\AI\Agent\Agent; use Symfony\AI\Agent\Toolbox\AgentProcessor; -use Symfony\AI\Agent\Toolbox\Tool\Clock; use Symfony\AI\Agent\Toolbox\Toolbox; use Symfony\AI\Platform\Bridge\VertexAi\PlatformFactory; use Symfony\AI\Platform\Message\Message; use Symfony\AI\Platform\Message\MessageBag; +use Symfony\AI\Tools\Clock; require_once __DIR__.'/bootstrap.php'; diff --git a/src/agent/CHANGELOG.md b/src/agent/CHANGELOG.md index 7fabac78c..ab945a924 100644 --- a/src/agent/CHANGELOG.md +++ b/src/agent/CHANGELOG.md @@ -24,15 +24,6 @@ CHANGELOG * Add built-in tools: - `SimilaritySearch` for RAG/vector store searches - `Agent` allowing agents to use other agents as tools - - `Clock` for current date/time - - `Brave` for web search integration - - `Crawler` for web page crawling - - `Mapbox` for geocoding addresses to coordinates and reverse geocoding - - `OpenMeteo` for weather information - - `SerpApi` for search engine results - - `Tavily` for AI-powered search - - `Wikipedia` for Wikipedia content retrieval - - `YouTubeTranscriber` for YouTube video transcription * Add structured output support: - PHP class output with automatic conversion from LLM responses - Array structure output with JSON schema validation diff --git a/src/tools/.gitattributes b/src/tools/.gitattributes new file mode 100644 index 000000000..9cf0aaea6 --- /dev/null +++ b/src/tools/.gitattributes @@ -0,0 +1,8 @@ +/.github export-ignore +/tests export-ignore +.gitattributes export-ignore +.gitignore export-ignore +phpstan.dist.neon export-ignore +phpunit.xml.dist export-ignore +CLAUDE.md export-ignore +AGENTS.md export-ignore diff --git a/src/tools/.gitignore b/src/tools/.gitignore new file mode 100644 index 000000000..f43db636b --- /dev/null +++ b/src/tools/.gitignore @@ -0,0 +1,3 @@ +composer.lock +vendor +.phpunit.cache diff --git a/src/tools/CHANGELOG.md b/src/tools/CHANGELOG.md new file mode 100644 index 000000000..976a392d9 --- /dev/null +++ b/src/tools/CHANGELOG.md @@ -0,0 +1,17 @@ +CHANGELOG +========= + +0.1 +--- + + * Add tools: + - `Brave` for web search integration + - `Clock` for current date/time + - `Crawler` for web page crawling + - `Firecrawl` for crawling and extracting web content via Firecrawl + - `Mapbox` for geocoding addresses to coordinates and reverse geocoding + - `OpenMeteo` for weather information + - `SerpApi` for search engine results + - `Tavily` for AI-powered search + - `Wikipedia` for Wikipedia content retrieval + - `YouTubeTranscriber` for YouTube video transcription diff --git a/src/tools/LICENSE b/src/tools/LICENSE new file mode 100644 index 000000000..bc38d714e --- /dev/null +++ b/src/tools/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/tools/README.md b/src/tools/README.md new file mode 100644 index 000000000..5c6e832ae --- /dev/null +++ b/src/tools/README.md @@ -0,0 +1,24 @@ +# Symfony AI - Tools Component + +The Tools component provides a collection of third party integrations as tools ready-to-use for agents. + +**This Component is experimental**. +[Experimental features](https://symfony.com/doc/current/contributing/code/experimental.html) +are not covered by Symfony's +[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html). + +## Installation + +```bash +composer require symfony/ai-tools +``` + +**This repository is a READ-ONLY sub-tree split**. See +https://github.com/symfony/ai to create issues or submit pull requests. + +## Resources + +- [Documentation](../../docs/index.rst) +- [Report issues](https://github.com/symfony/ai/issues) and + [send Pull Requests](https://github.com/symfony/ai/pulls) + in the [main Symfony AI repository](https://github.com/symfony/ai) diff --git a/src/tools/composer.json b/src/tools/composer.json new file mode 100644 index 000000000..339ae79d4 --- /dev/null +++ b/src/tools/composer.json @@ -0,0 +1,65 @@ +{ + "name": "symfony/ai-tools", + "description": "Collection of AI tools for Symfony AI Agents", + "license": "MIT", + "type": "library", + "keywords": [ + "ai", + "llm", + "tools" + ], + "authors": [ + { + "name": "Christopher Hertel", + "email": "mail@christopher-hertel.de" + }, + { + "name": "Oskar Stark", + "email": "oskarstark@googlemail.com" + } + ], + "require": { + "php": ">=8.2", + "ext-fileinfo": "*", + "symfony/ai-agent": "@dev", + "symfony/ai-platform": "@dev", + "symfony/clock": "^7.3|^8.0", + "symfony/http-client": "^7.3|^8.0" + }, + "require-dev": { + "mrmysql/youtube-transcript": "^0.0.5", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0", + "phpunit/phpunit": "^11.5.13", + "symfony/ai-store": "@dev", + "symfony/cache": "^7.3|^8.0", + "symfony/css-selector": "^7.3|^8.0", + "symfony/dom-crawler": "^7.3|^8.0", + "symfony/event-dispatcher": "^7.3|^8.0", + "symfony/http-foundation": "^7.3|^8.0", + "symfony/translation": "^7.3|^8.0", + "symfony/translation-contracts": "^3.6" + }, + "autoload": { + "psr-4": { + "Symfony\\AI\\Tools\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Symfony\\AI\\Tools\\Tests\\": "tests/", + "Symfony\\AI\\Fixtures\\": "../../fixtures", + "Symfony\\AI\\PHPStan\\": "../../.phpstan/" + } + }, + "config": { + "sort-packages": true + }, + "extra": { + "thanks": { + "name": "symfony/ai", + "url": "https://github.com/symfony/ai" + } + }, + "minimum-stability": "dev" +} diff --git a/src/tools/phpstan.dist.neon b/src/tools/phpstan.dist.neon new file mode 100644 index 000000000..0ea90278a --- /dev/null +++ b/src/tools/phpstan.dist.neon @@ -0,0 +1,11 @@ +includes: + - ../../.phpstan/extension.neon + +parameters: + level: 6 + paths: + - src/ + - tests/ + ignoreErrors: + - + message: "#^Method .*::test.*\\(\\) has no return type specified\\.$#" diff --git a/src/tools/phpunit.xml.dist b/src/tools/phpunit.xml.dist new file mode 100644 index 000000000..0ed27cf54 --- /dev/null +++ b/src/tools/phpunit.xml.dist @@ -0,0 +1,22 @@ + + + + + tests + + + + + + src + + + diff --git a/src/agent/src/Toolbox/Tool/Brave.php b/src/tools/src/Brave.php similarity index 98% rename from src/agent/src/Toolbox/Tool/Brave.php rename to src/tools/src/Brave.php index 5b9e75961..3780c7816 100644 --- a/src/agent/src/Toolbox/Tool/Brave.php +++ b/src/tools/src/Brave.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\Source\HasSourcesInterface; diff --git a/src/agent/src/Toolbox/Tool/Clock.php b/src/tools/src/Clock.php similarity index 97% rename from src/agent/src/Toolbox/Tool/Clock.php rename to src/tools/src/Clock.php index e59f3c3e6..c5ac902e5 100644 --- a/src/agent/src/Toolbox/Tool/Clock.php +++ b/src/tools/src/Clock.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\Source\HasSourcesInterface; diff --git a/src/agent/src/Toolbox/Tool/Firecrawl.php b/src/tools/src/Firecrawl.php similarity index 98% rename from src/agent/src/Toolbox/Tool/Firecrawl.php rename to src/tools/src/Firecrawl.php index 20e2e9f73..24af9a43a 100644 --- a/src/agent/src/Toolbox/Tool/Firecrawl.php +++ b/src/tools/src/Firecrawl.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\Contracts\HttpClient\HttpClientInterface; diff --git a/src/agent/src/Toolbox/Tool/Mapbox.php b/src/tools/src/Mapbox.php similarity index 99% rename from src/agent/src/Toolbox/Tool/Mapbox.php rename to src/tools/src/Mapbox.php index 3da0eeb37..6331b6e44 100644 --- a/src/agent/src/Toolbox/Tool/Mapbox.php +++ b/src/tools/src/Mapbox.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Platform\Contract\JsonSchema\Attribute\With; diff --git a/src/agent/src/Toolbox/Tool/OpenMeteo.php b/src/tools/src/OpenMeteo.php similarity index 99% rename from src/agent/src/Toolbox/Tool/OpenMeteo.php rename to src/tools/src/OpenMeteo.php index d96768ace..e5c1f9f2f 100644 --- a/src/agent/src/Toolbox/Tool/OpenMeteo.php +++ b/src/tools/src/OpenMeteo.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Platform\Contract\JsonSchema\Attribute\With; diff --git a/src/agent/src/Toolbox/Tool/Scraper.php b/src/tools/src/Scraper.php similarity index 97% rename from src/agent/src/Toolbox/Tool/Scraper.php rename to src/tools/src/Scraper.php index f3504af14..93a710a03 100644 --- a/src/agent/src/Toolbox/Tool/Scraper.php +++ b/src/tools/src/Scraper.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Exception\RuntimeException; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; diff --git a/src/agent/src/Toolbox/Tool/SerpApi.php b/src/tools/src/SerpApi.php similarity index 97% rename from src/agent/src/Toolbox/Tool/SerpApi.php rename to src/tools/src/SerpApi.php index 08f9ea13b..c8e373090 100644 --- a/src/agent/src/Toolbox/Tool/SerpApi.php +++ b/src/tools/src/SerpApi.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\Source\HasSourcesInterface; diff --git a/src/agent/src/Toolbox/Tool/Tavily.php b/src/tools/src/Tavily.php similarity index 98% rename from src/agent/src/Toolbox/Tool/Tavily.php rename to src/tools/src/Tavily.php index cdf150b77..837fcda7f 100644 --- a/src/agent/src/Toolbox/Tool/Tavily.php +++ b/src/tools/src/Tavily.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\Source\HasSourcesInterface; diff --git a/src/agent/src/Toolbox/Tool/Wikipedia.php b/src/tools/src/Wikipedia.php similarity index 98% rename from src/agent/src/Toolbox/Tool/Wikipedia.php rename to src/tools/src/Wikipedia.php index 748c2c235..066a5f847 100644 --- a/src/agent/src/Toolbox/Tool/Wikipedia.php +++ b/src/tools/src/Wikipedia.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use Symfony\AI\Agent\Toolbox\Attribute\AsTool; use Symfony\AI\Agent\Toolbox\Source\HasSourcesInterface; diff --git a/src/agent/src/Toolbox/Tool/YouTubeTranscriber.php b/src/tools/src/YouTubeTranscriber.php similarity index 97% rename from src/agent/src/Toolbox/Tool/YouTubeTranscriber.php rename to src/tools/src/YouTubeTranscriber.php index 1257f017f..68eebae03 100644 --- a/src/agent/src/Toolbox/Tool/YouTubeTranscriber.php +++ b/src/tools/src/YouTubeTranscriber.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Toolbox\Tool; +namespace Symfony\AI\Tools; use MrMySQL\YoutubeTranscript\TranscriptListFetcher; use Symfony\AI\Agent\Exception\LogicException; diff --git a/src/agent/tests/Toolbox/Tool/BraveTest.php b/src/tools/tests/BraveTest.php similarity index 90% rename from src/agent/tests/Toolbox/Tool/BraveTest.php rename to src/tools/tests/BraveTest.php index 90326509b..961657df0 100644 --- a/src/agent/tests/Toolbox/Tool/BraveTest.php +++ b/src/tools/tests/BraveTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace Symfony\AI\Tools\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Brave; +use Symfony\AI\Tools\Brave; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; use Symfony\Component\HttpClient\Response\MockResponse; @@ -21,7 +21,7 @@ final class BraveTest extends TestCase { public function testReturnsSearchResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/brave.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/brave.json'); $httpClient = new MockHttpClient($result); $brave = new Brave($httpClient, 'test-api-key'); @@ -38,7 +38,7 @@ public function testReturnsSearchResults() public function testPassesCorrectParametersToApi() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/brave.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/brave.json'); $httpClient = new MockHttpClient($result); $brave = new Brave($httpClient, 'test-api-key', ['extra' => 'option']); diff --git a/src/agent/tests/Toolbox/Tool/ClockTest.php b/src/tools/tests/ClockTest.php similarity index 92% rename from src/agent/tests/Toolbox/Tool/ClockTest.php rename to src/tools/tests/ClockTest.php index a4c9323b4..9931b6008 100644 --- a/src/agent/tests/Toolbox/Tool/ClockTest.php +++ b/src/tools/tests/ClockTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace Symfony\AI\Tools\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Clock; +use Symfony\AI\Tools\Clock; use Symfony\Component\Clock\MockClock; class ClockTest extends TestCase diff --git a/src/agent/tests/Toolbox/Tool/FirecrawlTest.php b/src/tools/tests/FirecrawlTest.php similarity index 74% rename from src/agent/tests/Toolbox/Tool/FirecrawlTest.php rename to src/tools/tests/FirecrawlTest.php index 9ef4d46ff..95d0be978 100644 --- a/src/agent/tests/Toolbox/Tool/FirecrawlTest.php +++ b/src/tools/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\Tools\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Firecrawl; +use Symfony\AI\Tools\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/firecrawl-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/firecrawl-crawl-wait.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/firecrawl-crawl-status.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/firecrawl-crawl-status-done.json'), + JsonMockResponse::fromFile(__DIR__.'/fixtures/firecrawl-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/firecrawl-map.json'), ]); $firecrawl = new Firecrawl($httpClient, 'test', 'https://127.0.0.1:3002'); diff --git a/src/agent/tests/Toolbox/Tool/MapboxTest.php b/src/tools/tests/MapboxTest.php similarity index 87% rename from src/agent/tests/Toolbox/Tool/MapboxTest.php rename to src/tools/tests/MapboxTest.php index 39063baad..875046465 100644 --- a/src/agent/tests/Toolbox/Tool/MapboxTest.php +++ b/src/tools/tests/MapboxTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace Symfony\AI\Tools\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Mapbox; +use Symfony\AI\Tools\Mapbox; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; @@ -20,7 +20,7 @@ final class MapboxTest extends TestCase { public function testGeocodeWithSingleResult() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/mapbox-geocode-single.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/mapbox-geocode-single.json'); $httpClient = new MockHttpClient($result); $mapbox = new Mapbox($httpClient, 'test_token'); @@ -46,7 +46,7 @@ public function testGeocodeWithSingleResult() public function testGeocodeWithMultipleResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/mapbox-geocode-multiple.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/mapbox-geocode-multiple.json'); $httpClient = new MockHttpClient($result); $mapbox = new Mapbox($httpClient, 'test_token'); @@ -81,7 +81,7 @@ public function testGeocodeWithMultipleResults() public function testGeocodeWithNoResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/mapbox-geocode-empty.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/mapbox-geocode-empty.json'); $httpClient = new MockHttpClient($result); $mapbox = new Mapbox($httpClient, 'test_token'); @@ -97,7 +97,7 @@ public function testGeocodeWithNoResults() public function testReverseGeocodeWithValidCoordinates() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/mapbox-reverse-geocode.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/mapbox-reverse-geocode.json'); $httpClient = new MockHttpClient($result); $mapbox = new Mapbox($httpClient, 'test_token'); @@ -139,7 +139,7 @@ public function testReverseGeocodeWithValidCoordinates() public function testReverseGeocodeWithNoResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/mapbox-reverse-geocode-empty.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/mapbox-reverse-geocode-empty.json'); $httpClient = new MockHttpClient($result); $mapbox = new Mapbox($httpClient, 'test_token'); diff --git a/src/agent/tests/Toolbox/Tool/OpenMeteoTest.php b/src/tools/tests/OpenMeteoTest.php similarity index 85% rename from src/agent/tests/Toolbox/Tool/OpenMeteoTest.php rename to src/tools/tests/OpenMeteoTest.php index 5a6c52f35..7d1b77efc 100644 --- a/src/agent/tests/Toolbox/Tool/OpenMeteoTest.php +++ b/src/tools/tests/OpenMeteoTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\OpenMeteo; +use Symfony\AI\Tools\OpenMeteo; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; @@ -20,7 +20,7 @@ final class OpenMeteoTest extends TestCase { public function testCurrent() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/openmeteo-current.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/openmeteo-current.json'); $httpClient = new MockHttpClient($result); $openMeteo = new OpenMeteo($httpClient); @@ -38,7 +38,7 @@ public function testCurrent() public function testForecast() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/openmeteo-forecast.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/openmeteo-forecast.json'); $httpClient = new MockHttpClient($result); $openMeteo = new OpenMeteo($httpClient); diff --git a/src/agent/tests/Toolbox/Tool/WikipediaTest.php b/src/tools/tests/WikipediaTest.php similarity index 85% rename from src/agent/tests/Toolbox/Tool/WikipediaTest.php rename to src/tools/tests/WikipediaTest.php index 5c7057635..f8bdfaf74 100644 --- a/src/agent/tests/Toolbox/Tool/WikipediaTest.php +++ b/src/tools/tests/WikipediaTest.php @@ -9,10 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\AI\Agent\Tests\Toolbox\Tool; +namespace Symfony\AI\Tools\Tests; use PHPUnit\Framework\TestCase; -use Symfony\AI\Agent\Toolbox\Tool\Wikipedia; +use Symfony\AI\Tools\Wikipedia; use Symfony\Component\HttpClient\MockHttpClient; use Symfony\Component\HttpClient\Response\JsonMockResponse; @@ -20,7 +20,7 @@ final class WikipediaTest extends TestCase { public function testSearchWithResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/wikipedia-search-result.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/wikipedia-search-result.json'); $httpClient = new MockHttpClient($result); $wikipedia = new Wikipedia($httpClient); @@ -47,7 +47,7 @@ public function testSearchWithResults() public function testSearchWithoutResults() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/wikipedia-search-empty.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/wikipedia-search-empty.json'); $httpClient = new MockHttpClient($result); $wikipedia = new Wikipedia($httpClient); @@ -60,7 +60,7 @@ public function testSearchWithoutResults() public function testArticleWithResult() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/wikipedia-article.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/wikipedia-article.json'); $httpClient = new MockHttpClient($result); $wikipedia = new Wikipedia($httpClient); @@ -76,7 +76,7 @@ public function testArticleWithResult() public function testArticleWithRedirect() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/wikipedia-article-redirect.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/wikipedia-article-redirect.json'); $httpClient = new MockHttpClient($result); $wikipedia = new Wikipedia($httpClient); @@ -94,7 +94,7 @@ public function testArticleWithRedirect() public function testArticleMissing() { - $result = JsonMockResponse::fromFile(__DIR__.'/../../fixtures/Tool/wikipedia-article-missing.json'); + $result = JsonMockResponse::fromFile(__DIR__.'/fixtures/wikipedia-article-missing.json'); $httpClient = new MockHttpClient($result); $wikipedia = new Wikipedia($httpClient); diff --git a/src/agent/tests/fixtures/Tool/brave.json b/src/tools/tests/fixtures/brave.json similarity index 100% rename from src/agent/tests/fixtures/Tool/brave.json rename to src/tools/tests/fixtures/brave.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-status-done.json b/src/tools/tests/fixtures/firecrawl-crawl-status-done.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-status-done.json rename to src/tools/tests/fixtures/firecrawl-crawl-status-done.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-status.json b/src/tools/tests/fixtures/firecrawl-crawl-status.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-status.json rename to src/tools/tests/fixtures/firecrawl-crawl-status.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl-wait.json b/src/tools/tests/fixtures/firecrawl-crawl-wait.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl-wait.json rename to src/tools/tests/fixtures/firecrawl-crawl-wait.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-crawl.json b/src/tools/tests/fixtures/firecrawl-crawl.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-crawl.json rename to src/tools/tests/fixtures/firecrawl-crawl.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-map.json b/src/tools/tests/fixtures/firecrawl-map.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-map.json rename to src/tools/tests/fixtures/firecrawl-map.json diff --git a/src/agent/tests/fixtures/Tool/firecrawl-scrape.json b/src/tools/tests/fixtures/firecrawl-scrape.json similarity index 100% rename from src/agent/tests/fixtures/Tool/firecrawl-scrape.json rename to src/tools/tests/fixtures/firecrawl-scrape.json diff --git a/src/agent/tests/fixtures/Tool/mapbox-geocode-empty.json b/src/tools/tests/fixtures/mapbox-geocode-empty.json similarity index 100% rename from src/agent/tests/fixtures/Tool/mapbox-geocode-empty.json rename to src/tools/tests/fixtures/mapbox-geocode-empty.json diff --git a/src/agent/tests/fixtures/Tool/mapbox-geocode-multiple.json b/src/tools/tests/fixtures/mapbox-geocode-multiple.json similarity index 100% rename from src/agent/tests/fixtures/Tool/mapbox-geocode-multiple.json rename to src/tools/tests/fixtures/mapbox-geocode-multiple.json diff --git a/src/agent/tests/fixtures/Tool/mapbox-geocode-single.json b/src/tools/tests/fixtures/mapbox-geocode-single.json similarity index 100% rename from src/agent/tests/fixtures/Tool/mapbox-geocode-single.json rename to src/tools/tests/fixtures/mapbox-geocode-single.json diff --git a/src/agent/tests/fixtures/Tool/mapbox-reverse-geocode-empty.json b/src/tools/tests/fixtures/mapbox-reverse-geocode-empty.json similarity index 100% rename from src/agent/tests/fixtures/Tool/mapbox-reverse-geocode-empty.json rename to src/tools/tests/fixtures/mapbox-reverse-geocode-empty.json diff --git a/src/agent/tests/fixtures/Tool/mapbox-reverse-geocode.json b/src/tools/tests/fixtures/mapbox-reverse-geocode.json similarity index 100% rename from src/agent/tests/fixtures/Tool/mapbox-reverse-geocode.json rename to src/tools/tests/fixtures/mapbox-reverse-geocode.json diff --git a/src/agent/tests/fixtures/Tool/openmeteo-current.json b/src/tools/tests/fixtures/openmeteo-current.json similarity index 100% rename from src/agent/tests/fixtures/Tool/openmeteo-current.json rename to src/tools/tests/fixtures/openmeteo-current.json diff --git a/src/agent/tests/fixtures/Tool/openmeteo-forecast.json b/src/tools/tests/fixtures/openmeteo-forecast.json similarity index 100% rename from src/agent/tests/fixtures/Tool/openmeteo-forecast.json rename to src/tools/tests/fixtures/openmeteo-forecast.json diff --git a/src/agent/tests/fixtures/Tool/wikipedia-article-missing.json b/src/tools/tests/fixtures/wikipedia-article-missing.json similarity index 100% rename from src/agent/tests/fixtures/Tool/wikipedia-article-missing.json rename to src/tools/tests/fixtures/wikipedia-article-missing.json diff --git a/src/agent/tests/fixtures/Tool/wikipedia-article-redirect.json b/src/tools/tests/fixtures/wikipedia-article-redirect.json similarity index 100% rename from src/agent/tests/fixtures/Tool/wikipedia-article-redirect.json rename to src/tools/tests/fixtures/wikipedia-article-redirect.json diff --git a/src/agent/tests/fixtures/Tool/wikipedia-article.json b/src/tools/tests/fixtures/wikipedia-article.json similarity index 100% rename from src/agent/tests/fixtures/Tool/wikipedia-article.json rename to src/tools/tests/fixtures/wikipedia-article.json diff --git a/src/agent/tests/fixtures/Tool/wikipedia-search-empty.json b/src/tools/tests/fixtures/wikipedia-search-empty.json similarity index 100% rename from src/agent/tests/fixtures/Tool/wikipedia-search-empty.json rename to src/tools/tests/fixtures/wikipedia-search-empty.json diff --git a/src/agent/tests/fixtures/Tool/wikipedia-search-result.json b/src/tools/tests/fixtures/wikipedia-search-result.json similarity index 100% rename from src/agent/tests/fixtures/Tool/wikipedia-search-result.json rename to src/tools/tests/fixtures/wikipedia-search-result.json