feat(ai): finalize AI magic edits epic rollout and operations
This commit is contained in:
@@ -8,10 +8,12 @@ use App\Models\AiEditRequest;
|
||||
use App\Models\AiStyle;
|
||||
use App\Models\Event;
|
||||
use App\Models\Photo;
|
||||
use App\Services\AiEditing\AiBudgetGuardService;
|
||||
use App\Services\AiEditing\AiEditingRuntimeConfig;
|
||||
use App\Services\AiEditing\AiStyleAccessService;
|
||||
use App\Services\AiEditing\AiStylingEntitlementService;
|
||||
use App\Services\AiEditing\EventAiEditingPolicyService;
|
||||
use App\Services\AiEditing\Safety\AiAbuseEscalationService;
|
||||
use App\Services\AiEditing\Safety\AiSafetyPolicyService;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use App\Support\ApiError;
|
||||
@@ -27,9 +29,11 @@ class EventPublicAiEditController extends BaseController
|
||||
private readonly EventJoinTokenService $joinTokenService,
|
||||
private readonly AiSafetyPolicyService $safetyPolicy,
|
||||
private readonly AiEditingRuntimeConfig $runtimeConfig,
|
||||
private readonly AiBudgetGuardService $budgetGuard,
|
||||
private readonly AiStylingEntitlementService $entitlements,
|
||||
private readonly EventAiEditingPolicyService $eventPolicy,
|
||||
private readonly AiStyleAccessService $styleAccess,
|
||||
private readonly AiAbuseEscalationService $abuseEscalation,
|
||||
) {}
|
||||
|
||||
public function store(GuestAiEditStoreRequest $request, string $token, int $photo): JsonResponse
|
||||
@@ -95,6 +99,19 @@ class EventPublicAiEditController extends BaseController
|
||||
);
|
||||
}
|
||||
|
||||
$budgetDecision = $this->budgetGuard->evaluateForEvent($event);
|
||||
if (! $budgetDecision['allowed']) {
|
||||
return ApiError::response(
|
||||
$budgetDecision['reason_code'] ?? 'budget_hard_cap_reached',
|
||||
'Budget limit reached',
|
||||
$budgetDecision['message'] ?? 'The AI editing budget for this billing period has been exhausted.',
|
||||
Response::HTTP_FORBIDDEN,
|
||||
[
|
||||
'budget' => $budgetDecision['budget'],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
$style = $this->resolveStyleByKey($request->input('style_key'));
|
||||
if ($request->filled('style_key') && ! $style) {
|
||||
return ApiError::response(
|
||||
@@ -126,6 +143,25 @@ class EventPublicAiEditController extends BaseController
|
||||
$safetyDecision = $this->safetyPolicy->evaluatePrompt($prompt, $negativePrompt);
|
||||
$deviceId = $this->normalizeOptionalString((string) $request->header('X-Device-Id', ''));
|
||||
$sessionId = $this->normalizeOptionalString((string) $request->input('session_id', ''));
|
||||
$scopeKey = $this->normalizeOptionalString($deviceId ?: $sessionId) ?: 'guest';
|
||||
$abuseSignal = null;
|
||||
$safetyReasons = $safetyDecision->reasonCodes;
|
||||
if ($safetyDecision->blocked) {
|
||||
$abuseSignal = $this->abuseEscalation->recordPromptBlock(
|
||||
(int) $event->tenant_id,
|
||||
(int) $event->id,
|
||||
$scopeKey
|
||||
);
|
||||
if (($abuseSignal['escalated'] ?? false) && ! in_array(AiAbuseEscalationService::REASON_CODE, $safetyReasons, true)) {
|
||||
$safetyReasons[] = AiAbuseEscalationService::REASON_CODE;
|
||||
}
|
||||
}
|
||||
|
||||
$metadata = (array) $request->input('metadata', []);
|
||||
if (is_array($abuseSignal)) {
|
||||
$metadata['abuse'] = $abuseSignal;
|
||||
}
|
||||
$metadata['budget'] = $budgetDecision['budget'];
|
||||
|
||||
$idempotencyKey = $this->resolveIdempotencyKey(
|
||||
$request->input('idempotency_key'),
|
||||
@@ -150,12 +186,12 @@ class EventPublicAiEditController extends BaseController
|
||||
'input_image_path' => $photoModel->file_path,
|
||||
'requested_by_device_id' => $deviceId,
|
||||
'requested_by_session_id' => $sessionId,
|
||||
'safety_reasons' => $safetyDecision->reasonCodes,
|
||||
'safety_reasons' => $safetyReasons,
|
||||
'failure_code' => $safetyDecision->failureCode,
|
||||
'failure_message' => $safetyDecision->failureMessage,
|
||||
'queued_at' => now(),
|
||||
'completed_at' => $safetyDecision->blocked ? now() : null,
|
||||
'metadata' => $request->input('metadata', []),
|
||||
'metadata' => $metadata,
|
||||
];
|
||||
|
||||
$editRequest = AiEditRequest::query()->firstOrCreate(
|
||||
@@ -419,6 +455,7 @@ class EventPublicAiEditController extends BaseController
|
||||
'id' => $style->id,
|
||||
'key' => $style->key,
|
||||
'name' => $style->name,
|
||||
'version' => $style->version,
|
||||
'category' => $style->category,
|
||||
'description' => $style->description,
|
||||
'provider' => $style->provider,
|
||||
|
||||
Reference in New Issue
Block a user