where('is_active', true)->firstOrFail() : $prompt; $provider = $this->provider($options['provider_id'] ?? null); $input = $promptModel->render($variables); $execution = AIExecution::create(['execution_id' => (string) Str::uuid(), 'ai_provider_id' => $provider->id, 'ai_prompt_id' => $promptModel->id, 'user_id' => auth()->id(), 'model' => $options['model'] ?? $provider->default_model, 'purpose' => $promptModel->purpose, 'input' => $input, 'context' => $variables, 'status' => 'running']); $started = microtime(true); try { $messages = []; if (filled($promptModel->system_prompt)) { $messages[] = ['role' => 'system', 'content' => $promptModel->system_prompt]; } $messages[] = ['role' => 'user', 'content' => $input]; $result = $this->driver($provider)->generate($provider, $messages, $options); $execution->update(['output' => $result['text'], 'usage' => $result['usage'], 'status' => 'completed', 'duration_ms' => (int) ((microtime(true) - $started) * 1000), 'completed_at' => now()]); } catch (\Throwable $e) { report($e); $execution->update(['status' => 'failed', 'error' => $e->getMessage(), 'duration_ms' => (int) ((microtime(true) - $started) * 1000), 'completed_at' => now()]); } return $execution->refresh(); } public function testProvider(int $providerId): array { $provider = AIProvider::findOrFail($providerId); try { $result = $this->driver($provider)->test($provider); $provider->update(['last_tested_at' => now(), 'last_test_status' => 'passed', 'last_test_message' => $result['message']]); return $result; } catch (\Throwable $e) { $provider->update(['last_tested_at' => now(), 'last_test_status' => 'failed', 'last_test_message' => $e->getMessage()]); return ['ok' => false, 'message' => $e->getMessage()]; } } private function provider(?int $id): AIProvider { return AIProvider::query()->when($id, fn ($q) => $q->whereKey($id))->when(! $id, fn ($q) => $q->where('is_default', true))->where('is_active', true)->first() ?? AIProvider::where('is_active', true)->firstOrFail(); } private function driver(AIProvider $provider): AIProviderDriver { return match ($provider->driver) { 'openai_compatible','openai','lm_studio','ollama' => app(OpenAICompatibleDriver::class), default => throw new \InvalidArgumentException("Unsupported AI driver [{$provider->driver}].") }; } }