diff --git a/app/Domains/Ai/Services/AiService.php b/app/Domains/Ai/Services/AiService.php index 786946a..4939272 100644 --- a/app/Domains/Ai/Services/AiService.php +++ b/app/Domains/Ai/Services/AiService.php @@ -6,24 +6,23 @@ use Illuminate\Support\Facades\Http; class AiService { - public function complete(string $prompt, string $model = 'claude-sonnet-4-6'): string + public function complete(string $prompt, string $model = 'gpt-4o-mini'): string { - $apiKey = config('services.anthropic.api_key'); + $apiKey = config('services.openai.api_key'); if (! $apiKey) { return ''; } $response = Http::withHeaders([ - 'x-api-key' => $apiKey, - 'anthropic-version' => '2023-06-01', - 'content-type' => 'application/json', - ])->post('https://api.anthropic.com/v1/messages', [ - 'model' => $model, - 'max_tokens' => 256, - 'messages' => [['role' => 'user', 'content' => $prompt]], + 'Authorization' => 'Bearer ' . $apiKey, + 'Content-Type' => 'application/json', + ])->post('https://api.openai.com/v1/chat/completions', [ + 'model' => $model, + 'max_tokens' => 512, + 'messages' => [['role' => 'user', 'content' => $prompt]], ]); - return trim($response->json('content.0.text') ?? ''); + return trim($response->json('choices.0.message.content') ?? ''); } } diff --git a/app/Livewire/Pages/Ai/Insights.php b/app/Livewire/Pages/Ai/Insights.php index 23b80f8..39a87b6 100644 --- a/app/Livewire/Pages/Ai/Insights.php +++ b/app/Livewire/Pages/Ai/Insights.php @@ -12,7 +12,7 @@ class Insights extends Component { public string $insights = ''; - public bool $loading = false; + public string $error = ''; public int $workspaceId = 0; @@ -23,21 +23,43 @@ class Insights extends Component public function generate(): void { - $workspace = Workspace::findOrFail($this->workspaceId); - $this->loading = true; + $this->error = ''; + $this->insights = ''; - $topLinks = Link::where('workspace_id', $workspace->id) - ->withCount('clicks') - ->orderByDesc('clicks_count') - ->limit(10) - ->get(['slug', 'target_url', 'clicks_count']); + if (! config('services.openai.api_key')) { + $this->error = 'OPENAI_API_KEY is not configured. Add it to .env and restart.'; + return; + } - $summary = $topLinks->map(fn ($l) => "{$l->slug}: {$l->clicks_count} clicks → {$l->target_url}")->implode("\n"); + try { + $workspace = Workspace::findOrFail($this->workspaceId); - $prompt = "You are a marketing analyst. Analyze these link performance stats and provide 3-5 actionable insights:\n\n{$summary}\n\nBe concise and specific."; + $topLinks = Link::where('workspace_id', $workspace->id) + ->withCount('clicks') + ->orderByDesc('clicks_count') + ->limit(10) + ->get(['slug', 'target_url', 'clicks_count']); - $this->insights = app(AiService::class)->complete($prompt); - $this->loading = false; + if ($topLinks->isEmpty()) { + $this->error = 'No links with clicks found. Create and share some links first.'; + return; + } + + $summary = $topLinks->map(fn ($l) => "{$l->slug}: {$l->clicks_count} clicks → {$l->target_url}")->implode("\n"); + + $prompt = "You are a marketing analyst. Analyze these link performance stats and provide 3-5 actionable insights:\n\n{$summary}\n\nBe concise and specific."; + + $result = app(AiService::class)->complete($prompt); + + if ($result === '') { + $this->error = 'AI returned an empty response. Check your API key and try again.'; + return; + } + + $this->insights = $result; + } catch (\Throwable $e) { + $this->error = 'Failed to generate insights: ' . $e->getMessage(); + } } public function render(): View diff --git a/config/services.php b/config/services.php index 6c78493..ebeed0b 100644 --- a/config/services.php +++ b/config/services.php @@ -39,4 +39,8 @@ return [ 'api_key' => env('ANTHROPIC_API_KEY'), ], + 'openai' => [ + 'api_key' => env('OPENAI_API_KEY'), + ], + ]; diff --git a/resources/views/livewire/pages/ai/insights.blade.php b/resources/views/livewire/pages/ai/insights.blade.php index dead542..c5dc7b7 100644 --- a/resources/views/livewire/pages/ai/insights.blade.php +++ b/resources/views/livewire/pages/ai/insights.blade.php @@ -10,6 +10,12 @@ + @if($error) +
Click "Generate Insights" to analyze your top 10 links with AI.