All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
- Ajout de tobimori/kirby-seo via Composer
- snippet('seo/head') dans header.php (remplace les meta manuels)
- snippet('seo/schemas') dans footer.php pour JSON-LD
- Onglet SEO ajouté dans site.yml et tous les blueprints de pages
- Configuration SEO dans config.php (sitemap, robots, canonicalBase TODO)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
65 lines
1.6 KiB
PHP
65 lines
1.6 KiB
PHP
<?php
|
|
|
|
namespace tobimori\Seo;
|
|
|
|
use Generator;
|
|
use Kirby\Exception\Exception as KirbyException;
|
|
use tobimori\Seo\Ai\Content;
|
|
use tobimori\Seo\Ai\Driver;
|
|
|
|
use function is_string;
|
|
use function is_array;
|
|
|
|
/**
|
|
* Ai facade
|
|
*/
|
|
class Ai
|
|
{
|
|
private static array $providers = [];
|
|
|
|
public static function enabled(): bool
|
|
{
|
|
return (bool)Seo::option('ai.enabled', false);
|
|
}
|
|
|
|
/**
|
|
* Returns a provider instance for the given ID or the default provider.
|
|
*/
|
|
public static function provider(string|null $providerId = null): Driver
|
|
{
|
|
$providerId ??= Seo::option('ai.provider');
|
|
|
|
if (isset(self::$providers[$providerId])) {
|
|
return self::$providers[$providerId];
|
|
}
|
|
|
|
$config = Seo::option("ai.providers.{$providerId}");
|
|
if (!is_array($config)) {
|
|
throw new KirbyException("AI provider \"{$providerId}\" is not defined.");
|
|
}
|
|
|
|
$driver = $config['driver'] ?? null;
|
|
if (!is_string($driver) || $driver === '') {
|
|
throw new KirbyException("AI provider \"{$providerId}\" is missing a driver reference.");
|
|
}
|
|
|
|
if (!is_subclass_of($driver, Driver::class)) {
|
|
throw new KirbyException("AI provider driver \"{$driver}\" must extend " . Driver::class . '.');
|
|
}
|
|
|
|
return self::$providers[$providerId] = new $driver($providerId);
|
|
}
|
|
|
|
public static function streamTask(string $taskId, array $variables = []): Generator
|
|
{
|
|
$snippet = "seo/prompts/tasks/{$taskId}";
|
|
$prompt = trim(snippet($snippet, $variables, return: true));
|
|
if ($prompt === '') {
|
|
throw new KirbyException("AI prompt snippet \"{$snippet}\" is missing or empty.");
|
|
}
|
|
|
|
$content = [Content::user()->text($prompt)];
|
|
|
|
return self::provider()->stream($content);
|
|
}
|
|
}
|