| @@ -310,8 +310,14 @@ | ||
| 310 | 310 | * @return array Response data |
| 311 | 311 | * @throws \Exception If request fails |
| 312 | 312 | */ |
| 313 | 313 | private function make_request(string $endpoint, array $body = []): array { |
| 314 | + // The user's daily ceiling and kill switch are enforced here, at the | |
| 315 | + // one place every outbound OpenRouter call passes through, so no feature | |
| 316 | + // path can bypass them by forgetting to ask first (#448). | |
| 317 | + Spend_Guard::guard(); | |
| 318 | + Spend_Guard::record(); | |
| 319 | + | |
| 314 | 320 | $url = self::API_BASE_URL . '/' . ltrim($endpoint, '/'); |
| 315 | 321 | |
| 316 | 322 | $args = [ |
| 317 | 323 | 'timeout' => $this->timeout, |
| @@ -679,9 +685,9 @@ | ||
| 679 | 685 | return [ |
| 680 | 686 | 'optimized_data' => [ |
| 681 | 687 | 'site_name' => sanitize_text_field($optimization['optimized_data']['site_name'] ?? ''), |
| 682 | 688 | 'project_overview' => sanitize_textarea_field($optimization['optimized_data']['project_overview'] ?? ''), |
| 683 | - 'key_features' => sanitize_textarea_field($optimization['optimized_data']['key_features'] ?? ''), | |
| 689 | + 'key_features' => \ThinkRank\SEO\LLMs_Txt_Manager::normalize_ai_key_features($optimization['optimized_data']['key_features'] ?? ''), | |
| 684 | 690 | 'architecture' => sanitize_textarea_field($optimization['optimized_data']['architecture'] ?? ''), |
| 685 | 691 | 'development_guidelines' => sanitize_textarea_field($optimization['optimized_data']['development_guidelines'] ?? ''), |
| 686 | 692 | 'ai_context' => sanitize_textarea_field($optimization['optimized_data']['ai_context'] ?? ''), |
| 687 | 693 | ], |