label(__('filament.resource.style.preview.generate')) ->icon('heroicon-o-sparkles') ->color('gray') ->action(function (): void { try { $state = $this->form->getState(); $path = $state['preview_source'] ?? null; $aiModelId = $state['ai_model_id'] ?? null; $prompt = $state['prompt'] ?? null; if (! $path) { throw new \RuntimeException(__('filament.resource.style.preview.missing_image')); } if (! $aiModelId) { throw new \RuntimeException(__('filament.resource.style.preview.missing_model')); } if (! $prompt) { throw new \RuntimeException(__('filament.resource.style.preview.missing_prompt')); } $aiModel = AiModel::with('primaryApiProvider')->findOrFail($aiModelId); $provider = $aiModel->primaryApiProvider; if (! $provider || ! $provider->enabled || ! $provider->plugin || ! $provider->token) { throw new \RuntimeException(__('filament.resource.style.preview.provider_invalid')); } $style = new Style([ 'title' => $state['title'] ?? 'Preview', 'prompt' => $prompt, 'description' => $state['description'] ?? '', 'parameters' => $state['parameters'] ?? [], ]); $style->setRelation('aiModel', $aiModel); $image = new Image([ 'path' => $path, ]); $plugin = PluginLoader::getPlugin($provider->plugin, $provider); $result = $plugin->processImageStyleChange($image, $style); $imageData = null; if (isset($result['base64Data'])) { $imageData = base64_decode($result['base64Data']); } elseif (isset($result['prompt_id'])) { $fetched = $plugin->getStyledImage($result['prompt_id']); if (str_starts_with($fetched, 'http')) { $resp = Http::timeout(30)->get($fetched); $resp->throw(); $imageData = $resp->body(); } else { $imageData = base64_decode($fetched); } } if (! $imageData) { throw new \RuntimeException(__('filament.resource.style.preview.no_image')); } $fileName = 'style_previews/generated_'.Str::uuid().'.png'; Storage::disk('public')->put($fileName, $imageData); $this->form->fill([ 'preview_image' => $fileName, ]); Notification::make() ->title(__('filament.resource.style.preview.done')) ->body(__('filament.resource.style.preview.saved_hint')) ->success() ->send(); } catch (\Throwable $e) { Notification::make() ->title(__('filament.resource.style.preview.failed')) ->body($e->getMessage()) ->danger() ->send(); } }), ]; } protected function getRedirectUrl(): string { return $this->getResource()::getUrl('index'); } }