'user', 'content' => $prompt, ), ); // Use planning model for keyword suggestion (fast and cheap) $response = $provider->chat( $messages, array( 'temperature' => 0.3 ), 'planning' ); if ( is_wp_error( $response ) ) { return $response; } $content = trim( $response['content'] ?? '' ); // Try to extract JSON from response $json_start = strpos( $content, '{' ); $json_end = strrpos( $content, '}' ); if ( false === $json_start || false === $json_end ) { return new WP_Error( 'invalid_response', 'AI response is not valid JSON' ); } $json_string = substr( $content, $json_start, $json_end - $json_start + 1 ); $suggestions = json_decode( $json_string, true ); if ( null === $suggestions || ! is_array( $suggestions ) ) { return new WP_Error( 'parse_error', 'Failed to parse keyword suggestions' ); } // Validate required fields if ( empty( $suggestions['focus_keyword'] ) || empty( $suggestions['secondary_keywords'] ) ) { return new WP_Error( 'incomplete_suggestions', 'Keyword suggestions are incomplete' ); } // Ensure secondary_keywords is an array if ( ! is_array( $suggestions['secondary_keywords'] ) ) { $suggestions['secondary_keywords'] = array(); } // Track cost with separate operation type $cost = $response['cost'] ?? 0; if ( $cost > 0 && $post_id > 0 ) { do_action( 'wp_aw_after_api_request', $post_id, $response['model'] ?? 'unknown', 'suggest_keyword', $response['input_tokens'] ?? 0, $response['output_tokens'] ?? 0, $cost ); } return array( 'focus_keyword' => $suggestions['focus_keyword'], 'secondary_keywords' => $suggestions['secondary_keywords'], 'reasoning' => $suggestions['reasoning'] ?? '', 'cost' => $cost, ); } /** * Build language instruction for keyword suggestion. * * @since 0.1.0 * @param string $language Language code. * @return string Language instruction. */ private static function build_language_instruction( $language ) { $language = trim( (string) $language ); // If auto or empty, match article language if ( empty( $language ) || 'auto' === strtolower( $language ) ) { return 'Suggest keywords in the same language as the article topic and outline.'; } // Pass any language name directly - AI understands all languages return "IMPORTANT: Suggest keywords in {$language}. Consider {$language} search queries and terms used by {$language} speakers."; } }