validator = new ChatGPT_Response_Validator(); $this->error_handler = new ChatGPT_Error_Handler(); } /** * Process raw API response. * * @param array $raw_response Raw HTTP response data. * @return array Processed response with success status and data. */ public function process_response( array $raw_response ): array { // Handle cURL errors. if ( ! empty( $raw_response['curl_error'] ) ) { return $this->error_handler->handle_curl_error( $raw_response['curl_error'] ); } // Handle HTTP errors. if ( 200 !== $raw_response['http_code'] ) { return $this->error_handler->handle_http_error( $raw_response ); } // Parse JSON response. return $this->parse_json_response( $raw_response['response'] ); } /** * Parse JSON response from ChatGPT API. * * @param string $response_body Raw JSON response. * @return array Parsed response with success status and data. */ private function parse_json_response( string $response_body ): array { $decoded = json_decode( $response_body, true ); if ( JSON_ERROR_NONE !== json_last_error() ) { return $this->error_handler->handle_json_error( json_last_error_msg() ); } // Handle API errors in response. if ( isset( $decoded['error'] ) ) { return $this->error_handler->handle_api_error( $decoded['error'] ); } // Extract content from successful response. return $this->extract_content( $decoded ); } /** * Extract content from successful API response. * * @param array $decoded Decoded JSON response. * @return array Success response with content and usage data. */ private function extract_content( array $decoded ): array { $content = null; // 1) Responses API (GPT-5): output array with text/message/content. if ( isset( $decoded['output'] ) && is_array( $decoded['output'] ) ) { foreach ( $decoded['output'] as $output_item ) { // Skip reasoning items, only process message items. if ( isset( $output_item['type'] ) && 'message' === $output_item['type'] ) { // Try: output[].content as array with text field. if ( isset( $output_item['content'] ) && is_array( $output_item['content'] ) ) { foreach ( $output_item['content'] as $content_item ) { if ( isset( $content_item['text'] ) && is_string( $content_item['text'] ) && '' !== trim( $content_item['text'] ) ) { $content = trim( $content_item['text'] ); break 2; // Exit both loops. } } } // Fallback: check content field as string. if ( isset( $output_item['content'] ) && is_string( $output_item['content'] ) && '' !== trim( $output_item['content'] ) ) { $content = trim( $output_item['content'] ); break; } } // Try: output[].text (direct text field). if ( isset( $output_item['text'] ) && is_string( $output_item['text'] ) && '' !== trim( $output_item['text'] ) ) { $content = trim( $output_item['text'] ); break; } // Try: output[].message.content (legacy format). if ( isset( $output_item['message']['content'] ) && is_string( $output_item['message']['content'] ) && '' !== trim( $output_item['message']['content'] ) ) { $content = trim( $output_item['message']['content'] ); break; } } } // 2) Standard Chat Completions: choices[0].message.content. if ( null === $content && isset( $decoded['choices'][0]['message']['content'] ) && is_string( $decoded['choices'][0]['message']['content'] ) ) { $content = trim( $decoded['choices'][0]['message']['content'] ); } // 3) Some responses expose choices[0].content directly. if ( null === $content && isset( $decoded['choices'][0]['content'] ) && is_string( $decoded['choices'][0]['content'] ) ) { $content = trim( $decoded['choices'][0]['content'] ); } // 4) Responses API: output_text (legacy format). if ( null === $content && isset( $decoded['output_text'] ) && is_string( $decoded['output_text'] ) ) { $content = trim( $decoded['output_text'] ); } if ( null === $content || '' === $content ) { if ( function_exists( 'accessibility_audio_tts_debug_log' ) ) { accessibility_audio_tts_debug_log( '[ChatGPT_Response_Processor] No recognized content field in response: ' . substr( wp_json_encode( $decoded ), 0, 400 ), true ); } return array( 'success' => false, 'error' => 'No content in API response', ); } $usage = $decoded['usage'] ?? null; $tokens_used = $usage['total_tokens'] ?? 0; if ( function_exists( 'accessibility_audio_tts_debug_log' ) ) { accessibility_audio_tts_debug_log( '[ChatGPT_Response_Processor] Success - returned ' . strlen( $content ) . ' characters, used ' . $tokens_used . ' tokens', true ); } return array( 'success' => true, 'content' => $content, 'usage' => $usage, 'tokens' => array( 'input' => $usage['input_tokens'] ?? $usage['prompt_tokens'] ?? 0, 'output' => $usage['output_tokens'] ?? $usage['completion_tokens'] ?? 0, 'total' => $tokens_used, 'model' => $decoded['model'] ?? null, 'cached_input' => $usage['input_tokens_details']['cached_tokens'] ?? $usage['prompt_tokens_details']['cached_tokens'] ?? 0, ), ); } /** * Validate response content quality. * * @param string $content Response content. * @param string $original_text Original input text. * @return array Validation results. */ public function validate_content_quality( string $content, string $original_text ): array { return $this->validator->validate_content_quality( $content, $original_text ); } }