| @@ -181,11 +181,9 @@ | ||
| 181 | 181 | // Check if this is truly manual content (no URL at all) vs a real URL that filter_var rejects |
| 182 | 182 | // filter_var(FILTER_VALIDATE_URL) rejects valid URLs with encoded chars, non-ASCII, fragments, etc. |
| 183 | 183 | // Use a looser check: if it starts with http(s):// or has a scheme, it's a URL |
| 184 | 184 | $has_url_scheme = !empty($source_url) && preg_match('#^https?://#i', $source_url); |
| 185 | - // Treat legacy mxchat.ai source URLs as manual — old bug assigned the site URL to manual entries | |
| 186 | - $is_legacy_mxchat_url = $has_url_scheme && strpos($source_url, 'mxchat.ai') !== false; | |
| 187 | - $is_manual_content = empty($source_url) || $source_url === '' || !$has_url_scheme || $is_legacy_mxchat_url; | |
| 185 | + $is_manual_content = empty($source_url) || $source_url === '' || !$has_url_scheme; | |
| 188 | 186 | |
| 189 | 187 | if ($is_manual_content) { |
| 190 | 188 | // Generate unique identifier for manual content to prevent overwrites |
| 191 | 189 | $source_url = 'mxchat://manual-content/' . time() . '-' . wp_generate_password(8, false); |
| @@ -804,34 +802,31 @@ | ||
| 804 | 802 | |
| 805 | 803 | // Add the original single-vector ID (for non-chunked content) |
| 806 | 804 | $vectors_to_delete[] = $base_vector_id; |
| 807 | 805 | |
| 808 | - // Pinecone /vectors/list is a GET endpoint with query-string parameters; a POST here returns a | |
| 809 | - // non-200 silently and we end up only deleting the base vector, leaving chunks orphaned. | |
| 810 | - $query_params = array( | |
| 806 | + // Use Pinecone list API to find all chunk vectors with this prefix | |
| 807 | + $list_url = "https://{$host}/vectors/list"; | |
| 808 | + | |
| 809 | + $list_body = array( | |
| 811 | 810 | 'prefix' => $base_vector_id . '_chunk_', |
| 812 | - 'limit' => 100, | |
| 811 | + 'limit' => 100 | |
| 813 | 812 | ); |
| 813 | + | |
| 814 | 814 | if (!empty($namespace)) { |
| 815 | - $query_params['namespace'] = $namespace; | |
| 815 | + $list_body['namespace'] = $namespace; | |
| 816 | 816 | } |
| 817 | 817 | |
| 818 | - $list_url = "https://{$host}/vectors/list?" . http_build_query($query_params); | |
| 818 | + $list_response = wp_remote_post($list_url, array( | |
| 819 | + 'headers' => array( | |
| 820 | + 'Api-Key' => $api_key, | |
| 821 | + 'accept' => 'application/json', | |
| 822 | + 'content-type' => 'application/json' | |
| 823 | + ), | |
| 824 | + 'body' => wp_json_encode($list_body), | |
| 825 | + 'timeout' => 30 | |
| 826 | + )); | |
| 819 | 827 | |
| 820 | - // Paginate in case a URL has more than 100 chunks. | |
| 821 | - do { | |
| 822 | - $list_response = wp_remote_get($list_url, array( | |
| 823 | - 'headers' => array( | |
| 824 | - 'Api-Key' => $api_key, | |
| 825 | - 'accept' => 'application/json', | |
| 826 | - ), | |
| 827 | - 'timeout' => 30, | |
| 828 | - )); | |
| 829 | - | |
| 830 | - if (is_wp_error($list_response) || wp_remote_retrieve_response_code($list_response) !== 200) { | |
| 831 | - break; | |
| 832 | - } | |
| 833 | - | |
| 828 | + if (!is_wp_error($list_response)) { | |
| 834 | 829 | $list_data = json_decode(wp_remote_retrieve_body($list_response), true); |
| 835 | 830 | if (!empty($list_data['vectors'])) { |
| 836 | 831 | foreach ($list_data['vectors'] as $vector) { |
| 837 | 832 | if (isset($vector['id'])) { |
| @@ -838,17 +833,9 @@ | ||
| 838 | 833 | $vectors_to_delete[] = $vector['id']; |
| 839 | 834 | } |
| 840 | 835 | } |
| 841 | 836 | } |
| 842 | - | |
| 843 | - $next_token = $list_data['pagination']['next'] ?? ''; | |
| 844 | - if (empty($next_token)) { | |
| 845 | - break; | |
| 846 | - } | |
| 847 | - | |
| 848 | - $query_params['paginationToken'] = $next_token; | |
| 849 | - $list_url = "https://{$host}/vectors/list?" . http_build_query($query_params); | |
| 850 | - } while (true); | |
| 837 | + } | |
| 851 | 838 | |
| 852 | 839 | if (empty($vectors_to_delete)) { |
| 853 | 840 | //error_log('[MXCHAT-CHUNK-DELETE] No vectors found to delete'); |
| 854 | 841 | return true; |