Skip to content

Conversation

@Tresor-Kasenda
Copy link

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

<?php
// Simple prompt
$response = ai('What is the capital of France?');

// Fluent configuration
$response = $ai
    ->using(AIProvider::ANTHROPIC)
    ->withModel('claude-sonnet-4-20250514')
    ->withTemperature(0.3)
    ->withSystemPrompt('Be concise.')
    ->prompt('Explain PHP');

// Conversation
$response = $ai->chat([
    AIMessage::system('You are helpful.'),
    AIMessage::user('Hello!'),
]);

Attributes

<?php
final class MyController
{
    public function __construct(
        #[WithAI(provider: AIProvider::OPENAI, model: 'gpt-4o')]
        private AIChat $ai,
    ) {}

    #[SystemPrompt('Respond in JSON format.')]
    #[CacheAIResponse(ttl: 3600)]
    public function getData(): Response { ... }
}

- 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
Copilot AI review requested due to automatic review settings February 6, 2026 13:18
Copy link

Copilot AI left a 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\AI core 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.json autoload/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.

Comment on lines +5 to +6
namespace Tempest\AI\Tests;

Copy link

Copilot AI Feb 6, 2026

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).

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +43
$this->expectException(AIException::class);
$this->expectExceptionMessage('OpenAI API key is not configured');

$driver->chat([AIMessage::user('Hello')]);
Copy link

Copilot AI Feb 6, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +43
$this->expectException(AIException::class);
$this->expectExceptionMessage('Anthropic API key is not configured');

$driver->chat([AIMessage::user('Hello')]);
Copy link

Copilot AI Feb 6, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
namespace Tempest\AI\Tests;

Copy link

Copilot AI Feb 6, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
namespace Tempest\AI\Tests;

Copy link

Copilot AI Feb 6, 2026

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).

Copilot uses AI. Check for mistakes.
Comment on lines +42 to +53
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,
);
}
Copy link

Copilot AI Feb 6, 2026

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).

Copilot uses AI. Check for mistakes.
Comment on lines +7 to +15
use function Tempest\get;

/**
* Get the AI chat instance.
*/
function ai(): AIChat
{
return get(AIChat::class);
}
Copy link

Copilot AI Feb 6, 2026

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).

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +15
function ai(): AIChat
{
return get(AIChat::class);
}
Copy link

Copilot AI Feb 6, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +6 to +10
"require": {
"php": "^8.4",
"tempest/container": "dev-main",
"tempest/http-client": "dev-main",
"tempest/support": "dev-main"
Copy link

Copilot AI Feb 6, 2026

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.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +6
namespace Tempest\AI\Tests;

Copy link

Copilot AI Feb 6, 2026

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).

Copilot uses AI. Check for mistakes.
@innocenzi innocenzi marked this pull request as draft February 6, 2026 15:08
@innocenzi
Copy link
Member

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, openai/php—there are a lot of implementations, this space is moving fast with new features all the time (tool calling, agents, skills, MCPs, ACP).

I don't believe we should provide our own implementation right now. This would be a huge maintenance sink.

@Tresor-Kasenda
Copy link
Author

Sure, no problem. The goal is to add a version of Laravel/Boost for Tempest. That's why I created a package.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants