feat(ai-templates): content template contract + value objects

This commit is contained in:
Paulo Castellano 2026-06-17 17:03:42 -03:00
parent 34c49c5ce8
commit ebd9a2ac0f
3 changed files with 104 additions and 0 deletions

View file

@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace App\Ai\Templates;
use Illuminate\Contracts\JsonSchema\JsonSchema;
interface AiContentTemplate
{
/** Stable key used in the request + registry, e.g. 'image_card'. */
public function key(): string;
/** i18n key for the gallery label. */
public function name(): string;
/** i18n key for the gallery description. */
public function description(): string;
/** Public path to the preview thumbnail shown in the picker. */
public function previewAsset(): string;
/** Whether a social account must be selected for this template. */
public function needsAccount(): bool;
/**
* Content types (by value) this template can produce. Empty = all AI formats.
*
* @return array<int, string>
*/
public function supportedFormats(): array;
/** The 'format' string passed to the generator agent (e.g. 'single'). */
public function generatorFormat(): string;
/** The Blade view path for the generator prompt. */
public function promptView(): string;
/**
* The structured-output schema for the generator.
*
* @return array<string, mixed>
*/
public function schema(JsonSchema $schema, TemplateContext $context): array;
/**
* Text fields (by structured-output key) the humanizer should rewrite.
* Empty = skip humanization.
*
* @return array<string, string>
*/
public function humanizableFields(): array;
/**
* Build the post from the (humanized) structured output.
*
* @param array<string, mixed> $structured
*/
public function assemble(array $structured, TemplateContext $context): GeneratedPost;
}

View file

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Ai\Templates;
use App\Enums\PostPlatform\ContentType;
/**
* The output of a template's assemble(): the caption to store as Post.content,
* the media items to attach, and the content type the post platform should use.
*/
class GeneratedPost
{
/**
* @param array<int, array<string, mixed>> $media
*/
public function __construct(
public string $content,
public array $media,
public ?ContentType $contentType,
) {}
}

View file

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace App\Ai\Templates;
use App\Models\SocialAccount;
use App\Models\Workspace;
/**
* Everything a template needs to assemble a post from the LLM output.
*/
class TemplateContext
{
public function __construct(
public Workspace $workspace,
public ?SocialAccount $socialAccount,
public string $format,
public int $imageCount,
) {}
}