feat: intégration plugin Kirby SEO
All checks were successful
Deploy / Deploy to Production (push) Successful in 22s
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>
This commit is contained in:
parent
baab2fb3a1
commit
58c31ea391
133 changed files with 9201 additions and 253 deletions
65
site/plugins/kirby-seo/classes/Ai.php
Normal file
65
site/plugins/kirby-seo/classes/Ai.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?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);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue