Changeset 3390455
- Timestamp:
- 11/05/2025 12:42:16 PM (5 months ago)
- Location:
- clearpost-simple-ai-auto-post
- Files:
-
- 5 edited
- 28 copied
-
tags/1.2.2 (copied) (copied from clearpost-simple-ai-auto-post/trunk)
-
tags/1.2.2/assets (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets)
-
tags/1.2.2/assets/css/design-system.css (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/css/design-system.css)
-
tags/1.2.2/assets/css/editor-chat.css (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/css/editor-chat.css)
-
tags/1.2.2/assets/css/onboarding.css (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/css/onboarding.css)
-
tags/1.2.2/assets/css/scheduler.css (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/css/scheduler.css)
-
tags/1.2.2/assets/js/admin.js (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/js/admin.js)
-
tags/1.2.2/assets/js/dist/editor-chat.bundle.js (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/js/dist/editor-chat.bundle.js)
-
tags/1.2.2/assets/js/editor-chat.js (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/js/editor-chat.js)
-
tags/1.2.2/assets/js/scheduler.js (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/js/scheduler.js)
-
tags/1.2.2/assets/js/site-context.js (copied) (copied from clearpost-simple-ai-auto-post/trunk/assets/js/site-context.js)
-
tags/1.2.2/includes (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes)
-
tags/1.2.2/includes/ai-requests.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/ai-requests.php) (2 diffs)
-
tags/1.2.2/includes/ai-settings.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/ai-settings.php)
-
tags/1.2.2/includes/editor-chat.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/editor-chat.php)
-
tags/1.2.2/includes/generate.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/generate.php) (2 diffs)
-
tags/1.2.2/includes/images.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/images.php)
-
tags/1.2.2/includes/licensing.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/licensing.php)
-
tags/1.2.2/includes/onboarding.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/onboarding.php)
-
tags/1.2.2/includes/scheduler.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/scheduler.php)
-
tags/1.2.2/includes/site-context.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/site-context.php) (7 diffs)
-
tags/1.2.2/includes/taxonomy.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/includes/taxonomy.php)
-
tags/1.2.2/index.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/index.php)
-
tags/1.2.2/languages (copied) (copied from clearpost-simple-ai-auto-post/trunk/languages)
-
tags/1.2.2/license.txt (copied) (copied from clearpost-simple-ai-auto-post/trunk/license.txt)
-
tags/1.2.2/readme.txt (copied) (copied from clearpost-simple-ai-auto-post/trunk/readme.txt) (1 diff)
-
tags/1.2.2/simple-ai-auto-post.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/simple-ai-auto-post.php) (2 diffs)
-
tags/1.2.2/uninstall.php (copied) (copied from clearpost-simple-ai-auto-post/trunk/uninstall.php)
-
trunk/includes/ai-requests.php (modified) (2 diffs)
-
trunk/includes/generate.php (modified) (2 diffs)
-
trunk/includes/site-context.php (modified) (7 diffs)
-
trunk/readme.txt (modified) (1 diff)
-
trunk/simple-ai-auto-post.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
clearpost-simple-ai-auto-post/tags/1.2.2/includes/ai-requests.php
r3387025 r3390455 119 119 } elseif ( $provider === 'anthropic' ) { 120 120 $tool_schema = array( 121 'type' => 'custom', 121 122 'name' => 'json_responder', 122 123 'description' => 'Responds with a JSON object containing a chat message and edited content.', … … 157 158 'model' => $model ?: 'claude-sonnet-4-20250514', 158 159 'messages' => $anthropic_messages, 159 'tool_choice' => 'auto',160 'tools' => array( array( 'type' => 'web_search ' ), $tool_schema ),160 'tool_choice' => array( 'type' => 'tool', 'name' => 'json_responder' ), 161 'tools' => array( array( 'type' => 'web_search_20250305', 'name' => 'web_search' ), $tool_schema ), 161 162 ); 162 163 -
clearpost-simple-ai-auto-post/tags/1.2.2/includes/generate.php
r3387025 r3390455 83 83 $post_data = array( 84 84 'post_title' => ! empty( $args['title'] ) ? $args['title'] : $generated['title'], 85 'post_content' => $generated['content'],85 'post_content' => saiap_prepare_post_content( $generated['content'] ), 86 86 'post_status' => 'draft', 87 87 'post_type' => $args['post_type'], … … 154 154 'edit_url' => get_edit_post_link( $post_id, '' ), 155 155 ); 156 } 157 158 /** 159 * Normalize generated content for WordPress/Gutenberg display. 160 * - If content already contains blocks or <p> tags, return as-is. 161 * - Otherwise, convert plaintext newlines to paragraphs using wpautop and sanitize. 162 * 163 * @param string $raw Raw generated content 164 * @return string Normalized HTML content 165 */ 166 function saiap_prepare_post_content( $raw ) { 167 if ( ! is_string( $raw ) || $raw === '' ) { 168 return ''; 169 } 170 // If the content already contains block delimiters or existing paragraph tags, keep it 171 if ( ( function_exists( 'has_blocks' ) && has_blocks( $raw ) ) || 172 strpos( $raw, '<!-- wp:' ) !== false || 173 strpos( $raw, '<p' ) !== false ) { 174 return $raw; 175 } 176 177 // Normalize line endings and convert to paragraphs 178 $normalized = str_replace( array( "\r\n", "\r" ), "\n", $raw ); 179 $html = wpautop( $normalized ); 180 181 // Sanitize to allowed post HTML 182 return wp_kses_post( $html ); 156 183 } 157 184 -
clearpost-simple-ai-auto-post/tags/1.2.2/includes/site-context.php
r3387025 r3390455 465 465 $context = saiap_get_site_context(); 466 466 467 $max_retries = 2; 468 $retry_delay = 3; // seconds 469 470 for ( $attempt = 0; $attempt <= $max_retries; $attempt++ ) { 471 if ( $attempt > 0 ) { 472 sleep( $retry_delay ); 473 } 474 475 // Log the posts data being sent to API 476 $posts_for_api = array_map( 477 function ( $post ) { 478 return array( 479 'ID' => $post['ID'], 480 'title' => $post['title'], 481 'content' => $post['content'], 482 'published_at' => $post['published_at'], 483 'modified_at' => $post['modified_at'], 484 'post_type' => $post['post_type'], 485 'taxonomy_data' => isset( $post['taxonomy_data'] ) ? $post['taxonomy_data'] : null, 486 ); 487 }, 488 $context['posts'] 467 // Prepare posts for API and collect present IDs 468 $posts_for_api = array_map( 469 function ( $post ) { 470 return array( 471 'ID' => $post['ID'], 472 'title' => $post['title'], 473 'content' => $post['content'], 474 'published_at' => $post['published_at'], 475 'modified_at' => $post['modified_at'], 476 'post_type' => $post['post_type'], 477 'taxonomy_data' => isset( $post['taxonomy_data'] ) ? $post['taxonomy_data'] : null, 478 ); 479 }, 480 $context['posts'] 481 ); 482 $present_post_ids = array_map( 483 function( $p ) { return $p['ID']; }, 484 $posts_for_api 485 ); 486 487 // Chunk posts to keep request size low 488 $chunk_size = 20; // heuristic; adjust as needed 489 $chunks = array_chunk( $posts_for_api, $chunk_size ); 490 491 // Send partial chunks (aggregate errors, don't early return) 492 $partial_errors = array(); 493 $successful_chunks = 0; 494 $total_chunks = count( $chunks ); 495 foreach ( $chunks as $chunk_index => $chunk_posts ) { 496 $partial_body = wp_json_encode( 497 array( 498 'license_key' => $license_key, 499 'domain' => $context['site_data']['domain'], 500 'site_data' => array( 501 'homepage_content' => $context['site_data']['homepage_content'], 502 'site_description' => $context['site_data']['site_description'], 503 ), 504 'posts' => $chunk_posts, 505 'is_partial' => true, 506 // Include aggregated metadata for richer context on the premium side 507 'post_types' => $context['postTypes'], 508 'taxonomies' => $context['taxonomies'], 509 'customContext' => isset( $context['customContext'] ) ? $context['customContext'] : null, 510 ) 489 511 ); 490 491 492 512 493 513 $response = wp_remote_post( … … 498 518 'Accept' => 'application/json', 499 519 ), 500 'body' => wp_json_encode( 501 array( 502 'license_key' => $license_key, 503 'domain' => $context['site_data']['domain'], 504 'site_data' => array( 505 'homepage_content' => $context['site_data']['homepage_content'], 506 'site_description' => $context['site_data']['site_description'], 507 ), 508 'posts' => $posts_for_api, 509 // Include aggregated metadata for richer context on the premium side 510 'post_types' => $context['postTypes'], 511 'taxonomies' => $context['taxonomies'], 512 'customContext' => isset( $context['customContext'] ) ? $context['customContext'] : null, 513 ) 514 ), 515 'timeout' => 60, // Longer timeout for full context update 520 'body' => $partial_body, 521 'timeout' => 60, 516 522 ) 517 523 ); 518 524 519 // Log response details 520 if ( is_wp_error( $response ) ) { 521 522 } else { 523 $status_code = wp_remote_retrieve_response_code( $response ); 524 $headers = wp_remote_retrieve_headers( $response ); 525 526 $body = wp_remote_retrieve_body( $response ); 527 528 $data = json_decode( $body, true ); 529 } 530 531 if ( ! is_wp_error( $response ) ) { 532 $status_code = wp_remote_retrieve_response_code( $response ); 533 if ( $status_code === 200 ) { 534 break; // Success, exit retry loop 535 } 536 if ( $status_code !== 503 && $status_code !== 404 ) { 537 break; // Don't retry on non-503/404 errors 538 } 539 } 540 } 541 542 if ( is_wp_error( $response ) ) { 543 return new WP_Error( 'api_error', 'Failed to update context: ' . $response->get_error_message() ); 544 } 525 if ( is_wp_error( $response ) ) { 526 $partial_errors[] = array( 527 'chunk' => $chunk_index + 1, 528 'total' => $total_chunks, 529 'message' => $response->get_error_message(), 530 'status' => null, 531 ); 532 continue; 533 } 534 535 $status_code = wp_remote_retrieve_response_code( $response ); 536 if ( $status_code !== 200 ) { 537 $body_err = wp_remote_retrieve_body( $response ); 538 $data_err = json_decode( $body_err, true ); 539 $error_detail = ( $data_err && isset( $data_err['error'] ) ) ? $data_err['error'] : 'Server returned status code: ' . $status_code; 540 $partial_errors[] = array( 541 'chunk' => $chunk_index + 1, 542 'total' => $total_chunks, 543 'message' => $error_detail, 544 'status' => $status_code, 545 ); 546 continue; 547 } 548 549 $successful_chunks++; 550 } 551 552 // Final prune request with IDs only 553 $prune_body = wp_json_encode( 554 array( 555 'license_key' => $license_key, 556 'domain' => $context['site_data']['domain'], 557 'present_post_ids' => $present_post_ids, 558 ) 559 ); 560 561 $response = wp_remote_post( 562 'https://saiap.gopurposego.com/api/context/update', 563 array( 564 'headers' => array( 565 'Content-Type' => 'application/json', 566 'Accept' => 'application/json', 567 ), 568 'body' => $prune_body, 569 'timeout' => 60, 570 ) 571 ); 572 573 if ( is_wp_error( $response ) ) { 574 $aggregate_note = ''; 575 if ( ! empty( $partial_errors ) ) { 576 $aggregate_note = ' Partial errors: ' . wp_json_encode( $partial_errors ); 577 } 578 return new WP_Error( 'api_error', 'Failed to finalize context update: ' . $response->get_error_message() . $aggregate_note ); 579 } 545 580 546 581 $status_code = wp_remote_retrieve_response_code( $response ); … … 548 583 $data = json_decode( $body, true ); 549 584 550 if ( $status_code !== 200 ) { 551 $error_message = 'Failed to update context. '; 552 if ( $data && isset( $data['error'] ) ) { 553 $error_message .= $data['error']; 554 } else { 555 $error_message .= 'Server returned status code: ' . $status_code; 556 } 557 return new WP_Error( 'api_error', $error_message ); 558 } 585 if ( $status_code !== 200 ) { 586 $error_message = 'Failed to finalize context update. '; 587 if ( $data && isset( $data['error'] ) ) { 588 $error_message .= $data['error']; 589 } else { 590 $error_message .= 'Server returned status code: ' . $status_code; 591 } 592 if ( ! empty( $partial_errors ) ) { 593 $error_message .= ' Partial errors: ' . wp_json_encode( $partial_errors ); 594 } 595 return new WP_Error( 'api_error', $error_message ); 596 } 597 598 // If all chunks failed but prune succeeded, surface aggregated error 599 if ( $successful_chunks === 0 && $total_chunks > 0 ) { 600 return new WP_Error( 'api_error', 'Failed to update context: all ' . $total_chunks . ' chunk(s) failed. Details: ' . wp_json_encode( $partial_errors ) ); 601 } 559 602 560 603 // Store the last update timestamp … … 571 614 572 615 // Set appropriate message based on changes and failures 573 if ( ! $has_changes ) {616 if ( ! $has_changes ) { 574 617 $message = 'No changes detected. Site context remains the same.'; 575 618 } else { 576 $message = 'Site context updated successfully.';577 578 if ( isset( $data['syncResult'] ) && isset( $data['syncResult']['failedCount'] ) && $data['syncResult']['failedCount'] > 0 ) {619 $message = 'Site context updated successfully.'; 620 621 if ( isset( $data['syncResult'] ) && isset( $data['syncResult']['failedCount'] ) && $data['syncResult']['failedCount'] > 0 ) { 579 622 $has_failures = true; 580 623 $message .= ' However, ' . $data['syncResult']['failedCount'] . ' posts failed to sync.'; … … 582 625 } 583 626 627 // Reflect any transport-level chunk failures in the flags/message 628 if ( ! empty( $partial_errors ) ) { 629 $has_failures = true; 630 $message .= ' Some chunks failed during upload.'; 631 } 632 584 633 // Update cache if context is in the response 585 634 if ( isset( $data['context'] ) ) { … … 587 636 } 588 637 589 return array(638 return array( 590 639 'message' => $message, 591 640 'has_failures' => $has_failures, … … 593 642 'sync_result' => isset( $data['syncResult'] ) ? $data['syncResult'] : null, 594 643 'timestamp' => $timestamp, 644 'partial_errors' => ! empty( $partial_errors ) ? $partial_errors : null, 595 645 ); 596 646 } -
clearpost-simple-ai-auto-post/tags/1.2.2/readme.txt
r3387025 r3390455 4 4 Requires at least: 5.0 5 5 Tested up to: 6.8 6 Stable tag: 1.2. 06 Stable tag: 1.2.2 7 7 Requires PHP: 7.2 8 8 License: GPLv2 or later -
clearpost-simple-ai-auto-post/tags/1.2.2/simple-ai-auto-post.php
r3387025 r3390455 4 4 Description: Your AI Agent for SEO, in WordPress. An AI content marketer that knows your site, then schedules and generates posts every day. 5 5 Plugin URI: https://clearpostplugin.com/ 6 Version: 1.2. 06 Version: 1.2.2 7 7 License: GPLv2 or later 8 8 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 18 18 19 19 // Define plugin version 20 define( 'SAIAP_VERSION', '1.2. 0' );20 define( 'SAIAP_VERSION', '1.2.2' ); 21 21 22 22 // Optionally enable Demo Mode (for internal testing only) -
clearpost-simple-ai-auto-post/trunk/includes/ai-requests.php
r3387025 r3390455 119 119 } elseif ( $provider === 'anthropic' ) { 120 120 $tool_schema = array( 121 'type' => 'custom', 121 122 'name' => 'json_responder', 122 123 'description' => 'Responds with a JSON object containing a chat message and edited content.', … … 157 158 'model' => $model ?: 'claude-sonnet-4-20250514', 158 159 'messages' => $anthropic_messages, 159 'tool_choice' => 'auto',160 'tools' => array( array( 'type' => 'web_search ' ), $tool_schema ),160 'tool_choice' => array( 'type' => 'tool', 'name' => 'json_responder' ), 161 'tools' => array( array( 'type' => 'web_search_20250305', 'name' => 'web_search' ), $tool_schema ), 161 162 ); 162 163 -
clearpost-simple-ai-auto-post/trunk/includes/generate.php
r3387025 r3390455 83 83 $post_data = array( 84 84 'post_title' => ! empty( $args['title'] ) ? $args['title'] : $generated['title'], 85 'post_content' => $generated['content'],85 'post_content' => saiap_prepare_post_content( $generated['content'] ), 86 86 'post_status' => 'draft', 87 87 'post_type' => $args['post_type'], … … 154 154 'edit_url' => get_edit_post_link( $post_id, '' ), 155 155 ); 156 } 157 158 /** 159 * Normalize generated content for WordPress/Gutenberg display. 160 * - If content already contains blocks or <p> tags, return as-is. 161 * - Otherwise, convert plaintext newlines to paragraphs using wpautop and sanitize. 162 * 163 * @param string $raw Raw generated content 164 * @return string Normalized HTML content 165 */ 166 function saiap_prepare_post_content( $raw ) { 167 if ( ! is_string( $raw ) || $raw === '' ) { 168 return ''; 169 } 170 // If the content already contains block delimiters or existing paragraph tags, keep it 171 if ( ( function_exists( 'has_blocks' ) && has_blocks( $raw ) ) || 172 strpos( $raw, '<!-- wp:' ) !== false || 173 strpos( $raw, '<p' ) !== false ) { 174 return $raw; 175 } 176 177 // Normalize line endings and convert to paragraphs 178 $normalized = str_replace( array( "\r\n", "\r" ), "\n", $raw ); 179 $html = wpautop( $normalized ); 180 181 // Sanitize to allowed post HTML 182 return wp_kses_post( $html ); 156 183 } 157 184 -
clearpost-simple-ai-auto-post/trunk/includes/site-context.php
r3387025 r3390455 465 465 $context = saiap_get_site_context(); 466 466 467 $max_retries = 2; 468 $retry_delay = 3; // seconds 469 470 for ( $attempt = 0; $attempt <= $max_retries; $attempt++ ) { 471 if ( $attempt > 0 ) { 472 sleep( $retry_delay ); 473 } 474 475 // Log the posts data being sent to API 476 $posts_for_api = array_map( 477 function ( $post ) { 478 return array( 479 'ID' => $post['ID'], 480 'title' => $post['title'], 481 'content' => $post['content'], 482 'published_at' => $post['published_at'], 483 'modified_at' => $post['modified_at'], 484 'post_type' => $post['post_type'], 485 'taxonomy_data' => isset( $post['taxonomy_data'] ) ? $post['taxonomy_data'] : null, 486 ); 487 }, 488 $context['posts'] 467 // Prepare posts for API and collect present IDs 468 $posts_for_api = array_map( 469 function ( $post ) { 470 return array( 471 'ID' => $post['ID'], 472 'title' => $post['title'], 473 'content' => $post['content'], 474 'published_at' => $post['published_at'], 475 'modified_at' => $post['modified_at'], 476 'post_type' => $post['post_type'], 477 'taxonomy_data' => isset( $post['taxonomy_data'] ) ? $post['taxonomy_data'] : null, 478 ); 479 }, 480 $context['posts'] 481 ); 482 $present_post_ids = array_map( 483 function( $p ) { return $p['ID']; }, 484 $posts_for_api 485 ); 486 487 // Chunk posts to keep request size low 488 $chunk_size = 20; // heuristic; adjust as needed 489 $chunks = array_chunk( $posts_for_api, $chunk_size ); 490 491 // Send partial chunks (aggregate errors, don't early return) 492 $partial_errors = array(); 493 $successful_chunks = 0; 494 $total_chunks = count( $chunks ); 495 foreach ( $chunks as $chunk_index => $chunk_posts ) { 496 $partial_body = wp_json_encode( 497 array( 498 'license_key' => $license_key, 499 'domain' => $context['site_data']['domain'], 500 'site_data' => array( 501 'homepage_content' => $context['site_data']['homepage_content'], 502 'site_description' => $context['site_data']['site_description'], 503 ), 504 'posts' => $chunk_posts, 505 'is_partial' => true, 506 // Include aggregated metadata for richer context on the premium side 507 'post_types' => $context['postTypes'], 508 'taxonomies' => $context['taxonomies'], 509 'customContext' => isset( $context['customContext'] ) ? $context['customContext'] : null, 510 ) 489 511 ); 490 491 492 512 493 513 $response = wp_remote_post( … … 498 518 'Accept' => 'application/json', 499 519 ), 500 'body' => wp_json_encode( 501 array( 502 'license_key' => $license_key, 503 'domain' => $context['site_data']['domain'], 504 'site_data' => array( 505 'homepage_content' => $context['site_data']['homepage_content'], 506 'site_description' => $context['site_data']['site_description'], 507 ), 508 'posts' => $posts_for_api, 509 // Include aggregated metadata for richer context on the premium side 510 'post_types' => $context['postTypes'], 511 'taxonomies' => $context['taxonomies'], 512 'customContext' => isset( $context['customContext'] ) ? $context['customContext'] : null, 513 ) 514 ), 515 'timeout' => 60, // Longer timeout for full context update 520 'body' => $partial_body, 521 'timeout' => 60, 516 522 ) 517 523 ); 518 524 519 // Log response details 520 if ( is_wp_error( $response ) ) { 521 522 } else { 523 $status_code = wp_remote_retrieve_response_code( $response ); 524 $headers = wp_remote_retrieve_headers( $response ); 525 526 $body = wp_remote_retrieve_body( $response ); 527 528 $data = json_decode( $body, true ); 529 } 530 531 if ( ! is_wp_error( $response ) ) { 532 $status_code = wp_remote_retrieve_response_code( $response ); 533 if ( $status_code === 200 ) { 534 break; // Success, exit retry loop 535 } 536 if ( $status_code !== 503 && $status_code !== 404 ) { 537 break; // Don't retry on non-503/404 errors 538 } 539 } 540 } 541 542 if ( is_wp_error( $response ) ) { 543 return new WP_Error( 'api_error', 'Failed to update context: ' . $response->get_error_message() ); 544 } 525 if ( is_wp_error( $response ) ) { 526 $partial_errors[] = array( 527 'chunk' => $chunk_index + 1, 528 'total' => $total_chunks, 529 'message' => $response->get_error_message(), 530 'status' => null, 531 ); 532 continue; 533 } 534 535 $status_code = wp_remote_retrieve_response_code( $response ); 536 if ( $status_code !== 200 ) { 537 $body_err = wp_remote_retrieve_body( $response ); 538 $data_err = json_decode( $body_err, true ); 539 $error_detail = ( $data_err && isset( $data_err['error'] ) ) ? $data_err['error'] : 'Server returned status code: ' . $status_code; 540 $partial_errors[] = array( 541 'chunk' => $chunk_index + 1, 542 'total' => $total_chunks, 543 'message' => $error_detail, 544 'status' => $status_code, 545 ); 546 continue; 547 } 548 549 $successful_chunks++; 550 } 551 552 // Final prune request with IDs only 553 $prune_body = wp_json_encode( 554 array( 555 'license_key' => $license_key, 556 'domain' => $context['site_data']['domain'], 557 'present_post_ids' => $present_post_ids, 558 ) 559 ); 560 561 $response = wp_remote_post( 562 'https://saiap.gopurposego.com/api/context/update', 563 array( 564 'headers' => array( 565 'Content-Type' => 'application/json', 566 'Accept' => 'application/json', 567 ), 568 'body' => $prune_body, 569 'timeout' => 60, 570 ) 571 ); 572 573 if ( is_wp_error( $response ) ) { 574 $aggregate_note = ''; 575 if ( ! empty( $partial_errors ) ) { 576 $aggregate_note = ' Partial errors: ' . wp_json_encode( $partial_errors ); 577 } 578 return new WP_Error( 'api_error', 'Failed to finalize context update: ' . $response->get_error_message() . $aggregate_note ); 579 } 545 580 546 581 $status_code = wp_remote_retrieve_response_code( $response ); … … 548 583 $data = json_decode( $body, true ); 549 584 550 if ( $status_code !== 200 ) { 551 $error_message = 'Failed to update context. '; 552 if ( $data && isset( $data['error'] ) ) { 553 $error_message .= $data['error']; 554 } else { 555 $error_message .= 'Server returned status code: ' . $status_code; 556 } 557 return new WP_Error( 'api_error', $error_message ); 558 } 585 if ( $status_code !== 200 ) { 586 $error_message = 'Failed to finalize context update. '; 587 if ( $data && isset( $data['error'] ) ) { 588 $error_message .= $data['error']; 589 } else { 590 $error_message .= 'Server returned status code: ' . $status_code; 591 } 592 if ( ! empty( $partial_errors ) ) { 593 $error_message .= ' Partial errors: ' . wp_json_encode( $partial_errors ); 594 } 595 return new WP_Error( 'api_error', $error_message ); 596 } 597 598 // If all chunks failed but prune succeeded, surface aggregated error 599 if ( $successful_chunks === 0 && $total_chunks > 0 ) { 600 return new WP_Error( 'api_error', 'Failed to update context: all ' . $total_chunks . ' chunk(s) failed. Details: ' . wp_json_encode( $partial_errors ) ); 601 } 559 602 560 603 // Store the last update timestamp … … 571 614 572 615 // Set appropriate message based on changes and failures 573 if ( ! $has_changes ) {616 if ( ! $has_changes ) { 574 617 $message = 'No changes detected. Site context remains the same.'; 575 618 } else { 576 $message = 'Site context updated successfully.';577 578 if ( isset( $data['syncResult'] ) && isset( $data['syncResult']['failedCount'] ) && $data['syncResult']['failedCount'] > 0 ) {619 $message = 'Site context updated successfully.'; 620 621 if ( isset( $data['syncResult'] ) && isset( $data['syncResult']['failedCount'] ) && $data['syncResult']['failedCount'] > 0 ) { 579 622 $has_failures = true; 580 623 $message .= ' However, ' . $data['syncResult']['failedCount'] . ' posts failed to sync.'; … … 582 625 } 583 626 627 // Reflect any transport-level chunk failures in the flags/message 628 if ( ! empty( $partial_errors ) ) { 629 $has_failures = true; 630 $message .= ' Some chunks failed during upload.'; 631 } 632 584 633 // Update cache if context is in the response 585 634 if ( isset( $data['context'] ) ) { … … 587 636 } 588 637 589 return array(638 return array( 590 639 'message' => $message, 591 640 'has_failures' => $has_failures, … … 593 642 'sync_result' => isset( $data['syncResult'] ) ? $data['syncResult'] : null, 594 643 'timestamp' => $timestamp, 644 'partial_errors' => ! empty( $partial_errors ) ? $partial_errors : null, 595 645 ); 596 646 } -
clearpost-simple-ai-auto-post/trunk/readme.txt
r3387025 r3390455 4 4 Requires at least: 5.0 5 5 Tested up to: 6.8 6 Stable tag: 1.2. 06 Stable tag: 1.2.2 7 7 Requires PHP: 7.2 8 8 License: GPLv2 or later -
clearpost-simple-ai-auto-post/trunk/simple-ai-auto-post.php
r3387025 r3390455 4 4 Description: Your AI Agent for SEO, in WordPress. An AI content marketer that knows your site, then schedules and generates posts every day. 5 5 Plugin URI: https://clearpostplugin.com/ 6 Version: 1.2. 06 Version: 1.2.2 7 7 License: GPLv2 or later 8 8 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 18 18 19 19 // Define plugin version 20 define( 'SAIAP_VERSION', '1.2. 0' );20 define( 'SAIAP_VERSION', '1.2.2' ); 21 21 22 22 // Optionally enable Demo Mode (for internal testing only)
Note: See TracChangeset
for help on using the changeset viewer.