-
-
Notifications
You must be signed in to change notification settings - Fork 144
Add AI Package with OpenAI and Anthropic integrations #1948
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 3.x
Are you sure you want to change the base?
Conversation
- Add AIChat interface and GenericAIChat implementation - Add OpenAI driver with chat completion support - Add Anthropic driver with Claude API support - Add configuration classes for both providers - Add AIMessage, AIResponse, and MessageRole value objects - Add AIDriver interface with provider abstraction - Add AIInitializer for container integration - Add helper functions (ai() and ai_chat()) - Add comprehensive test suite (58 tests, 138 assertions)
- Add #[WithAI] attribute for parameter/property configuration - Add #[SystemPrompt] attribute for class/method system prompts - Add #[AIHandler] attribute to mark AI-powered methods - Add #[JsonOutput] attribute for structured JSON responses - Add #[CacheAIResponse] attribute for response caching - Add tests for all attributes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Introduces a new packages/ai package for Tempest that provides an AIChat abstraction with OpenAI + Anthropic drivers, configuration objects, helper functions, and PHP attributes, and wires it into the monorepo via Composer autoloading.
Changes:
- Added
Tempest\AIcore types (AIChat,GenericAIChat,AIMessage,AIResponse, enums) and container initializers. - Implemented provider drivers for OpenAI and Anthropic, plus provider-specific config objects.
- Added PHPUnit coverage for the new package and updated root
composer.jsonautoload/autoload-dev to include the package.
Reviewed changes
Copilot reviewed 41 out of 41 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/ai/tests/OpenAIDriverTest.php | Adds OpenAI driver tests (chat happy path, error handling, parameter passing). |
| packages/ai/tests/OpenAIConfigTest.php | Adds tests for OpenAI config defaults/overrides. |
| packages/ai/tests/MessageRoleTest.php | Adds tests for MessageRole enum values. |
| packages/ai/tests/GenericAIChatTest.php | Adds tests for GenericAIChat prompt/chat and fluent/immutable config methods. |
| packages/ai/tests/Attribute/WithAIAttributeTest.php | Adds tests for WithAI attribute construction. |
| packages/ai/tests/Attribute/SystemPromptAttributeTest.php | Adds tests for SystemPrompt attribute construction. |
| packages/ai/tests/Attribute/JsonOutputAttributeTest.php | Adds tests for JsonOutput attribute construction. |
| packages/ai/tests/Attribute/CacheAIResponseAttributeTest.php | Adds tests for CacheAIResponse attribute construction. |
| packages/ai/tests/Attribute/AIHandlerAttributeTest.php | Adds tests for AIHandler attribute construction. |
| packages/ai/tests/AnthropicDriverTest.php | Adds Anthropic driver tests (system extraction, headers, token accounting). |
| packages/ai/tests/AnthropicConfigTest.php | Adds tests for Anthropic config defaults/overrides. |
| packages/ai/tests/AIResponseTest.php | Adds tests for AIResponse value object behavior. |
| packages/ai/tests/AIProviderTest.php | Adds tests for AIProvider enum values. |
| packages/ai/tests/AIMessageTest.php | Adds tests for AIMessage helpers and array conversion. |
| packages/ai/tests/AIExceptionTest.php | Adds tests for the custom exception type. |
| packages/ai/tests/AIConfigTest.php | Adds tests for package-level config defaults/overrides. |
| packages/ai/src/functions.php | Adds package helper functions (ai(), prompt()). |
| packages/ai/src/MessageRole.php | Introduces message role enum used by messages/drivers. |
| packages/ai/src/GenericAIChat.php | Implements the main fluent chat façade and driver routing. |
| packages/ai/src/Exception/AIException.php | Adds AI-specific exception type. |
| packages/ai/src/Driver/OpenAIDriver.php | Implements OpenAI chat-completions driver. |
| packages/ai/src/Driver/AnthropicDriver.php | Implements Anthropic messages API driver. |
| packages/ai/src/Config/OpenAIConfig.php | Adds OpenAI config (env fallback, base URL, org, default model). |
| packages/ai/src/Config/AnthropicConfig.php | Adds Anthropic config (env fallback, base URL, version, default model). |
| packages/ai/src/Attribute/WithAI.php | Adds attribute for configuring injected AI instances. |
| packages/ai/src/Attribute/SystemPrompt.php | Adds attribute for declaring system prompts. |
| packages/ai/src/Attribute/JsonOutput.php | Adds attribute for requesting JSON-structured output. |
| packages/ai/src/Attribute/CacheAIResponse.php | Adds attribute for caching AI responses. |
| packages/ai/src/Attribute/AIHandler.php | Adds attribute to mark AI-powered handlers. |
| packages/ai/src/AIResponse.php | Adds response value object. |
| packages/ai/src/AIProvider.php | Adds provider enum. |
| packages/ai/src/AIMessage.php | Adds message value object and helpers. |
| packages/ai/src/AIDriver.php | Adds driver interface. |
| packages/ai/src/AIConfigInitializer.php | Adds container initializer for default AIConfig. |
| packages/ai/src/AIConfig.php | Adds package-level config object and defaults. |
| packages/ai/src/AIChatInitializer.php | Adds container initializer that builds GenericAIChat and registers drivers. |
| packages/ai/src/AIChat.php | Adds AIChat interface for fluent prompting/chat. |
| packages/ai/composer.json | Adds composer manifest for the new package. |
| packages/ai/LICENSE.md | Adds license file for the new package. |
| packages/ai/.gitattributes | Adds export-ignore rules and diff settings for the package. |
| composer.json | Registers Tempest\AI PSR-4 autoloading and the AI functions file + test namespace at the monorepo root. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| namespace Tempest\AI\Tests; | ||
|
|
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace does not match the directory structure under PSR-4 (Tempest\\AI\\Tests\\ => packages/ai/tests). Since this file is under tests/Attribute, it should be in Tempest\\AI\\Tests\\Attribute (consistent with other packages, e.g. packages/router/tests/Routing/Matching/MatchingRegexTest.php).
| $this->expectException(AIException::class); | ||
| $this->expectExceptionMessage('OpenAI API key is not configured'); | ||
|
|
||
| $driver->chat([AIMessage::user('Hello')]); |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test expects exception message OpenAI API key is not configured, but OpenAIDriver currently throws a longer message (... not configured. Set OPENAI_API_KEY ...). This will fail the test suite. Either update the expected message (e.g. use expectExceptionMessageMatches) or change the driver message to the exact string asserted here.
| $this->expectException(AIException::class); | ||
| $this->expectExceptionMessage('Anthropic API key is not configured'); | ||
|
|
||
| $driver->chat([AIMessage::user('Hello')]); |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test expects exception message Anthropic API key is not configured, but AnthropicDriver currently throws a longer message (... not configured. Set ANTHROPIC_API_KEY ...). This will fail the test suite. Either update the expected message (e.g. use expectExceptionMessageMatches) or change the driver message to the exact string asserted here.
| namespace Tempest\AI\Tests; | ||
|
|
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace does not match the directory structure under PSR-4 (Tempest\\AI\\Tests\\ => packages/ai/tests). Since this file is under tests/Attribute, it should be in Tempest\\AI\\Tests\\Attribute (consistent with other packages, e.g. packages/router/tests/Routing/Matching/MatchingRegexTest.php). This improves autoloading consistency and avoids classmap surprises.
| namespace Tempest\AI\Tests; | ||
|
|
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace does not match the directory structure under PSR-4 (Tempest\\AI\\Tests\\ => packages/ai/tests). Since this file is under tests/Attribute, it should be in Tempest\\AI\\Tests\\Attribute (consistent with other packages, e.g. packages/router/tests/Routing/Matching/MatchingRegexTest.php).
| public function chat(array $messages): AIResponse | ||
| { | ||
| $provider = $this->provider ?? $this->config->defaultProvider; | ||
| $driver = $this->getDriver($provider); | ||
|
|
||
| return $driver->chat( | ||
| messages: $messages, | ||
| model: $this->model, | ||
| temperature: $this->temperature, | ||
| maxTokens: $this->maxTokens, | ||
| ); | ||
| } |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
withSystemPrompt() currently only affects prompt(): chat() forwards the provided messages as-is and never prepends/merges the configured $this->systemPrompt. Given the interface doc (“Set a system prompt for this request”), callers will reasonably expect ->withSystemPrompt(...)->chat([...]) to include that system prompt as well. Consider having chat() inject the system prompt when set (ideally without duplicating it if the message list already contains a system message).
| use function Tempest\get; | ||
|
|
||
| /** | ||
| * Get the AI chat instance. | ||
| */ | ||
| function ai(): AIChat | ||
| { | ||
| return get(AIChat::class); | ||
| } |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
functions.php imports Tempest\get, but the container helper is Tempest\Container\get (see packages/container/src/functions.php). As written, calling ai() will trigger an undefined function error. Update the import to the correct namespace (or call \Tempest\Container\get() directly).
| function ai(): AIChat | ||
| { | ||
| return get(AIChat::class); | ||
| } |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The PR description shows $response = ai('...'), but ai() is defined with no parameters and returns an AIChat instance. Either update the docs/README to show the correct usage (ai()->prompt(...) or the prompt(...) helper), or change the helper signature to support ai(string $prompt) as documented.
| "require": { | ||
| "php": "^8.4", | ||
| "tempest/container": "dev-main", | ||
| "tempest/http-client": "dev-main", | ||
| "tempest/support": "dev-main" |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This package requires PHP ^8.4, but the root composer.json and other Tempest packages require ^8.5. In a monorepo this will create inconsistent platform requirements; align this to ^8.5 unless there is a deliberate reason to support 8.4 across the repo.
| namespace Tempest\AI\Tests; | ||
|
|
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Namespace does not match the directory structure under PSR-4 (Tempest\\AI\\Tests\\ => packages/ai/tests). Since this file is under tests/Attribute, it should be in Tempest\\AI\\Tests\\Attribute (consistent with other packages, e.g. packages/router/tests/Routing/Matching/MatchingRegexTest.php).
|
Hey @Tresor-Kasenda, it's better to come discuss on Discord about the features you want to add when they are this big. I've been working with AI at my job, I've used Symfony AI, Prism, I don't believe we should provide our own implementation right now. This would be a huge maintenance sink. |
|
Sure, no problem. The goal is to add a version of Laravel/Boost for Tempest. That's why I created a package. |
This PR introduces a new tempest/ai package that provides seamless AI integration for the Tempest Framework.
Features
Multi-provider support: OpenAI (GPT-4o, GPT-4-turbo, etc.) and Anthropic (Claude Sonnet, Opus, Haiku)
Fluent API: Chain configuration methods for clean, readable code
Immutable design: Each configuration method returns a new instance
Dependency injection: Full container integration with auto-discovery
PHP 8 Attributes: Declarative AI configuration on controllers and services
Usage
Attributes