'system', 'content' => AIWEST_OpenAI::system_prompt()], ['role' => 'user', 'content' => "You are AI Webmaster Studio and a visual content builder for the WordPress website: " . get_bloginfo('name') . ".\n" . "Create ONE finished page/subpage, not a plan.\n\n" . "Administrator instruction:\n{$command}\n\n" . "Brand style:\n{$brand_style}\n\n" . "Page layout mode: {$layout_mode}. If the mode is ai_independent, build complete AI sections inside the page content and do not assume that the active theme will provide the full layout.\n\n" . "Active project goals:\n" . wp_json_encode($goals, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n\n" . "Imported design reference stored in project memory:\n" . ($lovable_context ?: 'No imported design reference.') . "\n\n" . (class_exists('AIWEST_Design_Contract') ? AIWEST_Design_Contract::planner_context($design_contract) . "\n\n" : '') . (class_exists('AIWEST_Design_System') ? AIWEST_Design_System::style_prompt() . "\n\n" : '') . (class_exists('AIWEST_Search_Optimization') ? AIWEST_Search_Optimization::prompt_contract(['post_type'=>'page']) . "\n\n" : '') . "Use external URLs only when the administrator instruction explicitly requests an external link. Otherwise use verified existing same-site URLs or the documented page anchors.\n\n" . "Return JSON only, without markdown:\n" . "{\n" . "\"page_title\":\"Page title\",\n" . "\"slug\":\"suggested-slug\",\n" . "\"excerpt\":\"Short page description\",\n" . "\"meta_title\":\"Truthful search title\",\n" . "\"meta_description\":\"Accurate search description\",\n" . "\"image_prompt\":\"featured image prompt without text in the image\",\n" . "\"sections\":[\n" . "{\"type\":\"hero\",\"title\":\"...\",\"subtitle\":\"...\",\"primary_cta\":\"...\",\"primary_cta_url\":\"verified same-site URL or #aiwest-main\",\"secondary_cta\":\"...\",\"secondary_cta_url\":\"verified same-site URL\"},\n" . "{\"type\":\"cards\",\"title\":\"...\",\"items\":[{\"title\":\"...\",\"text\":\"...\",\"link_label\":\"optional\",\"url\":\"verified same-site URL\"}]},\n" . "{\"type\":\"steps\",\"title\":\"...\",\"items\":[{\"title\":\"...\",\"text\":\"...\"}]},\n" . "{\"type\":\"text_image\",\"title\":\"...\",\"text\":\"...\"},\n" . "{\"type\":\"article_grid\",\"title\":\"...\",\"items\":[{\"title\":\"...\",\"text\":\"...\"}]},\n" . "{\"type\":\"faq\",\"title\":\"FAQ\",\"items\":[{\"question\":\"...\",\"answer\":\"...\"}]},\n" . "{\"type\":\"cta\",\"title\":\"...\",\"text\":\"...\",\"button\":\"...\",\"button_url\":\"verified same-site URL or #aiwest-contact\"}\n" . "],\n" . "\"admin_note\":\"Short note for the administrator describing what was prepared\"\n" . "}\n\n" . $admin_note_language . "\n" . "In sections, do not repeat page_title as an identical H1. Use the website language for page content, concrete details and practical guidance. The output must look like a modern page, not a plain article." ], ]; $result = AIWEST_OpenAI::chat($messages, 0.42); if (is_wp_error($result)) { if ($history_id) AIWEST_History::update_content($history_id, 'error', null, $result->get_error_message()); return $result; } $data = self::decode_json($result); if (!is_array($data) || empty($data['page_title'])) { $msg = __('AI did not return valid JSON for site building.', 'ai-webmaster-studio'); if ($history_id) AIWEST_History::update_content($history_id, 'error', null, $msg); return new WP_Error('aiwest_site_builder_bad_json', $msg); } $page_title = sanitize_text_field($data['page_title']); $requested_slug = sanitize_title($data['slug'] ?? $data['page_title']); if ($requested_slug === 'ai-directory-map' && class_exists('AIWEST_Directory_Map')) { $map_page_id = AIWEST_Directory_Map::ensure_map_page(true); if (is_wp_error($map_page_id)) { if ($history_id) AIWEST_History::update_content($history_id, 'error', null, $map_page_id->get_error_message()); return $map_page_id; } $message = __('The existing canonical map page was reused. Configure its content and layout in Site Builder > Locations & Partners Map.', 'ai-webmaster-studio'); if ($history_id) AIWEST_History::update_content($history_id, 'completed', $map_page_id, $message); return [ 'page_id' => (int) $map_page_id, 'title' => get_the_title((int) $map_page_id), 'status' => get_post_status((int) $map_page_id), 'admin_note' => $message, ]; } $data['_allow_external_links'] = self::instruction_allows_external_links($command); $html = class_exists('AIWEST_Visual_Renderer') ? AIWEST_Visual_Renderer::render_page($data) : wp_kses_post($data['html_content'] ?? ''); $heading_normalization = ['content' => $html, 'report' => []]; if (class_exists('AIWEST_Page_Title_Heading_Normalizer')) { $heading_normalization = AIWEST_Page_Title_Heading_Normalizer::normalize(0, $html, [ 'post_title' => $page_title, 'post_type' => 'page', 'mode' => 'custom_hero', 'theme_title_visible' => true, ]); $html = $heading_normalization['content']; } else { $html = self::remove_duplicate_first_heading($html, $page_title); } if (class_exists('AIWEST_Technical_Operator')) { $status = AIWEST_Technical_Operator::default_post_status($status); $aiwest_operator_decision = AIWEST_Technical_Operator::explain_decision('create_page', 'content_page_create', ['post_type' => 'page', 'post_status' => $status]); } else { $aiwest_operator_decision = []; } $page_id = wp_insert_post([ 'post_title' => $page_title, 'post_name' => sanitize_title($data['slug'] ?? $data['page_title']), 'post_excerpt' => sanitize_textarea_field($data['excerpt'] ?? ''), 'post_content' => wp_kses_post($html), 'post_status' => $status, 'post_type' => 'page', 'post_author' => class_exists('AIWEST_Technical_Operator') ? AIWEST_Technical_Operator::post_author_id(get_current_user_id()) : (get_current_user_id() ?: 1), 'meta_input' => [ '_aiwest_custom_hero_mode' => 'yes', ], ], true); if (is_wp_error($page_id)) { if ($history_id) AIWEST_History::update_content($history_id, 'error', null, $page_id->get_error_message()); return $page_id; } update_post_meta($page_id, '_aiwest_generated', 'yes'); update_post_meta($page_id, '_aiwest_source', 'site_builder'); update_post_meta($page_id, '_aiwest_custom_hero_mode', 'yes'); update_post_meta($page_id, '_aiwest_sections_json', wp_json_encode($data['sections'] ?? [], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT)); $search_report = class_exists('AIWEST_Search_Optimization') ? AIWEST_Search_Optimization::finalize($page_id, $html, ['post_type'=>'page','post_title'=>$page_title,'custom_hero'=>true], $data) : []; if (class_exists('AIWEST_Page_Title_Heading_Normalizer')) { AIWEST_Page_Title_Heading_Normalizer::record_report($page_id, $heading_normalization['report']); } $admin_note = self::normalize_admin_note($data['admin_note'] ?? ''); update_post_meta($page_id, '_aiwest_admin_note', $admin_note); if (class_exists('AIWEST_Technical_Operator')) { AIWEST_Technical_Operator::annotate_post($page_id, 'create_page', $aiwest_operator_decision); } $image_status = ''; if (class_exists('AIWEST_Image_Generator') && AIWEST_Image_Generator::enabled()) { $image = AIWEST_Image_Generator::generate_for_post($page_id, $data['image_prompt'] ?? $command); if (is_wp_error($image)) { $image_status = ' Image: error — ' . $image->get_error_message(); } else { $image_status = ' AI featured image has been added.'; } } elseif (class_exists('AIWEST_Image_Generator') && AIWEST_Image_Generator::library_enabled() && class_exists('AIWEST_Content_Engine')) { $media = AIWEST_Content_Engine::handle_media_for_existing_post($page_id, ['action' => 'library', 'placement' => 'featured', 'auto_select_library' => 'yes'], $data['image_prompt'] ?? $command); if (is_wp_error($media)) { $image_status = ' Media Library image: error — ' . $media->get_error_message(); } elseif (!empty($media['attachment_id'])) { $image_status = ' Featured image from Media Library has been added.'; } elseif (!empty($media['message'])) { $image_status = ' ' . sanitize_text_field($media['message']); } } $message = 'Page has been created as ' . get_post_status($page_id) . '.'; if (!empty($admin_note)) $message .= ' ' . $admin_note; $message .= $image_status; if ($history_id) AIWEST_History::update_content($history_id, 'completed', $page_id, $message); if (class_exists('AIWEST_Tasks')) { AIWEST_Tasks::add('site_page_created', [ 'page_id' => $page_id, 'command' => $command, 'status' => get_post_status($page_id), 'image' => $image_status, ], 'review'); } return [ 'page_id' => intval($page_id), 'title' => $page_title, 'status' => get_post_status($page_id), 'admin_note' => trim($admin_note . $image_status), ]; } public static function normalize_admin_note($text) { $text = sanitize_text_field((string) $text); if ($text === '') return ''; if (class_exists('AIWEST_Product') && AIWEST_Product::is_en()) { $map = [ 'Homepage została zbudowana zgodnie z wytycznymi: zawiera sekcję hero, karty funkcji, kroki wdrożenia, sekcję tekstowo-graficzną, siatkę kluczowych zasobów, FAQ oraz mocne CTA. Struktura jest nowoczesna, przejrzysta i gotowa do publikacji.' => 'The homepage was built according to the guidelines: it includes a hero section, feature cards, implementation steps, a text-and-image section, a grid of key resources, FAQ and a strong CTA. The structure is modern, clear and ready for publication.', 'Strona główna została zbudowana zgodnie z wytycznymi: zawiera sekcję hero, karty funkcji, kroki wdrożenia, sekcję tekstowo-graficzną, siatkę kluczowych zasobów, FAQ oraz mocne CTA. Struktura jest nowoczesna, przejrzysta i gotowa do publikacji.' => 'The homepage was built according to the guidelines: it includes a hero section, feature cards, implementation steps, a text-and-image section, a grid of key resources, FAQ and a strong CTA. The structure is modern, clear and ready for publication.', 'Homepage została zbudowana zgodnie z wytycznymi' => 'The homepage was built according to the guidelines', 'Strona główna została zbudowana zgodnie z wytycznymi' => 'The homepage was built according to the guidelines', 'została zbudowana zgodnie z wytycznymi' => 'was built according to the guidelines', 'zawiera sekcję hero' => 'it includes a hero section', 'karty funkcji' => 'feature cards', 'kroki wdrożenia' => 'implementation steps', 'sekcję tekstowo-graficzną' => 'a text-and-image section', 'siatkę kluczowych zasobów' => 'a grid of key resources', 'oraz mocne CTA' => 'and a strong CTA', 'Struktura jest nowoczesna, przejrzysta i gotowa do publikacji.' => 'The structure is modern, clear and ready for publication.', 'Struktura jest nowoczesna' => 'The structure is modern', 'przejrzysta' => 'clear', 'gotowa do publikacji' => 'ready for publication', 'zgodnie z wytycznymi' => 'according to the guidelines', 'sekcję' => 'section', 'sekcja' => 'section', 'zawiera' => 'includes', ]; uksort($map, function($a, $b) { return strlen($b) <=> strlen($a); }); $text = strtr($text, $map); $text = preg_replace('/\s+/', ' ', $text); } return trim($text); } protected static function instruction_allows_external_links($instruction) { return preg_match('/\b(?:external\s+links?|link\s+to\s+https?:\/\/|link\s+to\s+an?\s+external|zewnętrzn(?:y|e|ych)\s+link|link(?:i|u)?\s+zewnętrzn)/iu', (string)$instruction) === 1; } public static function decode_json($result) { $clean = trim((string)$result); $clean = preg_replace('/^```json\s*/i', '', $clean); $clean = preg_replace('/^```\s*/', '', $clean); $clean = preg_replace('/\s*```$/', '', $clean); $data = json_decode($clean, true); if (!is_array($data)) { $first = strpos($clean, '{'); $last = strrpos($clean, '}'); if ($first !== false && $last !== false && $last > $first) { $data = json_decode(substr($clean, $first, $last - $first + 1), true); } } return $data; } public static function remove_duplicate_first_heading($html, $title) { $title_clean = trim(wp_strip_all_tags($title)); if (!$html || !$title_clean) return $html; $pattern = '/^\s*