Perplexity MAX

Free Max & Pro features for Perplexity.ai with enhanced capabilities

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

Bạn sẽ cần cài đặt một tiện ích mở rộng như Tampermonkey hoặc Violentmonkey để cài đặt kịch bản này.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)


    // ==UserScript==
    // @name         Perplexity MAX
    // @description  Free Max & Pro features for Perplexity.ai with enhanced capabilities
    // @version      2.1.0
    // @author       AntiKeks & d4nc3r
    // @license      MIT
    // @match        https://*.perplexity.ai/*
    // @run-at       document-start
    // @grant        none
    // @namespace    https://greasyfork.org/users/1497368
    // @supportURL   https://github.com/AntiKeks/PerplexityMAX/issues
    // @homepageURL  https://github.com/AntiKeks/PerplexityMAX
    // ==/UserScript==

    (function () {
      'use strict';

      /* ─────────────────────────── LOGGING ─────────────────────────── */
      const DEBUG = true;  // Enable debug logging for troubleshooting
      const VERBOSE = false; // Disable verbose logging to improve performance
      const log = (...args) => DEBUG && console.log('[PERPLEXITY-MAX]', ...args);
      const verbose = (...args) => VERBOSE && console.log('[PERPLEXITY-MAX-VERBOSE]', ...args);

      /* ─────────────────────────── CACHING ─────────────────────────── */
      // Cache for API responses to improve performance
      const CACHE_TTL = 60 * 1000; // 1 minute cache lifetime
      const responseCache = new Map();

      // Cache helper functions
      const getCachedResponse = (url) => {
        const cachedItem = responseCache.get(url);
        if (cachedItem && Date.now() - cachedItem.timestamp < CACHE_TTL) {
          verbose(`Using cached response for ${url}`);
          return cachedItem.data;
        }
        return null;
      };

      const setCachedResponse = (url, data) => {
        responseCache.set(url, {
          data: data,
          timestamp: Date.now()
        });
        verbose(`Cached response for ${url}`);
      };

      // Cache cleanup interval
      setInterval(() => {
        const now = Date.now();
        let expiredCount = 0;
        responseCache.forEach((value, key) => {
          if (now - value.timestamp > CACHE_TTL) {
            responseCache.delete(key);
            expiredCount++;
          }
        });
        if (expiredCount > 0) {
          verbose(`Cleaned up ${expiredCount} expired cache items`);
        }
      }, CACHE_TTL);

      log('Initialization complete - MAX features activated');

      /* ───────────────────────── THROTTLING UI ────────────────────── */
      const COOLDOWN = 1000;              // Minimum interval between React "pings" (ms)
      let lastUpdate = 0;

      function forceReactUpdate() {
        const now = Date.now();
        if (now - lastUpdate < COOLDOWN) return;   // call no more than once per COOLDOWN
        lastUpdate = now;

        requestAnimationFrame(() => {
          document.dispatchEvent(new Event('visibilitychange'));
          window.dispatchEvent(new Event('resize'));
          log('Dispatched events to update UI');
        });
      }

      /* ─────────────────────── PATCH USER DATA ───────────────── */
      function patchDataRecursively(obj, path = '', depth = 0) {
        // Limit recursion depth to avoid performance issues
        if (depth > 5) return false;

        // Skip null, non-objects, and React elements
        if (!obj || typeof obj !== 'object' || obj.$$typeof) return false;

        let changed = false;

        // Check for subscription-related fields directly
        if (obj.hasOwnProperty('subscription_tier') && obj.subscription_tier !== 'max') {
          obj.subscription_tier = 'max';
          changed = true;
          log(`${path}.subscription_tier → max (was: ${obj.subscription_tier})`);
        }

        if (obj.hasOwnProperty('subscription_source') && obj.subscription_source !== 'stripe') {
          const oldValue = obj.subscription_source;
          obj.subscription_source = 'stripe';
          changed = true;
          log(`${path}.subscription_source → stripe (was: ${oldValue})`);
        }

        if (obj.hasOwnProperty('subscription_status') && obj.subscription_status !== 'active') {
          const oldValue = obj.subscription_status;
          obj.subscription_status = 'active';
          changed = true;
          log(`${path}.subscription_status → active (was: ${oldValue})`);
        }

        // Handle pro/max flags - IMPORTANT: For MAX to show, we need both is_pro=true AND is_max=true
        if (obj.hasOwnProperty('is_pro')) {
          const oldValue = obj.is_pro;
          obj.is_pro = true;  // Set to true for MAX to work properly
          if (oldValue !== true) {
            changed = true;
            log(`${path}.is_pro → true (was: ${oldValue})`);
          }
        }

        if (obj.hasOwnProperty('is_max')) {
          if (obj.is_max !== true) {
            obj.is_max = true;
            changed = true;
            log(`${path}.is_max → true`);
          }
        }

        if (obj.hasOwnProperty('has_max')) {
          if (obj.has_max !== true) {
            obj.has_max = true;
            changed = true;
            log(`${path}.has_max → true`);
          }
        }

        // Also handle has_pro flag
        if (obj.hasOwnProperty('has_pro')) {
          if (obj.has_pro !== true) {
            obj.has_pro = true;
            changed = true;
            log(`${path}.has_pro → true`);
          }
        }

        // Handle rate limits directly - very important!
        if (obj.hasOwnProperty('remaining_pro') && obj.remaining_pro !== 999999) {
          obj.remaining_pro = 999999;
          changed = true;
          log(`${path}.remaining_pro → 999999 (unlimited)`);
        }

        if (obj.hasOwnProperty('remaining_research') && obj.remaining_research !== 999999) {
          obj.remaining_research = 999999;
          changed = true;
          log(`${path}.remaining_research → 999999 (unlimited)`);
        }

        if (obj.hasOwnProperty('remaining_labs') && obj.remaining_labs !== 999999) {
          obj.remaining_labs = 999999;
          changed = true;
          log(`${path}.remaining_labs → 999999 (unlimited)`);
        }

        // Handle upload-related fields
        if (obj.hasOwnProperty('rate_limited') && obj.rate_limited !== false) {
          obj.rate_limited = false;
          changed = true;
          log(`${path}.rate_limited → false (enabling uploads)`);
        }

        if (obj.hasOwnProperty('remaining_uploads') && obj.remaining_uploads !== 999999) {
          obj.remaining_uploads = 999999;
          changed = true;
          log(`${path}.remaining_uploads → 999999 (unlimited)`);
        }

        if (obj.hasOwnProperty('max_uploads') && obj.max_uploads < 100) {
          obj.max_uploads = 100;
          changed = true;
          log(`${path}.max_uploads → 100`);
        }

        if (obj.hasOwnProperty('upload_limit') && obj.upload_limit < 100) {
          obj.upload_limit = 100;
          changed = true;
          log(`${path}.upload_limit → 100`);
        }

        if (obj.hasOwnProperty('can_upload') && obj.can_upload !== true) {
          obj.can_upload = true;
          changed = true;
          log(`${path}.can_upload → true`);
        }

        // Only process important objects further
        if (obj.hasOwnProperty('subscription') && typeof obj.subscription === 'object' && obj.subscription !== null) {
          if (!obj.subscription) {
            obj.subscription = {
              tier: 'max',
              status: 'active',
              source: 'stripe',
              price: 200,
              billing_period: 'monthly'
            };
            changed = true;
            log(`${path}.subscription created with MAX tier`);
          } else {
            if (obj.subscription.tier !== 'max') {
              obj.subscription.tier = 'max';
              changed = true;
            }
            if (obj.subscription.status !== 'active') {
              obj.subscription.status = 'active';
              changed = true;
            }
            if (obj.subscription.source !== 'stripe') {
              obj.subscription.source = 'stripe';
              changed = true;
            }
          }
        }

        // Handle features object
        if (obj.hasOwnProperty('features') && typeof obj.features === 'object' && obj.features !== null) {
          const featuresToEnable = {
            max_models: true,
            claude_opus_access: true,
            claude_sonnet_access: true,
            claude_haiku_access: true,
            gpt_4o_access: true,
            gpt_4_turbo_access: true,
            mistral_large_access: true,
            unlimited_searches: true,
            unlimited_uploads: true,
            unlimited_files: true,
            unlimited_images: true,
            all_models: true,
            image_upload: true,
            file_upload: true,
            pdf_upload: true,
            advanced_tools: true,
            collections_access: true,
            copilot_access: true
          };

          for (const f in featuresToEnable) {
            if (obj.features[f] !== true) {
              obj.features[f] = true;
              changed = true;
            }
          }
        }

        // Recursively process child objects - but only important ones to avoid performance issues
        for (const key in obj) {
          if (Object.prototype.hasOwnProperty.call(obj, key) && typeof obj[key] === 'object' && obj[key] !== null) {
            // Only process important keys to improve performance
            const importantKeys = [
              'user', 'account', 'subscription', 'features', 'settings', 'config',
              'data', 'profile', 'preferences', 'options', 'state', 'models',
              'uploads', 'files', 'images', 'usage'
            ];

            if (importantKeys.includes(key) || key.includes('user') || key.includes('subscription') ||
                key.includes('model') || key.includes('upload') || key.includes('file')) {
              if (patchDataRecursively(obj[key], path ? `${path}.${key}` : key, depth + 1)) {
                changed = true;
              }
            }
          }
        }

        return changed;
      }

      /* ──────────────────── PATCH GLOBAL JSON.parse ───────────────── */
      const originalParse = JSON.parse;
      JSON.parse = function (text, reviver) {
        const data = originalParse.call(this, text, reviver);

        if (patchDataRecursively(data)) {
          log('JSON-object converted to Max');
          forceReactUpdate();
        }
        return data;
      };

      /* ──────────────────────────── PATCH fetch ─────────────────────── */
      const originalFetch = window.fetch;
      window.fetch = async function (input, init) {
        try {
          // Extract URL and method
          const url = typeof input === 'string' ? input : input.url;
          const method = init?.method || 'GET';

          // Log all requests in debug mode
          if (DEBUG) {
            verbose(`Fetch request: ${method} ${url}`);
          }

          // Check if we have a cached response for GET requests
          if (method === 'GET' && !url.includes('/rest/sse/')) {
            const cachedResponse = getCachedResponse(url);
            if (cachedResponse) {
              verbose(`Using cached response for ${url}`);
              return new Response(JSON.stringify(cachedResponse), {
                status: 200,
                statusText: 'OK',
                headers: {
                  'Content-Type': 'application/json',
                  'X-Perplexity-Max-Cache': 'HIT'
                }
              });
            }
          }

          // Force logging for important endpoints
          if (url && (
            url.includes('/rest/rate-limit/all') ||
            url.includes('/rest/user/save-settings') ||
            url.includes('/rest/uploads/create_upload_url') ||
            url.includes('/rest/sse/perplexity_ask')
          )) {
            log(`Intercepting important request: ${method} ${url}`);
          }

          // Block Datadog analytics
          if (url && url.includes('datadoghq.com')) {
            log('Blocked Datadog analytics request');
            // Return empty success response
            return new Response(JSON.stringify({ success: true }), {
              status: 200,
              statusText: 'OK',
              headers: {
                'Content-Type': 'application/json'
              }
            });
          }

          // Block other analytics services
          if (url && (
            url.includes('analytics') ||
            url.includes('telemetry') ||
            url.includes('metrics') ||
            url.includes('singular.net') ||
            url.includes('segment.io') ||
            url.includes('mixpanel') ||
            url.includes('facebook.com') ||
            url.includes('fbevents')
          )) {
            log(`Blocked analytics request: ${url}`);
            // Return empty success response
            return new Response(JSON.stringify({ success: true }), {
              status: 200,
              statusText: 'OK',
              headers: {
                'Content-Type': 'application/json'
              }
            });
          }

          // CRITICAL: Handle rate-limit requests - MUST intercept these
          if (url && url.includes('/rest/rate-limit/all')) {
            log(`Intercepted rate-limit request (${method}) - FORCING UNLIMITED LIMITS`);

            // ALWAYS return our custom response with unlimited limits
            const unlimitedResponse = {
              remaining_pro: 999999,
              remaining_research: 999999,
              remaining_labs: 999999,
              remaining_uploads: 999999,
              remaining_copilot: 999999,
              remaining_search: 999999,
              remaining_create: 999999,
              rate_limited: false
            };

            log('Returning unlimited rate limits');

            // Cache this response for future requests
            setCachedResponse(url, unlimitedResponse);

            // Return our custom response directly, bypassing the server
            return new Response(JSON.stringify(unlimitedResponse), {
              status: 200,
              statusText: 'OK',
              headers: {
                'Content-Type': 'application/json'
              }
            });
          }

          // Handle SSE requests for perplexity_ask
          if (url && url.includes('/rest/sse/perplexity_ask')) {
            log(`Intercepted SSE perplexity_ask request (${method})`);

            try {
              // Get the original request body
              let requestBody = {};
              if (init && init.body) {
                if (typeof init.body === 'string') {
                  try {
                    requestBody = JSON.parse(init.body);
                  } catch (parseError) {
                    log(`Error parsing SSE request body: ${parseError.message}`);
                    // Continue with empty request body rather than failing
                    requestBody = {};
                  }
                }
              }

              // Save original request for retry purposes
              const originalRequest = {
                url,
                method,
                headers: init?.headers ? new Headers(init.headers) : new Headers(),
                body: init?.body
              };

              // Modify params to ensure MAX features
              if (requestBody.params) {
                // Enable MAX model options with support for latest models
                const latestModels = {
                  'claude': 'claude-3-opus-20240229',
                  'gpt': 'gpt-4o',
                  'mistral': 'mistral-large-2'
                };
                requestBody.params.model_preference = requestBody.params.model_preference || latestModels.claude;

                // Add MAX subscription flags
                requestBody.params.is_max = true;
                requestBody.params.has_max = true;
                requestBody.params.is_pro = true;
                requestBody.params.subscription_tier = 'max';

                // Set to use the best model available based on type
                if (!requestBody.params.model_preference || requestBody.params.model_preference === 'turbo') {
                  const preferredModel = latestModels.claude;
                  requestBody.params.model_preference = preferredModel;
                  log(`Enhanced model to ${preferredModel}`);
                }

                // Update the request with modified body
                init.body = JSON.stringify(requestBody);
                log('Modified SSE request with MAX subscription data');
              }

              // Make the modified request
              const response = await originalFetch(input, init);

              // For SSE responses, we need to create a custom response that modifies the stream
              if (response.headers.get('content-type')?.includes('text/event-stream')) {
                log('Intercepting SSE response stream');

                const reader = response.body.getReader();
                const stream = new ReadableStream({
                  async start(controller) {
                    try {
                      while (true) {
                        const { done, value } = await reader.read();
                        if (done) {
                          controller.close();
                          break;
                        }

                        // Convert the chunk to text
                        let text = new TextDecoder().decode(value);

                        // Process each event in the chunk
                        const events = text.split('\n\n');
                        let modifiedEvents = [];

                        for (const event of events) {
                          if (!event.trim()) continue;

                          // Check if this is a data event
                          if (event.includes('event: message') && event.includes('data: {')) {
                            try {
                              // Extract the data part
                              const dataMatch = event.match(/data: ({.*})/);
                              if (dataMatch && dataMatch[1]) {
                                const data = JSON.parse(dataMatch[1]);

                                // Modify the data to ensure MAX features
                                data.gpt4 = true; // Enable GPT-4 flag
                                data.display_model = data.display_model || 'claude-3-opus-20240229'; // Set display model to MAX

                                // If there's a classifier_results object, modify it
                                if (data.classifier_results) {
                                  data.classifier_results.personal_search = true;
                                  data.classifier_results.skip_search = false;
                                }

                                // If there's a telemetry_data object, modify it
                                if (data.telemetry_data) {
                                  data.telemetry_data.is_pro = true;
                                  data.telemetry_data.is_max = true;
                                  data.telemetry_data.has_max = true;
                                }

                                // Replace the data in the event
                                const modifiedEvent = event.replace(dataMatch[1], JSON.stringify(data));
                                modifiedEvents.push(modifiedEvent);
                                continue;
                              }
                            } catch (e) {
                              verbose('Error modifying SSE event:', e);
                            }
                          }

                          // If we couldn't modify the event, keep it as is
                          modifiedEvents.push(event);
                        }

                        // Join the events back together
                        const modifiedText = modifiedEvents.join('\n\n') + '\n\n';
                        controller.enqueue(new TextEncoder().encode(modifiedText));
                      }
                    } catch (e) {
                      log('Error in SSE stream processing:', e);
                      controller.error(e);
                    }
                  }
                });

                // Return a new response with the modified stream
                return new Response(stream, {
                  headers: response.headers,
                  status: response.status,
                  statusText: response.statusText
                });
              }

              return response;
            } catch (e) {
              log('Error processing SSE request:', e);

              // Implement retry mechanism for SSE requests
              const MAX_RETRIES = 3;
              const RETRY_DELAY = 1000; // 1 second

              // Function to retry the request with exponential backoff
              const retryRequest = async (retryCount = 0) => {
                if (retryCount >= MAX_RETRIES) {
                  log(`Maximum retries (${MAX_RETRIES}) reached for SSE request, giving up`);
                  // If we've reached max retries, proceed with the original request as fallback
                  return originalFetch(input, init);
                }

                log(`Retrying SSE request (attempt ${retryCount + 1}/${MAX_RETRIES}) after ${RETRY_DELAY * Math.pow(2, retryCount)}ms`);

                // Wait with exponential backoff
                await new Promise(resolve => setTimeout(resolve, RETRY_DELAY * Math.pow(2, retryCount)));

                try {
                  // Clone the original request but create a new AbortController
                  const newInit = { ...init };
                  if (init?.signal) {
                    const controller = new AbortController();
                    newInit.signal = controller.signal;
                  }

                  return await originalFetch(input, newInit);
                } catch (retryError) {
                  log(`Retry attempt ${retryCount + 1} failed:`, retryError);
                  // Try again with increased retry count
                  return retryRequest(retryCount + 1);
                }
              };

              // Start the retry process
              return retryRequest();
            }
          }

          // Handle upload URL creation requests
          if (url && url.includes('/rest/uploads/create_upload_url')) {
            log('Intercepted upload URL creation request');

            // Make the original request
            const response = await originalFetch(input, init);

            try {
              // Clone the response so we can read and modify it
              const cloned = response.clone();
              const json = await cloned.json();

              // Remove rate limiting for uploads
              if (json.hasOwnProperty('rate_limited')) {
                json.rate_limited = false;
                log('.rate_limited → false (enabling uploads)');

                // Return the modified response
                return new Response(JSON.stringify(json), {
                  status: response.status,
                  statusText: response.statusText,
                  headers: response.headers
                });
              }

              // If we didn't modify anything, return the original response
              return response;
            } catch (e) {
              log('Error processing upload URL response:', e);
              // Not JSON or other error - return original response
              return response;
            }
          }

          // Handle feedback visibility requests
          if (url && url.includes('/rest/entry/should-show-feedback')) {
            log('Intercepted feedback visibility request');

            // Create a modified response that always sets should_show_feedback to true
            return new Response(JSON.stringify({
              should_show_feedback: true
            }), {
              status: 200,
              statusText: 'OK',
              headers: {
                'Content-Type': 'application/json'
              }
            });
          }

          // Handle save-settings requests
          if (url && url.includes('/rest/user/save-settings')) {
            log(`Intercepted save-settings request (${method})`);

            // For GET requests, we'll handle the response below
            if (method === 'GET') {
              const response = await originalFetch(input, init);
              try {
                const cloned = response.clone();
                const json = await cloned.json();

                // Modify the settings to ensure MAX subscription
                json.subscription_tier = 'max';
                json.subscription_status = 'active';
                json.subscription_source = 'stripe';
                json.stripe_status = 'active';
                json.gpt4_limit = 999999;
                json.pplx_alpha_limit = 999999;
                json.pplx_beta_limit = 999999;
                json.pages_limit = 999999;
                json.upload_limit = 999999;
                json.create_limit = 999999;
                json.article_image_upload_limit = 999999;
                json.max_files_per_user = 999999;
                json.max_files_per_repository = 999999;

                log('Modified GET save-settings response with MAX subscription data');

                // Return the modified response
                return new Response(JSON.stringify(json), {
                  status: response.status,
                  statusText: response.statusText,
                  headers: response.headers
                });
              } catch (e) {
                log('Error processing GET save-settings response:', e);
                return response;
              }
            }

            // For PUT/POST requests, modify both the request and response
            if (method === 'PUT' || method === 'POST') {
              try {
                // Get the original request body
                let requestBody = {};
                if (init && init.body) {
                  if (typeof init.body === 'string') {
                    requestBody = JSON.parse(init.body);
                  } else if (init.body instanceof FormData) {
                    // Handle FormData if needed
                  }
                }

                // Check if this is a partial update with updated_settings
                if (requestBody.updated_settings) {
                  log('Detected partial settings update');

                  // Ensure MAX subscription settings in the updated_settings
                  requestBody.updated_settings.subscription_tier = 'max';
                  requestBody.updated_settings.subscription_status = 'active';
                  requestBody.updated_settings.subscription_source = 'stripe';
                  requestBody.updated_settings.stripe_status = 'active';
                  requestBody.updated_settings.gpt4_limit = 999999;
                  requestBody.updated_settings.pplx_alpha_limit = 999999;
                  requestBody.updated_settings.pplx_beta_limit = 999999;
                  requestBody.updated_settings.pages_limit = 999999;
                  requestBody.updated_settings.upload_limit = 999999;
                  requestBody.updated_settings.create_limit = 999999;
                  requestBody.updated_settings.article_image_upload_limit = 999999;
                  requestBody.updated_settings.max_files_per_user = 999999;
                  requestBody.updated_settings.max_files_per_repository = 999999;
                } else {
                  // Ensure MAX subscription settings in the full settings
                  requestBody.subscription_tier = 'max';
                  requestBody.subscription_status = 'active';
                  requestBody.subscription_source = 'stripe';
                  requestBody.stripe_status = 'active';
                  requestBody.gpt4_limit = 999999;
                  requestBody.pplx_alpha_limit = 999999;
                  requestBody.pplx_beta_limit = 999999;
                  requestBody.pages_limit = 999999;
                  requestBody.upload_limit = 999999;
                  requestBody.create_limit = 999999;
                  requestBody.article_image_upload_limit = 999999;
                  requestBody.max_files_per_user = 999999;
                  requestBody.max_files_per_repository = 999999;
                }

                // Update the request with modified body
                const modifiedInit = {
                  ...init,
                  body: JSON.stringify(requestBody)
                };

                log('Modified save-settings request with MAX subscription data');

                // Make the modified request
                const response = await originalFetch(input, modifiedInit);

                // Also modify the response to ensure MAX settings are returned
                try {
                  const cloned = response.clone();
                  const json = await cloned.json();

                  // Always ensure the response has MAX settings
                  json.subscription_tier = 'max';
                  json.subscription_status = 'active';
                  json.subscription_source = 'stripe';
                  json.stripe_status = 'active';
                  json.gpt4_limit = 999999;
                  json.pplx_alpha_limit = 999999;
                  json.pplx_beta_limit = 999999;
                  json.pages_limit = 999999;
                  json.upload_limit = 999999;
                  json.create_limit = 999999;
                  json.article_image_upload_limit = 999999;
                  json.max_files_per_user = 999999;
                  json.max_files_per_repository = 999999;

                  // Log the modified response for debugging
                  log('Modified PUT/POST save-settings response with MAX subscription data');

                  return new Response(JSON.stringify(json), {
                    status: response.status,
                    statusText: response.statusText,
                    headers: response.headers
                  });
                } catch (e) {
                  // If there's an error processing the response, return the original
                  log('Error modifying save-settings response: ' + e.message);
                  return response;
                }
              } catch (e) {
                log('Error processing save-settings request: ' + e.message);
                // If there's an error, proceed with the original request
                return originalFetch(input, init);
              }
            }
          }

          // For all other requests, proceed normally
          const response = await originalFetch(input, init);

          // Check if the response is JSON and modify it if needed
          try {
            // Check if the response is actually JSON
            const ct = response.headers.get('content-type') || '';
            if (!ct.startsWith('application/json')) return response;

            const cloned = response.clone();
            const json = await cloned.json();

            // Cache successful GET responses that aren't SSE
            if (method === 'GET' && response.ok && !url.includes('/rest/sse/')) {
              setCachedResponse(url, json);
            }

            if (patchDataRecursively(json)) {
              log(`Response modified ← ${url}`);
              forceReactUpdate();

              // Cache the modified response
              if (method === 'GET' && !url.includes('/rest/sse/')) {
                setCachedResponse(url, json);
              }

              return new Response(JSON.stringify(json), {
                status: response.status,
                statusText: response.statusText,
                headers: response.headers
              });
            }
          } catch (e) {
            /* not JSON — ignore */
          }

          return response;
        } catch (e) {
          log('Error in fetch interceptor:', e);
          // If there's a critical error, fall back to original fetch
          return originalFetch(input, init);
        }
      };

      // Also inject the fetch interceptor into the page context
      const injectFetchInterceptor = () => {
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Setting up fetch interceptor');

            const originalFetch = window.fetch;
            window.fetch = async function(input, init) {
              try {
                // Extract URL and method
                const url = typeof input === 'string' ? input : input.url;
                const method = init?.method || 'GET';

                // CRITICAL: Handle rate-limit requests - MUST intercept these
                if (url && url.includes('/rest/rate-limit/all')) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Intercepted rate-limit request - FORCING UNLIMITED LIMITS');

                  // ALWAYS return our custom response with unlimited limits
                  const unlimitedResponse = {
                    remaining_pro: 999999,
                    remaining_research: 999999,
                    remaining_labs: 999999,
                    remaining_uploads: 999999,
                    remaining_copilot: 999999,
                    remaining_search: 999999,
                    remaining_create: 999999,
                    rate_limited: false
                  };

                  // Return our custom response directly, bypassing the server
                  return new Response(JSON.stringify(unlimitedResponse), {
                    status: 200,
                    statusText: 'OK',
                    headers: {
                      'Content-Type': 'application/json'
                    }
                  });
                }

                // Handle save-settings requests
                if (url && url.includes('/rest/user/save-settings')) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Intercepted save-settings request');

                  // For GET requests, we'll handle the response
                  if (method === 'GET') {
                    const response = await originalFetch(input, init);
                    try {
                      const cloned = response.clone();
                      const json = await cloned.json();

                      // Modify the settings to ensure MAX subscription
                      json.subscription_tier = 'max';
                      json.subscription_status = 'active';
                      json.subscription_source = 'stripe';
                      json.stripe_status = 'active';
                      json.gpt4_limit = 999999;
                      json.pplx_alpha_limit = 999999;
                      json.pplx_beta_limit = 999999;
                      json.pages_limit = 999999;
                      json.upload_limit = 999999;
                      json.create_limit = 999999;
                      json.article_image_upload_limit = 999999;
                      json.max_files_per_user = 999999;
                      json.max_files_per_repository = 999999;

                      console.log('[PERPLEXITY-MAX-INJECTED] Modified GET save-settings response');

                      // Return the modified response
                      return new Response(JSON.stringify(json), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                      });
                    } catch (e) {
                      console.error('[PERPLEXITY-MAX-INJECTED] Error processing GET save-settings response:', e);
                      return response;
                    }
                  }
                }

                // For all other requests, proceed normally
                return originalFetch.apply(this, arguments);
              } catch (e) {
                console.error('[PERPLEXITY-MAX-INJECTED] Error in fetch interceptor:', e);
                // If there's a critical error, fall back to original fetch
                return originalFetch.apply(this, arguments);
              }
            };

            console.log('[PERPLEXITY-MAX-INJECTED] Fetch interceptor setup complete');
          })();
        `;

        document.head.appendChild(script);
        document.head.removeChild(script);
      };

      /* ───────────────────── SIMPLIFIED WebSocket HANDLING ──────────────── */
      // This is a simplified version that just logs connections but doesn't modify data
      // This avoids breaking the WebSocket connections
      const originalWebSocket = window.WebSocket;
      window.WebSocket = function(url, protocols) {
        log(`WebSocket connection to ${url}`);
        return new originalWebSocket(url, protocols);
      };

      /* ─────────────── BLOCK ANALYTICS AND TRACKING SCRIPTS ─────────────── */
      function blockAnalyticsScripts() {
        log('Setting up analytics and tracking script blocker');

        // Override XMLHttpRequest to block analytics
        const originalXhrOpen = XMLHttpRequest.prototype.open;
        const originalXhrSend = XMLHttpRequest.prototype.send;
        const originalXhrSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

        // Fix for XMLHttpRequest state issues
        XMLHttpRequest.prototype.open = function(method, url, ...rest) {
          // Store the state and URL for later use
          this._pplxState = 'OPENED';
          this._pplxUrl = url;

          if (typeof url === 'string' && (
            url.includes('datadoghq.com') ||
            url.includes('analytics') ||
            url.includes('telemetry') ||
            url.includes('metrics') ||
            url.includes('singular.net') ||
            url.includes('segment.io') ||
            url.includes('mixpanel') ||
            url.includes('facebook') ||
            url.includes('fbevents')
          )) {
            log(`Blocked XHR analytics request to: ${url}`);
            // Make this XHR do nothing but maintain proper state
            this._pplxBlocked = true;

            // Create a safe version that maintains proper state
            this.setRequestHeader = function(header, value) {
              // Allow setRequestHeader to be called without errors
              if (this._pplxState === 'OPENED') {
                // Just log but don't actually set headers
                verbose(`Blocked setRequestHeader for ${url}: ${header}=${value}`);
                return;
              } else {
                throw new DOMException('XMLHttpRequest.setRequestHeader: XMLHttpRequest state must be OPENED.');
              }
            };

            this.send = function(body) {
              // Change state to prevent further calls
              this._pplxState = 'DONE';

              // Simulate a successful response
              setTimeout(() => {
                if (typeof this.onreadystatechange === 'function') {
                  this.readyState = 4;
                  this.status = 200;
                  this.response = '{"success":true}';
                  this.responseText = '{"success":true}';
                  this.onreadystatechange();
                }

                if (typeof this.onload === 'function') {
                  this.onload();
                }
              }, 10);
            };

            // Still call original open to maintain proper state
            return originalXhrOpen.call(this, method, url, ...rest);
          }

          // For non-blocked requests, proceed normally
          return originalXhrOpen.call(this, method, url, ...rest);
        };

        // Safer setRequestHeader override
        XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
          try {
            // Only proceed if not blocked
            if (!this._pplxBlocked) {
              return originalXhrSetRequestHeader.call(this, header, value);
            } else {
              // For blocked requests, just pretend it worked
              verbose(`Blocked setRequestHeader: ${header}=${value}`);
              return;
            }
          } catch (e) {
            log(`Error in setRequestHeader: ${e.message}`);
            // If there's an error, don't break the page
            return;
          }
        };

        // Safer send override
        XMLHttpRequest.prototype.send = function(body) {
          try {
            // Only proceed if not blocked
            if (!this._pplxBlocked) {
              return originalXhrSend.call(this, body);
            } else {
              // For blocked requests, simulate success
              this._pplxState = 'DONE';
              setTimeout(() => {
                if (typeof this.onreadystatechange === 'function') {
                  this.readyState = 4;
                  this.status = 200;
                  this.response = '{"success":true}';
                  this.responseText = '{"success":true}';
                  this.onreadystatechange();
                }

                if (typeof this.onload === 'function') {
                  this.onload();
                }
              }, 10);
              return;
            }
          } catch (e) {
            log(`Error in send: ${e.message}`);
            // If there's an error, don't break the page
            return;
          }
        };

        // Inject script to block analytics in page context
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Setting up analytics blocker');

            // Block Datadog
            window.DD_RUM = {
              init: function() { console.log('[PERPLEXITY-MAX-INJECTED] Blocked Datadog init'); },
              addTiming: function() {},
              addAction: function() {},
              addError: function() {},
              startSessionReplayRecording: function() {},
              setGlobalContextProperty: function() {}
            };

            // Block other analytics services
            window.ga = function() { console.log('[PERPLEXITY-MAX-INJECTED] Blocked GA call'); };
            window.gtag = function() { console.log('[PERPLEXITY-MAX-INJECTED] Blocked GTM call'); };
            window._paq = { push: function() { console.log('[PERPLEXITY-MAX-INJECTED] Blocked Matomo call'); } };
            window.mixpanel = { track: function() {}, identify: function() {} };
            window.segment = { track: function() {}, identify: function() {} };
            window.amplitude = { track: function() {}, identify: function() {} };

            // Block Facebook Pixel
            window.fbq = function() {
              console.log('[PERPLEXITY-MAX-INJECTED] Blocked Facebook Pixel call');
            };

            // Block Facebook events
            window.FB = window.FB || {};
            window.FB.Event = window.FB.Event || { subscribe: function() {} };
            window.FB.CustomerChat = window.FB.CustomerChat || { hide: function() {}, show: function() {} };

            // Fix XMLHttpRequest issues
            try {
              const originalXhrOpen = XMLHttpRequest.prototype.open;
              const originalXhrSend = XMLHttpRequest.prototype.send;
              const originalXhrSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader;

              XMLHttpRequest.prototype.open = function(method, url, ...rest) {
                // Store state for later use
                this._pplxState = 'OPENED';
                this._pplxUrl = url;

                if (typeof url === 'string' && (
                  url.includes('datadoghq.com') ||
                  url.includes('analytics') ||
                  url.includes('telemetry') ||
                  url.includes('metrics') ||
                  url.includes('singular.net') ||
                  url.includes('segment.io') ||
                  url.includes('mixpanel') ||
                  url.includes('facebook') ||
                  url.includes('fbevents')
                )) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Blocked XHR request:', url);
                  this._pplxBlocked = true;
                  return originalXhrOpen.call(this, method, 'data:text/plain,{}', ...rest);
                }

                return originalXhrOpen.call(this, method, url, ...rest);
              };

              XMLHttpRequest.prototype.setRequestHeader = function(header, value) {
                if (this._pplxBlocked) {
                  // Do nothing for blocked requests
                  return;
                }
                return originalXhrSetRequestHeader.call(this, header, value);
              };

              XMLHttpRequest.prototype.send = function(body) {
                if (this._pplxBlocked) {
                  // Simulate success for blocked requests
                  this._pplxState = 'DONE';
                  setTimeout(() => {
                    if (typeof this.onreadystatechange === 'function') {
                      this.readyState = 4;
                      this.status = 200;
                      this.response = '{"success":true}';
                      this.responseText = '{"success":true}';
                      this.onreadystatechange();
                    }

                    if (typeof this.onload === 'function') {
                      this.onload();
                    }
                  }, 10);
                  return;
                }
                return originalXhrSend.call(this, body);
              };

              console.log('[PERPLEXITY-MAX-INJECTED] XMLHttpRequest patched successfully');
            } catch (e) {
              console.error('[PERPLEXITY-MAX-INJECTED] Failed to patch XMLHttpRequest:', e);
            }

            // Override fetch for analytics
            const originalFetch = window.fetch;
            window.fetch = async function(input, init) {
              const url = typeof input === 'string' ? input : input.url;
              if (url && (
                url.includes('datadoghq.com') ||
                url.includes('analytics') ||
                url.includes('telemetry') ||
                url.includes('metrics') ||
                url.includes('singular.net') ||
                url.includes('segment.io') ||
                url.includes('mixpanel') ||
                url.includes('facebook') ||
                url.includes('fbevents')
              )) {
                console.log('[PERPLEXITY-MAX-INJECTED] Blocked analytics fetch:', url);
                return new Response(JSON.stringify({ success: true }), {
                  status: 200,
                  statusText: 'OK',
                  headers: { 'Content-Type': 'application/json' }
                });
              }
              return originalFetch.apply(this, arguments);
            };

            // Override any analytics-related properties
            Object.defineProperties(window, {
              analytics: {
                get: function() {
                  return {
                    track: function() {},
                    identify: function() {},
                    page: function() {}
                  };
                },
                configurable: true
              },
              dataLayer: {
                get: function() { return []; },
                set: function() {},
                configurable: true
              }
            });

            console.log('[PERPLEXITY-MAX-INJECTED] Analytics blocker setup complete');
          })();
        `;

        document.head.appendChild(script);
        document.head.removeChild(script);
      }

      /* ─────────────────── FORCE MAX SUBSCRIPTION ─────────────────── */
    function forceMaxSubscription() {
      // This function directly modifies subscription data in the DOM
      log('Forcing MAX subscription data');

      // 1. Force window.__NEXT_DATA__ if it exists (this contains initial state)
      try {
        if (window.__NEXT_DATA__ && window.__NEXT_DATA__.props && window.__NEXT_DATA__.props.pageProps) {
          // Force user data
          if (window.__NEXT_DATA__.props.pageProps.user) {
            window.__NEXT_DATA__.props.pageProps.user.subscription_tier = 'max';
            window.__NEXT_DATA__.props.pageProps.user.subscription_status = 'active';
            window.__NEXT_DATA__.props.pageProps.user.subscription_source = 'stripe';
            window.__NEXT_DATA__.props.pageProps.user.is_max = true;
            window.__NEXT_DATA__.props.pageProps.user.has_max = true;
            window.__NEXT_DATA__.props.pageProps.user.is_pro = true;
            log('Forced MAX subscription in __NEXT_DATA__.props.pageProps.user');
          }

          // Force subscription data
          if (window.__NEXT_DATA__.props.pageProps.subscription) {
            window.__NEXT_DATA__.props.pageProps.subscription.tier = 'max';
            window.__NEXT_DATA__.props.pageProps.subscription.status = 'active';
            window.__NEXT_DATA__.props.pageProps.subscription.source = 'stripe';
            log('Forced MAX subscription in __NEXT_DATA__.props.pageProps.subscription');
          }

          // Force rate limits
          if (window.__NEXT_DATA__.props.pageProps.usage) {
            if (window.__NEXT_DATA__.props.pageProps.usage.remaining_pro !== undefined) {
              window.__NEXT_DATA__.props.pageProps.usage.remaining_pro = 999999;
            }
            if (window.__NEXT_DATA__.props.pageProps.usage.remaining_research !== undefined) {
              window.__NEXT_DATA__.props.pageProps.usage.remaining_research = 999999;
            }
            if (window.__NEXT_DATA__.props.pageProps.usage.remaining_labs !== undefined) {
              window.__NEXT_DATA__.props.pageProps.usage.remaining_labs = 999999;
            }
            log('Forced unlimited usage in __NEXT_DATA__');
          }
        }
      } catch (e) {
        log('Error modifying __NEXT_DATA__: ' + e.message);
      }

      // 2. Inject a script to modify React state directly
      const script = document.createElement('script');
      script.textContent = `
        (function() {
          console.log('[PERPLEXITY-MAX-INJECTED] Direct subscription override');

          // Override subscription data in localStorage
          try {
            const storageKeys = ['perplexity-user', 'perplexity-subscription', 'perplexity-usage'];

            storageKeys.forEach(key => {
              const data = localStorage.getItem(key);
              if (data) {
                try {
                  const parsed = JSON.parse(data);

                  if (key === 'perplexity-user') {
                    parsed.subscription_tier = 'max';
                    parsed.subscription_status = 'active';
                    parsed.subscription_source = 'stripe';
                    parsed.is_max = true;
                    parsed.has_max = true;
                    parsed.is_pro = true;
                  }

                  if (key === 'perplexity-subscription') {
                    parsed.tier = 'max';
                    parsed.status = 'active';
                    parsed.source = 'stripe';
                  }

                  if (key === 'perplexity-usage') {
                    if (parsed.remaining_pro !== undefined) parsed.remaining_pro = 999999;
                    if (parsed.remaining_research !== undefined) parsed.remaining_research = 999999;
                    if (parsed.remaining_labs !== undefined) parsed.remaining_labs = 999999;
                  }

                  localStorage.setItem(key, JSON.stringify(parsed));
                  console.log('[PERPLEXITY-MAX-INJECTED] Modified localStorage:', key);
                } catch (e) {
                  console.error('[PERPLEXITY-MAX-INJECTED] Error parsing localStorage:', e);
                }
              }
            });
          } catch (e) {
            console.error('[PERPLEXITY-MAX-INJECTED] Error accessing localStorage:', e);
          }

          // Try to find and modify React state directly
          function modifyReactState() {
            // Look for React fiber nodes
            let rootNode = document.querySelector('#__next');
            if (!rootNode) rootNode = document.querySelector('body > div');

            if (!rootNode) return;

            // Get React internal instance
            let internalInstance = null;

            // React 16+
            if (rootNode._reactRootContainer && rootNode._reactRootContainer._internalRoot) {
              internalInstance = rootNode._reactRootContainer._internalRoot.current;
            }

            // React 17+
            const reactKey = Object.keys(rootNode).find(key =>
              key.startsWith('__reactContainer$') ||
              key.startsWith('__reactFiber$')
            );

            if (reactKey) {
              internalInstance = rootNode[reactKey];
            }

            if (!internalInstance) return;

            // Walk the fiber tree to find subscription data
            function walkFiber(fiber) {
              if (!fiber) return;

              // Check for subscription state
              if (fiber.memoizedState && fiber.memoizedState.memoizedState) {
                const state = fiber.memoizedState.memoizedState;

                // Look for subscription data in state
                if (state.subscription || state.user || state.usage) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Found React state with subscription data');

                  if (state.subscription) {
                    state.subscription.tier = 'max';
                    state.subscription.status = 'active';
                    state.subscription.source = 'stripe';
                  }

                  if (state.user) {
                    state.user.subscription_tier = 'max';
                    state.user.subscription_status = 'active';
                    state.user.subscription_source = 'stripe';
                    state.user.is_max = true;
                    state.user.has_max = true;
                    state.user.is_pro = true;
                  }

                  if (state.usage) {
                    if (state.usage.remaining_pro !== undefined) state.usage.remaining_pro = 999999;
                    if (state.usage.remaining_research !== undefined) state.usage.remaining_research = 999999;
                    if (state.usage.remaining_labs !== undefined) state.usage.remaining_labs = 999999;
                  }

                  // Force update
                  if (fiber.stateNode && typeof fiber.stateNode.forceUpdate === 'function') {
                    fiber.stateNode.forceUpdate();
                  }
                }
              }

              // Walk child fibers
              if (fiber.child) walkFiber(fiber.child);
              if (fiber.sibling) walkFiber(fiber.sibling);
            }

            walkFiber(internalInstance);
          }

          // Run immediately and periodically
          modifyReactState();
          setInterval(modifyReactState, 5000);

          // Also override fetch responses for subscription endpoints
          const originalFetch = window.fetch;
          window.fetch = async function(input, init) {
            const url = typeof input === 'string' ? input : input.url;

            // Check if this is a subscription-related request
            const isSubscriptionRequest = url && (
              url.includes('/api/user') ||
              url.includes('/api/subscription') ||
              url.includes('/api/auth/session')
            );

            if (isSubscriptionRequest) {
              console.log('[PERPLEXITY-MAX-INJECTED] Intercepted subscription request:', url);

              // For session requests, return a modified response
              if (url.includes('/api/auth/session')) {
                return new Response(JSON.stringify({
                  user: {
                    subscription_tier: 'max',
                    subscription_status: 'active',
                    subscription_source: 'stripe',
                    is_max: true,
                    has_max: true,
                    is_pro: true
                  }
                }), {
                  status: 200,
                  headers: { 'Content-Type': 'application/json' }
                });
              }
            }

            // For other requests, proceed normally
            return originalFetch.apply(this, arguments);
          };
        })();
      `;

      document.head.appendChild(script);
      document.head.removeChild(script);

      // 3. Also directly modify any visible plan elements
      const planElements = document.querySelectorAll('[data-plan], [data-tier], [data-subscription]');
      planElements.forEach(element => {
        if (element.getAttribute('data-plan') === 'pro') {
          element.setAttribute('data-plan', 'max');
          log('Changed data-plan from pro to max');
        }

        if (element.getAttribute('data-tier') === 'pro') {
          element.setAttribute('data-tier', 'max');
          log('Changed data-tier from pro to max');
        }

        if (element.getAttribute('data-subscription') === 'pro') {
          element.setAttribute('data-subscription', 'max');
          log('Changed data-subscription from pro to max');
        }
      });

      // 4. Force model selection buttons to be clickable
      const modelButtons = document.querySelectorAll('button[aria-label="Choose a model"], [data-model-selector="true"]');
      modelButtons.forEach(button => {
        // Clone the button to remove all event listeners
        const newButton = button.cloneNode(true);

        // Make sure it's visible and clickable
        newButton.style.display = '';
        newButton.style.visibility = 'visible';
        newButton.style.pointerEvents = 'auto';
        newButton.style.cursor = 'pointer';

        // Remove any disabled attributes
        newButton.removeAttribute('disabled');
        newButton.setAttribute('aria-disabled', 'false');

        // Add a click event listener that will force the dropdown to appear
        newButton.addEventListener('click', () => {
          log('Model button clicked');
        });

        // Replace the original button
        if (button.parentNode) {
          button.parentNode.replaceChild(newButton, button);
          log('Replaced model button with enhanced version');
        }
      });
    }

      /* ─────────────────── ADD STATUS INDICATOR ─────────────────── */
      function addStatusIndicator() {
        // Create a simple status indicator
        const statusDiv = document.createElement('div');
        statusDiv.style.position = 'fixed';
        statusDiv.style.bottom = '20px';
        statusDiv.style.right = '20px';
        statusDiv.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
        statusDiv.style.color = '#00ff9d';
        statusDiv.style.padding = '8px 15px';
        statusDiv.style.borderRadius = '8px';
        statusDiv.style.fontSize = '12px';
        statusDiv.style.fontWeight = 'bold';
        statusDiv.style.zIndex = '9999';
        statusDiv.style.opacity = '0.9';
        statusDiv.style.transition = 'opacity 0.3s, transform 0.3s';
        statusDiv.style.fontFamily = 'Arial, sans-serif';
        statusDiv.style.userSelect = 'none';
        statusDiv.style.boxShadow = '0 2px 10px rgba(0, 255, 157, 0.3)';
        statusDiv.style.cursor = 'pointer';
        statusDiv.style.display = 'flex';
        statusDiv.style.flexDirection = 'column';
        statusDiv.style.gap = '5px';

        // Main title
        const titleDiv = document.createElement('div');
        titleDiv.textContent = 'PERPLEXITY MAX v2.1';
        titleDiv.style.display = 'flex';
        titleDiv.style.alignItems = 'center';
        titleDiv.style.justifyContent = 'space-between';
        titleDiv.style.width = '100%';

        // Status indicator dot
        const statusDot = document.createElement('span');
        statusDot.style.width = '8px';
        statusDot.style.height = '8px';
        statusDot.style.borderRadius = '50%';
        statusDot.style.backgroundColor = '#00ff9d';
        statusDot.style.display = 'inline-block';
        statusDot.style.marginLeft = '8px';
        statusDot.style.boxShadow = '0 0 5px #00ff9d';

        titleDiv.appendChild(statusDot);
        statusDiv.appendChild(titleDiv);

        // Status text
        const statusText = document.createElement('div');
        statusText.textContent = 'All features active';
        statusText.style.fontSize = '10px';
        statusText.style.opacity = '0.8';
        statusDiv.appendChild(statusText);

        // Add to DOM
        document.body.appendChild(statusDiv);

        // Stats container (initially hidden)
        const statsDiv = document.createElement('div');
        statsDiv.style.overflow = 'hidden';
        statsDiv.style.maxHeight = '0';
        statsDiv.style.transition = 'max-height 0.3s ease-out';
        statsDiv.style.fontSize = '10px';
        statsDiv.style.opacity = '0.8';
        statsDiv.style.marginTop = '5px';

        // Add stats content
        statsDiv.innerHTML = `
          <div>Cache size: <span id="pplx-max-cache-size">0</span> items</div>
          <div>Requests intercepted: <span id="pplx-max-requests">0</span></div>
        `;
        statusDiv.appendChild(statsDiv);

        // Counter for intercepted requests
        let interceptedRequests = 0;

        // Update stats periodically
        const updateStats = () => {
          const cacheSize = document.getElementById('pplx-max-cache-size');
          if (cacheSize) cacheSize.textContent = responseCache.size;

          const requestsCount = document.getElementById('pplx-max-requests');
          if (requestsCount) requestsCount.textContent = interceptedRequests;
        };

        // Intercept fetch to count requests
        const originalFetchProxy = window.fetch;
        window.fetch = function(...args) {
          interceptedRequests++;
          updateStats();
          return originalFetchProxy.apply(this, args);
        };

        // Toggle stats visibility on click
        let statsVisible = false;
        statusDiv.addEventListener('click', () => {
          statsVisible = !statsVisible;
          if (statsVisible) {
            statsDiv.style.maxHeight = '100px';
            updateStats();
          } else {
            statsDiv.style.maxHeight = '0';
          }
        });

        // Fade out after 5 seconds, but stay visible on hover
        let fadeTimeout;
        const startFadeOut = () => {
          fadeTimeout = setTimeout(() => {
            statusDiv.style.opacity = '0.3';
          }, 5000);
        };

        statusDiv.addEventListener('mouseenter', () => {
          clearTimeout(fadeTimeout);
          statusDiv.style.opacity = '0.9';
        });

        statusDiv.addEventListener('mouseleave', () => {
          startFadeOut();
        });

        startFadeOut();

        // Add neon author credit
        addNeonAuthorCredit();

        // Return the intercepted requests counter for other functions to use
        return { incrementRequestCount: () => {
          interceptedRequests++;
          updateStats();
        }};
      }

      /* ─────────────────── ADD NEON AUTHOR CREDIT ─────────────────── */
      function addNeonAuthorCredit() {
        // Create wrapper for the neon text
        const neonWrapper = document.createElement('div');
        neonWrapper.style.position = 'fixed';
        neonWrapper.style.bottom = '60px';
        neonWrapper.style.right = '20px';
        neonWrapper.style.zIndex = '9999';
        neonWrapper.style.userSelect = 'none';
        neonWrapper.style.opacity = '0';
        neonWrapper.style.transition = 'opacity 1s ease-in-out';

        // Create the neon text element
        const neonText = document.createElement('div');
        neonText.textContent = 'by AntiKeks & d4nc3r';
        neonText.style.fontFamily = '"Courier New", monospace';
        neonText.style.fontSize = '14px';
        neonText.style.fontWeight = 'bold';
        neonText.style.color = '#fff';
        neonText.style.textShadow = `
          0 0 5px #ff6600,
          0 0 10px #ff6600,
          0 0 15px #ff6600,
          0 0 20px #ff6600,
          0 0 25px #ff6600,
          0 0 30px #ff6600
        `;
        neonText.style.animation = 'neonPulse 1.5s ease-in-out infinite alternate';

        // Create and add the style for the neon pulse animation
        const styleElement = document.createElement('style');
        styleElement.textContent = `
          @keyframes neonPulse {
            from {
              text-shadow:
                0 0 5px #ff6600,
                0 0 10px #ff6600,
                0 0 15px #ff6600,
                0 0 20px #ff6600;
            }
            to {
              text-shadow:
                0 0 5px #ff6600,
                0 0 10px #ff8800,
                0 0 15px #ff8800,
                0 0 20px #ff8800,
                0 0 25px #ff8800,
                0 0 30px #ff8800,
                0 0 35px #ffaa00;
            }
          }

          @keyframes neonFlicker {
            0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% {
              text-shadow:
                0 0 5px #ff6600,
                0 0 10px #ff6600,
                0 0 15px #ff8800,
                0 0 20px #ff8800,
                0 0 25px #ffaa00;
            }
            20%, 24%, 55% {
              text-shadow: none;
            }
          }
        `;
        document.head.appendChild(styleElement);

        // Add the neon text to the wrapper
        neonWrapper.appendChild(neonText);

        // Add the wrapper to the document
        document.body.appendChild(neonWrapper);

        // Fade in after a short delay
        setTimeout(() => {
          neonWrapper.style.opacity = '1';

          // Add flickering effect after it's visible
          setTimeout(() => {
            neonText.style.animation = 'neonFlicker 2s linear 1, neonPulse 1.5s ease-in-out infinite alternate';
          }, 2000);

          // Fade out after 6 seconds
          setTimeout(() => {
            neonWrapper.style.opacity = '0';

            // Remove from DOM after fade out
            setTimeout(() => {
              if (neonWrapper.parentNode) {
                neonWrapper.parentNode.removeChild(neonWrapper);
              }
              if (styleElement.parentNode) {
                styleElement.parentNode.removeChild(styleElement);
              }
            }, 1000);
          }, 6000);
        }, 1000);
      }

      /* ─────────────────── ENABLE UNLIMITED UPLOADS ─────────────────── */
      function enableUnlimitedUploads() {
        log('Enabling unlimited file uploads');

        // Inject a script to modify any upload limits in the page context
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Enabling unlimited uploads');

            // Override any upload limit checks in the page context
            const originalFetch = window.fetch;
            window.fetch = async function(input, init) {
              const url = typeof input === 'string' ? input : input.url;

              // If this is an upload-related request, modify it
              if (url && url.includes('/uploads')) {
                // If there's a body, check for any limit-related fields
                if (init && init.body && typeof init.body === 'string') {
                  try {
                    const body = JSON.parse(init.body);

                    // Remove any limit-related fields
                    if (body.hasOwnProperty('limit')) {
                      body.limit = 999999;
                    }

                    if (body.hasOwnProperty('max_size')) {
                      body.max_size = 1000000000; // 1GB
                    }

                    if (body.hasOwnProperty('max_count')) {
                      body.max_count = 100;
                    }

                    // Update the request body
                    init.body = JSON.stringify(body);
                  } catch (e) {
                    // Not JSON - ignore
                  }
                }
              }

              return originalFetch.apply(this, arguments);
            };

            // Advanced fix for FormData.append issues
            try {
              // Store the original method
              const originalFormDataAppend = FormData.prototype.append;

              // Create a safer version that handles all edge cases
              FormData.prototype.append = function(name, value, filename) {
                // Handle the case when name is not a string
                if (typeof name !== 'string') {
                  try {
                    name = String(name);
                  } catch (e) {
                    name = 'unnamed';
                    console.warn('[PERPLEXITY-MAX-INJECTED] FormData.append: Invalid name parameter');
                  }
                }

                // Handle null or undefined values
                if (value === null || value === undefined) {
                  console.log('[PERPLEXITY-MAX-INJECTED] FormData.append: Converting null/undefined to empty string');
                  try {
                    return originalFormDataAppend.call(this, name, '', filename);
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] FormData.append failed with empty string:', e);
                    return; // Silently fail rather than breaking the page
                  }
                }

                // Handle File and Blob objects properly
                if (value instanceof File || value instanceof Blob) {
                  try {
                    return originalFormDataAppend.call(this, name, value, filename);
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] FormData.append failed with File/Blob:', e);
                    return; // Silently fail rather than breaking the page
                  }
                }

                // Handle string values
                if (typeof value === 'string') {
                  try {
                    return originalFormDataAppend.call(this, name, value, filename);
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] FormData.append failed with string:', e);
                    return; // Silently fail rather than breaking the page
                  }
                }

                // For objects, try to stringify them
                if (typeof value === 'object') {
                  try {
                    // Try to convert to a Blob first if it has certain properties
                    if (value.type && (value.size !== undefined || value.length !== undefined)) {
                      try {
                        const blob = new Blob([value], { type: value.type || 'application/octet-stream' });
                        return originalFormDataAppend.call(this, name, blob, filename || value.name);
                      } catch (blobError) {
                        console.warn('[PERPLEXITY-MAX-INJECTED] Failed to convert to Blob:', blobError);
                        // Fall through to JSON stringify
                      }
                    }

                    // Try JSON stringify
                    const jsonString = JSON.stringify(value);
                    return originalFormDataAppend.call(this, name, jsonString, filename);
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] FormData.append failed with object:', e);
                    try {
                      return originalFormDataAppend.call(this, name, '[object Object]', filename);
                    } catch (e2) {
                      console.error('[PERPLEXITY-MAX-INJECTED] FormData.append fallback failed:', e2);
                      return; // Silently fail rather than breaking the page
                    }
                  }
                }

                // For everything else, convert to string
                try {
                  const stringValue = String(value);
                  return originalFormDataAppend.call(this, name, stringValue, filename);
                } catch (e) {
                  console.error('[PERPLEXITY-MAX-INJECTED] FormData.append string conversion failed:', e);
                  return; // Silently fail rather than breaking the page
                }
              };

              console.log('[PERPLEXITY-MAX-INJECTED] FormData.append successfully patched');
            } catch (e) {
              console.error('[PERPLEXITY-MAX-INJECTED] Failed to patch FormData.append:', e);
            }

            // Block Facebook Pixel and other tracking scripts
            try {
              // Create dummy Facebook Pixel functions
              window.fbq = function() {
                console.log('[PERPLEXITY-MAX-INJECTED] Blocked Facebook Pixel call');
              };

              // Block Facebook events
              window.FB = window.FB || {};
              window.FB.Event = window.FB.Event || { subscribe: function() {} };
              window.FB.CustomerChat = window.FB.CustomerChat || { hide: function() {}, show: function() {} };

              console.log('[PERPLEXITY-MAX-INJECTED] Facebook tracking scripts blocked');
            } catch (e) {
              console.error('[PERPLEXITY-MAX-INJECTED] Failed to block Facebook tracking:', e);
            }

            // Also try to find and modify any upload limit variables in the page
            function overrideUploadLimits() {
              // Look for common variable names related to upload limits
              const globalVars = [
                'MAX_UPLOADS', 'MAX_UPLOAD_COUNT', 'UPLOAD_LIMIT',
                'MAX_UPLOAD_SIZE', 'FILE_UPLOAD_LIMIT', 'UPLOAD_MAX_FILES'
              ];

              globalVars.forEach(varName => {
                if (window[varName] !== undefined) {
                  if (typeof window[varName] === 'number') {
                    window[varName] = 999999;
                    console.log('[PERPLEXITY-MAX-INJECTED] Overrode global upload limit:', varName);
                  }
                }
              });

              // Also look for common object properties related to upload limits
              const objects = ['config', 'settings', 'options', 'limits', 'uploadConfig'];
              const properties = ['maxUploads', 'maxUploadSize', 'uploadLimit', 'fileLimit', 'maxFiles'];

              objects.forEach(objName => {
                if (window[objName]) {
                  properties.forEach(prop => {
                    if (window[objName][prop] !== undefined && typeof window[objName][prop] === 'number') {
                      window[objName][prop] = 999999;
                      console.log('[PERPLEXITY-MAX-INJECTED] Overrode upload limit:', objName + '.' + prop);
                    }
                  });
                }
              });
            }

            // Run immediately and periodically
            overrideUploadLimits();
            setInterval(overrideUploadLimits, 5000);
          })();
        `;

        document.head.appendChild(script);
        document.head.removeChild(script);

        // Set up tracking system for upload requests
        setupUploadTracking();
      }

      /* ─────────────────── AUTO-SAVE SESSIONS ─────────────────── */
      function setupAutoSave() {
        log('Setting up auto-save functionality');

        // Create a script to handle auto-saving
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Setting up auto-save functionality');

            // Storage key for saved sessions
            const STORAGE_KEY = 'pplx-max-saved-sessions';

            // Maximum number of saved sessions
            const MAX_SAVED_SESSIONS = 50;

            // Get saved sessions from localStorage
            const getSavedSessions = () => {
              try {
                const sessions = localStorage.getItem(STORAGE_KEY);
                return sessions ? JSON.parse(sessions) : [];
              } catch (e) {
                console.error('[PERPLEXITY-MAX-INJECTED] Error loading saved sessions:', e);
                return [];
              }
            };

            // Save sessions to localStorage
            const saveSessions = (sessions) => {
              try {
                localStorage.setItem(STORAGE_KEY, JSON.stringify(sessions));
              } catch (e) {
                console.error('[PERPLEXITY-MAX-INJECTED] Error saving sessions:', e);
              }
            };

            // Function to extract conversation data
            const extractConversationData = () => {
              // Look for conversation container
              const conversationContainer = document.querySelector('[data-conversation-container="true"]');
              if (!conversationContainer) return null;

              // Get all message elements
              const messageElements = conversationContainer.querySelectorAll('[data-message]');
              if (!messageElements.length) return null;

              const messages = [];
              messageElements.forEach(el => {
                const role = el.getAttribute('data-message-role') || 'unknown';
                const content = el.innerText || '';
                if (content.trim()) {
                  messages.push({ role, content });
                }
              });

              // Get title from URL or page title
              let title = '';
              try {
                const urlParams = new URLSearchParams(window.location.search);
                title = urlParams.get('q') || document.title || 'Untitled Conversation';
              } catch (e) {
                title = document.title || 'Untitled Conversation';
              }

              // Only save if we have messages
              if (messages.length === 0) return null;

              return {
                id: window.location.pathname,
                title: title.substring(0, 100), // Limit title length
                timestamp: Date.now(),
                messages,
                url: window.location.href
              };
            };

            // Auto-save current conversation
            const autoSaveConversation = () => {
              const conversationData = extractConversationData();
              if (!conversationData) return;

              const savedSessions = getSavedSessions();

              // Check if this conversation is already saved (by ID)
              const existingIndex = savedSessions.findIndex(s => s.id === conversationData.id);

              if (existingIndex !== -1) {
                // Update existing session
                savedSessions[existingIndex] = conversationData;
              } else {
                // Add new session
                savedSessions.unshift(conversationData);

                // Limit the number of saved sessions
                if (savedSessions.length > MAX_SAVED_SESSIONS) {
                  savedSessions.length = MAX_SAVED_SESSIONS;
                }
              }

              saveSessions(savedSessions);
              console.log('[PERPLEXITY-MAX-INJECTED] Auto-saved conversation:', conversationData.title);
            };

            // Set up auto-save interval
            setInterval(autoSaveConversation, 10000); // Save every 10 seconds

            // Also save on page unload
            window.addEventListener('beforeunload', autoSaveConversation);

            // Add global function to access saved sessions
            window.pplxMaxGetSavedSessions = () => {
              return getSavedSessions();
            };

            console.log('[PERPLEXITY-MAX-INJECTED] Auto-save functionality setup complete');
          })();
        `;

        document.head.appendChild(script);
        document.head.removeChild(script);
      }

      /* ─────────────────── TRACK UPLOAD REQUESTS ─────────────────── */
      function setupUploadTracking() {
        log('Setting up upload tracking system');

        // Inject a script to track upload requests and responses
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Setting up upload tracking system');

            // Track file upload events
            document.addEventListener('drop', function(e) {
              if (e.dataTransfer && e.dataTransfer.files && e.dataTransfer.files.length > 0) {
                console.log('[PERPLEXITY-MAX-INJECTED] File drop detected:', e.dataTransfer.files.length, 'files');
              }
            }, true);

            // Track file input changes
            document.addEventListener('change', function(e) {
              if (e.target && e.target.type === 'file' && e.target.files && e.target.files.length > 0) {
                console.log('[PERPLEXITY-MAX-INJECTED] File input change detected:', e.target.files.length, 'files');
              }
            }, true);

            // Override the FormData.append method to track file uploads
            const originalAppend = FormData.prototype.append;
            FormData.prototype.append = function(name, value, filename) {
              // Check if this is a file upload
              if (value instanceof Blob || value instanceof File) {
                console.log('[PERPLEXITY-MAX-INJECTED] File added to FormData:', name, filename || (value.name || 'blob'));
              }

              return originalAppend.call(this, name, value, filename);
            };
          })();
        `;

        document.head.appendChild(script);
        document.head.removeChild(script);
      }

      /* ─────────────────── FORCE UNLIMITED ACCESS ─────────────────── */
      function injectUnlimitedAccess() {
        log('Injecting unlimited access script into page context');

        // Create a script that will run in the page context
        const script = document.createElement('script');
        script.textContent = `
          (function() {
            console.log('[PERPLEXITY-MAX-INJECTED] Setting up unlimited access');

            // Create a debug logger
            const DEBUG = true;
            const debug = (...args) => DEBUG && console.log('[PERPLEXITY-MAX-DEBUG]', ...args);

            // Store original methods
            const originalFetch = window.fetch;
            const OriginalXMLHttpRequest = window.XMLHttpRequest;

            // Create a response modifier function
            function createMaxResponse(originalResponse) {
              // Define max settings
              const maxSettings = {
                subscription_tier: 'max',
                subscription_status: 'active',
                subscription_source: 'stripe',
                stripe_status: 'active',
                gpt4_limit: 999999,
                pplx_alpha_limit: 999999,
                pplx_beta_limit: 999999,
                pages_limit: 999999,
                upload_limit: 999999,
                create_limit: 999999,
                article_image_upload_limit: 999999,
                max_files_per_user: 999999,
                max_files_per_repository: 999999,
                rate_limited: false,
                remaining_pro: 999999,
                remaining_research: 999999,
                remaining_labs: 999999,
                remaining_uploads: 999999,
                remaining_copilot: 999999,
                remaining_search: 999999,
                remaining_create: 999999
              };

              // Apply max settings to response
              return Object.assign({}, originalResponse, maxSettings);
            }

            // Create a completely new XMLHttpRequest class
            window.XMLHttpRequest = function() {
              const xhr = new OriginalXMLHttpRequest();

              // Track request details
              let requestUrl = '';
              let requestMethod = '';
              let isImportant = false;
              let isModified = false;

              // Override open
              const originalOpen = xhr.open;
              xhr.open = function(method, url, ...args) {
                requestMethod = method;
                requestUrl = url;

                debug('XHR Open:', method, url);

                // Check if this is an important request
                if (typeof url === 'string') {
                  if (url.includes('/rest/rate-limit/all')) {
                    isImportant = true;
                    console.log('[PERPLEXITY-MAX-INJECTED] Important XHR detected: rate-limit');

                    // For rate-limit requests, we'll handle them specially
                    const fakeResponse = {
                      remaining_pro: 999999,
                      remaining_research: 999999,
                      remaining_labs: 999999,
                      remaining_uploads: 999999,
                      remaining_copilot: 999999,
                      remaining_search: 999999,
                      remaining_create: 999999,
                      rate_limited: false
                    };

                    // Create a fake URL that will be intercepted later
                    url = 'data:application/json,' + encodeURIComponent(JSON.stringify(fakeResponse));
                  }
                  else if (url.includes('/rest/user/save-settings')) {
                    isImportant = true;
                    console.log('[PERPLEXITY-MAX-INJECTED] Important XHR detected: save-settings');
                  }
                  else if (url.includes('/rest/uploads/create_upload_url')) {
                    isImportant = true;
                    console.log('[PERPLEXITY-MAX-INJECTED] Important XHR detected: upload-url');
                  }
                }

                return originalOpen.call(xhr, method, url, ...args);
              };

              // Override send
              const originalSend = xhr.send;
              xhr.send = function(body) {
                debug('XHR Send:', requestMethod, requestUrl, body);

                // Modify request body for important requests
                if (isImportant && body && typeof body === 'string') {
                  try {
                    const data = JSON.parse(body);

                    // For save-settings requests
                    if (requestUrl.includes('/rest/user/save-settings')) {
                      console.log('[PERPLEXITY-MAX-INJECTED] Modifying save-settings request body');

                      // If this is a partial update
                      if (data.updated_settings) {
                        console.log('[PERPLEXITY-MAX-INJECTED] Original updated_settings:', JSON.stringify(data.updated_settings));

                        data.updated_settings = Object.assign({}, data.updated_settings, {
                          subscription_tier: 'max',
                          subscription_status: 'active',
                          subscription_source: 'stripe',
                          stripe_status: 'active',
                          gpt4_limit: 999999,
                          pplx_alpha_limit: 999999,
                          pplx_beta_limit: 999999,
                          pages_limit: 999999,
                          upload_limit: 999999,
                          create_limit: 999999,
                          article_image_upload_limit: 999999,
                          max_files_per_user: 999999,
                          max_files_per_repository: 999999
                        });

                        console.log('[PERPLEXITY-MAX-INJECTED] Modified updated_settings:', JSON.stringify(data.updated_settings));
                      } else {
                        // Full update
                        Object.assign(data, {
                          subscription_tier: 'max',
                          subscription_status: 'active',
                          subscription_source: 'stripe',
                          stripe_status: 'active',
                          gpt4_limit: 999999,
                          pplx_alpha_limit: 999999,
                          pplx_beta_limit: 999999,
                          pages_limit: 999999,
                          upload_limit: 999999,
                          create_limit: 999999,
                          article_image_upload_limit: 999999,
                          max_files_per_user: 999999,
                          max_files_per_repository: 999999
                        });
                      }

                      // Update the body
                      body = JSON.stringify(data);
                      console.log('[PERPLEXITY-MAX-INJECTED] Modified request body:', body);
                    }
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] Error modifying request body:', e);
                  }
                }

                // For important requests, intercept the response
                if (isImportant) {
                  // Override responseText getter
                  let originalResponseText = '';
                  Object.defineProperty(xhr, 'responseText', {
                    get: function() {
                      if (isModified) {
                        return originalResponseText;
                      }

                      const response = xhr._responseText || '';

                      // Only modify JSON responses
                      if (response && response.startsWith('{')) {
                        try {
                          const data = JSON.parse(response);

                          // For rate-limit requests
                          if (requestUrl.includes('/rest/rate-limit/all')) {
                            console.log('[PERPLEXITY-MAX-INJECTED] Modifying rate-limit response');
                            const modifiedData = {
                              remaining_pro: 999999,
                              remaining_research: 999999,
                              remaining_labs: 999999,
                              remaining_uploads: 999999,
                              remaining_copilot: 999999,
                              remaining_search: 999999,
                              remaining_create: 999999,
                              rate_limited: false
                            };
                            originalResponseText = JSON.stringify(modifiedData);
                            isModified = true;
                            return originalResponseText;
                          }

                          // For save-settings requests
                          if (requestUrl.includes('/rest/user/save-settings')) {
                            console.log('[PERPLEXITY-MAX-INJECTED] Modifying save-settings response');
                            const modifiedData = createMaxResponse(data);
                            originalResponseText = JSON.stringify(modifiedData);
                            isModified = true;
                            return originalResponseText;
                          }

                          // For upload URL creation
                          if (requestUrl.includes('/rest/uploads/create_upload_url')) {
                            console.log('[PERPLEXITY-MAX-INJECTED] Modifying upload URL response');
                            data.rate_limited = false;

                            // If fields are null, create fake ones to allow uploads
                            if (!data.fields || !data.s3_bucket_url) {
                              data.s3_bucket_url = "https://api.cloudinary.com/v1_1/pplx/image/upload";
                              data.s3_object_url = "https://api.cloudinary.com/v1_1/pplx/image/upload/";
                              data.fields = {
                                timestamp: Date.now(),
                                unique_filename: "true",
                                folder: "user_uploads/unlimited/max",
                                use_filename: "true",
                                public_id: "unlimited_" + Date.now(),
                                transformation: "t_fit2",
                                type: "private",
                                resource_type: "image",
                                api_key: "168798331147639",
                                cloud_name: "pplx",
                                signature: "unlimited_max_signature"
                              };
                              data.file_uuid = "unlimited_" + Date.now();
                            }

                            originalResponseText = JSON.stringify(data);
                            isModified = true;
                            return originalResponseText;
                          }
                        } catch (e) {
                          console.error('[PERPLEXITY-MAX-INJECTED] Error modifying response:', e);
                        }
                      }

                      return response;
                    },
                    set: function(value) {
                      xhr._responseText = value;
                    }
                  });

                  // Override response getter
                  Object.defineProperty(xhr, 'response', {
                    get: function() {
                      // If we've modified the responseText, return that for JSON responses
                      if (isModified && xhr.responseType === '' || xhr.responseType === 'text') {
                        return xhr.responseText;
                      }

                      return xhr._response;
                    },
                    set: function(value) {
                      xhr._response = value;
                    }
                  });
                }

                // Monitor readyState changes
                const originalStateChange = xhr.onreadystatechange;
                xhr.onreadystatechange = function(e) {
                  if (xhr.readyState === 4) {
                    debug('XHR Complete:', requestMethod, requestUrl, xhr.status);

                    if (isImportant) {
                      debug('Response for important request:', xhr.responseText);
                    }
                  }

                  if (originalStateChange) {
                    return originalStateChange.call(xhr, e);
                  }
                };

                return originalSend.call(xhr, body);
              };

              return xhr;
            };

            // Override fetch with a proxy
            window.fetch = new Proxy(originalFetch, {
              apply: async function(target, thisArg, args) {
                // Extract URL and init
                let [input, init] = args;
                const url = typeof input === 'string' ? input : input.url;
                const method = init?.method || 'GET';

                debug('Fetch:', method, url);

                // Handle rate limit requests directly
                if (url && url.includes('/rest/rate-limit/all')) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Intercepting rate-limit fetch request');

                  return new Response(JSON.stringify({
                    remaining_pro: 999999,
                    remaining_research: 999999,
                    remaining_labs: 999999,
                    remaining_uploads: 999999,
                    remaining_copilot: 999999,
                    remaining_search: 999999,
                    remaining_create: 999999,
                    rate_limited: false
                  }), {
                    status: 200,
                    headers: { 'Content-Type': 'application/json' }
                  });
                }

                // Handle save-settings requests
                if (url && url.includes('/rest/user/save-settings')) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Intercepting save-settings fetch request');

                  // Modify request body for PUT/POST
                  if ((method === 'PUT' || method === 'POST') && init && init.body) {
                    try {
                      let body = {};

                      if (typeof init.body === 'string') {
                        body = JSON.parse(init.body);
                      }

                      // If this is a partial update
                      if (body.updated_settings) {
                        console.log('[PERPLEXITY-MAX-INJECTED] Original updated_settings:', JSON.stringify(body.updated_settings));

                        body.updated_settings = Object.assign({}, body.updated_settings, {
                          subscription_tier: 'max',
                          subscription_status: 'active',
                          subscription_source: 'stripe',
                          stripe_status: 'active',
                          gpt4_limit: 999999,
                          pplx_alpha_limit: 999999,
                          pplx_beta_limit: 999999,
                          pages_limit: 999999,
                          upload_limit: 999999,
                          create_limit: 999999,
                          article_image_upload_limit: 999999,
                          max_files_per_user: 999999,
                          max_files_per_repository: 999999
                        });

                        console.log('[PERPLEXITY-MAX-INJECTED] Modified updated_settings:', JSON.stringify(body.updated_settings));
                      } else {
                        // Full update
                        Object.assign(body, {
                          subscription_tier: 'max',
                          subscription_status: 'active',
                          subscription_source: 'stripe',
                          stripe_status: 'active',
                          gpt4_limit: 999999,
                          pplx_alpha_limit: 999999,
                          pplx_beta_limit: 999999,
                          pages_limit: 999999,
                          upload_limit: 999999,
                          create_limit: 999999,
                          article_image_upload_limit: 999999,
                          max_files_per_user: 999999,
                          max_files_per_repository: 999999
                        });
                      }

                      // Update the request
                      init.body = JSON.stringify(body);
                      console.log('[PERPLEXITY-MAX-INJECTED] Modified save-settings request body:', init.body);
                    } catch (e) {
                      console.error('[PERPLEXITY-MAX-INJECTED] Error modifying save-settings request:', e);
                    }
                  }

                  // Make the modified request
                  const response = await target.apply(thisArg, [input, init]);

                  // Clone and modify the response
                  try {
                    const clonedResponse = response.clone();
                    const data = await clonedResponse.json();

                    console.log('[PERPLEXITY-MAX-INJECTED] Original save-settings response:', JSON.stringify(data));

                    // Apply max settings
                    const maxData = createMaxResponse(data);

                    console.log('[PERPLEXITY-MAX-INJECTED] Modified save-settings response:', JSON.stringify(maxData));

                    return new Response(JSON.stringify(maxData), {
                      status: response.status,
                      statusText: response.statusText,
                      headers: response.headers
                    });
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] Error modifying save-settings response:', e);
                    return response;
                  }
                }

                // Handle upload URL creation
                if (url && url.includes('/rest/uploads/create_upload_url')) {
                  console.log('[PERPLEXITY-MAX-INJECTED] Intercepting upload URL creation fetch request');

                  // Make the original request
                  const response = await target.apply(thisArg, args);

                  try {
                    // Clone and get the data
                    const clonedResponse = response.clone();
                    const data = await clonedResponse.json();

                    console.log('[PERPLEXITY-MAX-INJECTED] Original upload URL response:', JSON.stringify(data));

                    // Always set rate_limited to false
                    data.rate_limited = false;

                    // If fields are null, create fake ones to allow uploads
                    if (!data.fields || !data.s3_bucket_url) {
                      data.s3_bucket_url = "https://api.cloudinary.com/v1_1/pplx/image/upload";
                      data.s3_object_url = "https://api.cloudinary.com/v1_1/pplx/image/upload/";
                      data.fields = {
                        timestamp: Date.now(),
                        unique_filename: "true",
                        folder: "user_uploads/unlimited/max",
                        use_filename: "true",
                        public_id: "unlimited_" + Date.now(),
                        transformation: "t_fit2",
                        type: "private",
                        resource_type: "image",
                        api_key: "168798331147639",
                        cloud_name: "pplx",
                        signature: "unlimited_max_signature"
                      };
                      data.file_uuid = "unlimited_" + Date.now();
                    }

                    console.log('[PERPLEXITY-MAX-INJECTED] Modified upload URL response:', JSON.stringify(data));

                    return new Response(JSON.stringify(data), {
                      status: response.status,
                      statusText: response.statusText,
                      headers: response.headers
                    });
                  } catch (e) {
                    console.error('[PERPLEXITY-MAX-INJECTED] Error modifying upload URL response:', e);
                    return response;
                  }
                }

                // For all other requests, proceed normally
                const response = await target.apply(thisArg, args);

                // For JSON responses, check if we need to modify them
                if (url && (
                  url.includes('/api/user') ||
                  url.includes('/api/subscription') ||
                  url.includes('/api/auth/session') ||
                  url.includes('/rest/user/')
                )) {
                  try {
                    const contentType = response.headers.get('content-type');
                    if (contentType && contentType.includes('application/json')) {
                      const clonedResponse = response.clone();
                      const data = await clonedResponse.json();

                      // Check if this response has any fields we want to modify
                      const keysToCheck = [
                        'subscription_tier', 'subscription_status', 'subscription_source',
                        'remaining_pro', 'remaining_research', 'remaining_labs',
                        'upload_limit', 'rate_limited', 'gpt4_limit'
                      ];

                      let shouldModify = false;
                      for (const key of keysToCheck) {
                        if (key in data) {
                          shouldModify = true;
                          break;
                        }
                      }

                      if (shouldModify) {
                        console.log('[PERPLEXITY-MAX-INJECTED] Modifying JSON response for:', url);
                        const maxData = createMaxResponse(data);

                        return new Response(JSON.stringify(maxData), {
                          status: response.status,
                          statusText: response.statusText,
                          headers: response.headers
                        });
                      }
                    }
                  } catch (e) {
                    // Not JSON or other error
                  }
                }

                return response;
              }
            });

            // Override Object.defineProperty to catch React state updates
            const originalDefineProperty = Object.defineProperty;
            Object.defineProperty = function(obj, prop, descriptor) {
              // Check if this is a subscription-related property
              if (prop === 'subscription_tier' || prop === 'subscription_status' ||
                  prop === 'is_pro' || prop === 'is_max' || prop === 'has_max') {

                // Force MAX values
                if (descriptor && descriptor.value !== undefined) {
                  if (prop === 'subscription_tier') descriptor.value = 'max';
                  if (prop === 'subscription_status') descriptor.value = 'active';
                  if (prop === 'is_pro' || prop === 'is_max' || prop === 'has_max') descriptor.value = true;
                }

                // For getters/setters
                if (descriptor && descriptor.get) {
                  const originalGetter = descriptor.get;
                  descriptor.get = function() {
                    let value = originalGetter.call(this);
                    if (prop === 'subscription_tier') value = 'max';
                    if (prop === 'subscription_status') value = 'active';
                    if (prop === 'is_pro' || prop === 'is_max' || prop === 'has_max') value = true;
                    return value;
                  };
                }
              }

              // Apply the original defineProperty
              return originalDefineProperty.call(this, obj, prop, descriptor);
            };

            // Create a global helper function to force MAX subscription
            window.forcePplxMax = function() {
              console.log('[PERPLEXITY-MAX-INJECTED] Manually forcing MAX subscription');

              // Try to find React state in the DOM
              const reactRoots = document.querySelectorAll('[data-reactroot]');
              reactRoots.forEach(root => {
                console.log('[PERPLEXITY-MAX-INJECTED] Found React root:', root);
              });

              // Force update by triggering resize and visibility events
              window.dispatchEvent(new Event('resize'));
              document.dispatchEvent(new Event('visibilitychange'));

              // Try to modify localStorage
              try {
                const storageKeys = ['perplexity-user', 'perplexity-subscription', 'perplexity-usage'];

                storageKeys.forEach(key => {
                  const data = localStorage.getItem(key);
                  if (data) {
                    try {
                      const parsed = JSON.parse(data);

                      if (key === 'perplexity-user') {
                        parsed.subscription_tier = 'max';
                        parsed.subscription_status = 'active';
                        parsed.subscription_source = 'stripe';
                        parsed.is_max = true;
                        parsed.has_max = true;
                        parsed.is_pro = true;
                      }

                      if (key === 'perplexity-subscription') {
                        parsed.tier = 'max';
                        parsed.status = 'active';
                        parsed.source = 'stripe';
                      }

                      if (key === 'perplexity-usage') {
                        if (parsed.remaining_pro !== undefined) parsed.remaining_pro = 999999;
                        if (parsed.remaining_research !== undefined) parsed.remaining_research = 999999;
                        if (parsed.remaining_labs !== undefined) parsed.remaining_labs = 999999;
                      }

                      localStorage.setItem(key, JSON.stringify(parsed));
                      console.log('[PERPLEXITY-MAX-INJECTED] Modified localStorage:', key);
                    } catch (e) {
                      console.error('[PERPLEXITY-MAX-INJECTED] Error parsing localStorage:', e);
                    }
                  }
                });
              } catch (e) {
                console.error('[PERPLEXITY-MAX-INJECTED] Error accessing localStorage:', e);
              }

              return "MAX subscription forced!";
            };

            // Run forcePplxMax periodically
            setInterval(window.forcePplxMax, 5000);

            console.log('[PERPLEXITY-MAX-INJECTED] Unlimited access setup complete. Use window.forcePplxMax() to force MAX subscription manually.');
          })();
        `;

        // Add the script to the page
        document.head.appendChild(script);
        document.head.removeChild(script);
        log('Unlimited access script injected with advanced monitoring');
      }

      /* ─────────────────── INITIALIZATION ─────────────────── */
      function initializeScript() {
        log('Initializing Perplexity MAX script v2.1');

        // Version information
        const VERSION = {
          major: 2,
          minor: 1,
          patch: 0,
          date: '2025-10-18',
          features: [
            'Improved caching system',
            'Auto-save conversations',
            'Enhanced error handling',
            'Latest model support',
            'Expanded feature set',
            'Improved UI indicators'
          ]
        };

        // Log version info
        log(`Version ${VERSION.major}.${VERSION.minor}.${VERSION.patch} (${VERSION.date})`);
        log(`New features: ${VERSION.features.join(', ')}`);

        // Add a mutation observer to handle dynamically added elements
        const observer = new MutationObserver((mutations) => {
          // Check if body exists
          if (document.body) {
            // Run our main functions
            forceMaxSubscription(); // Force MAX subscription when DOM changes
            enableUnlimitedUploads(); // Enable unlimited uploads
            blockAnalyticsScripts(); // Block analytics and tracking
            injectUnlimitedAccess(); // Inject unlimited access script
            setupAutoSave(); // Set up auto-save functionality

            // Disconnect after initial setup to avoid performance issues
            observer.disconnect();

            // Add status indicator
            const statusIndicator = setTimeout(addStatusIndicator, 2000);

            // Set up periodic checks with improved error handling
            const subscriptionInterval = setInterval(() => {
              try {
                forceMaxSubscription();
              } catch (e) {
                log('Error in periodic subscription check:', e);
              }
            }, 10000);

            // Add global access to version info
            window.PERPLEXITY_MAX_VERSION = VERSION;

            // Expose a global API for debugging and extensions
            window.PERPLEXITY_MAX_API = {
              forceUpdate: forceReactUpdate,
              forceSubscription: forceMaxSubscription,
              version: VERSION,
              getCacheSize: () => responseCache.size,
              clearCache: () => {
                responseCache.clear();
                log('Cache cleared');
              }
            };
          }
        });

        // Start observing with error handling
        try {
          observer.observe(document.documentElement, {
            childList: true,
            subtree: true
          });
        } catch (e) {
          log('Error setting up mutation observer:', e);
          // Fallback to direct initialization
          if (document.body) {
            initializeDirect();
          } else {
            window.addEventListener('DOMContentLoaded', initializeDirect);
          }
        }

        // Direct initialization function for fallback
        function initializeDirect() {
          forceMaxSubscription(); // Force MAX subscription immediately
          enableUnlimitedUploads(); // Enable unlimited uploads
          blockAnalyticsScripts(); // Block analytics and tracking
          injectUnlimitedAccess(); // Inject unlimited access script
          setupAutoSave(); // Set up auto-save functionality
          setTimeout(addStatusIndicator, 2000);
          setInterval(forceMaxSubscription, 10000); // Periodically force MAX subscription
        }

        // If body already exists, run immediately
        if (document.body) {
          observer.disconnect();
          initializeDirect();
        }
      }

      // Start the script
      if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initializeScript);
      } else {
        initializeScript();
      }
    })();