Greasy Fork

Greasy Fork is available in English.

AI Conversation Navigator

Floating navigator for your prompts in conversations with bookmark feature. Applied for ChatGPT, Gemini, Aistudio, NotebookLM, Grok, Claude, Mistral, Perplexity, Meta, Poe, Deepai, Huggingface, Deepseek, Kimi, Qwen, Manus, Z.ai, Longcat, Chatglm, Ernie, Chatboxai, Lmarena, Quillbot, Canva, Genspark, Character, Spacefrontiers, Scienceos, Evidencehunt, Playground (allen), Paperfigureqa (allen), Scira, Scispace, Exa.ai, Consensus, Openevidence, Pathway, Math-gpt.

当前为 2026-02-02 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         AI Conversation Navigator
// @namespace    http://greasyfork.icu
// @version      9.8
// @description  Floating navigator for your prompts in conversations with bookmark feature. Applied for ChatGPT, Gemini, Aistudio, NotebookLM, Grok, Claude, Mistral, Perplexity, Meta, Poe, Deepai, Huggingface, Deepseek, Kimi, Qwen, Manus, Z.ai, Longcat, Chatglm, Ernie, Chatboxai, Lmarena, Quillbot, Canva, Genspark, Character, Spacefrontiers, Scienceos, Evidencehunt, Playground (allen), Paperfigureqa (allen), Scira, Scispace, Exa.ai, Consensus, Openevidence, Pathway, Math-gpt.
// @author       Bui Quoc Dung
// @match        https://chatgpt.com/*
// @match        https://gemini.google.com/*
// @match        https://aistudio.google.com/*
// @match        https://notebooklm.google.com/*
// @match        https://grok.com/*
// @match        https://claude.ai/*
// @match        https://www.kimi.com/*
// @match        https://chat.mistral.ai/*
// @match        https://www.perplexity.ai/*
// @match        https://www.meta.ai/*
// @match        https://poe.com/*
// @match        https://deepai.org/*
// @match        https://huggingface.co/chat/*
// @match        https://chat.deepseek.com/*
// @match        https://chat.qwen.ai/*
// @match        https://manus.im/*
// @match        https://chat.z.ai/*
// @match        https://longcat.chat/*
// @match        https://chatglm.cn/*
// @match        https://ernie.baidu.com/*
// @match        https://web.chatboxai.app/*
// @match        https://lmarena.ai/*
// @match        https://quillbot.com/*
// @match        https://www.canva.com/*
// @match        https://www.genspark.ai/*
// @match        https://character.ai/*
// @match        https://spacefrontiers.org/*
// @match        https://app.scienceos.ai/*
// @match        https://evidencehunt.com/*
// @match        https://playground.allenai.org/*
// @match        https://paperfigureqa.allen.ai/*
// @match        https://scira.ai/*
// @match        https://exa.ai/*
// @match        https://consensus.app/*
// @match        https://www.openevidence.com/*
// @match        https://www.pathway.md/*
// @match        https://math-gpt.org/*
// @grant        GM_addStyle
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    const NAV_WIDTH = 250;
    const NAV_COLLAPSED_WIDTH = 80;
    const DEBOUNCE_TIME = 500;
    const AISTUDIO_DEBOUNCE_TIME = 200;
    let activeMessageIndex = -1;
    let lastUrl = window.location.href;
    let lastPromptsContent = "";
    let cachedPrompts = [];
    let urlCheckInterval = null;
    let injectedStyleId = 'nav-shift-styles';
    let loadingTimeout = null;
    let bookmarkedMessages = new Set();

    function getAIStudioData() {
        const prompts = [];
        const scrollButtons = document.querySelectorAll('ms-prompt-scrollbar button[id^="scrollbar-item-"]');
        scrollButtons.forEach(btn => {
            const isUser = btn.querySelector('.prompt-scrollbar-dot');
            if (isUser) {
                let text = btn.getAttribute('aria-label');
                if (!text && (btn.querySelector('img') || btn.querySelector('mat-icon'))) {
                    text = "image:";
                }
                if (text) {
                    prompts.push({
                        element: btn,
                        text: text.trim()
                    });
                }
            }
        });
        return prompts;
    }

    function getClaudeData() {
          const prompts = [];
          const turns = document.querySelectorAll('.mb-1.mt-6.group');

          turns.forEach(turn => {
              const fileEl = turn.querySelector('[data-testid="file-thumbnail"] p');
              const fileText = fileEl ? fileEl.textContent.trim() : "";
              const msgEl = turn.querySelector('[data-testid="user-message"]');
              const msgText = msgEl ? msgEl.textContent.trim() : "";

              const combinedText = (fileText ? `[File] ${fileText} ` : "") + msgText;

              if (combinedText.trim()) {
                  prompts.push({
                      element: turn,
                      text: combinedText.trim()
                  });
              }
          });
          return prompts;
      }

    function getVersionInfo(container, vc) {
        if (!container || !vc) return null;

        const versionText = container.querySelector(vc.versionTextSelector);
        if (!versionText) return null;

        const text = versionText.textContent.trim();
        const match = text.match(/(\d+)\/(\d+)/);
        if (!match) return null;

        const currentVersion = parseInt(match[1]);
        const totalVersions = parseInt(match[2]);

        const prevButton = container.querySelector(vc.prevButtonSelector);
        const nextButton = container.querySelector(vc.nextButtonSelector);

        return {
            currentVersion,
            totalVersions,
            prevButton,
            nextButton,
            hasMultipleVersions: totalVersions > 1
        };
    }

    const SITE_CONFIGS = {
        chatgpt: {
            domain: 'chatgpt.com',
            includePath: ['chatgpt.com/c/', 'chatgpt.com/g/'],
            userMessage: 'div[data-message-author-role="user"]',
            shiftTarget: '[data-scroll-root]',
            shiftHeader: '.flex.items-center.justify-end.gap-2.overflow-x-hidden',
            collapsedTop: '5px',
            versionControl: {
                containerSelector: '[data-testid^="conversation-turn-"]',
                versionTextSelector: '.px-0\\.5.text-sm.font-semibold.tabular-nums',
                prevButtonSelector: 'button[aria-label*="Previous response"]',
                nextButtonSelector: 'button[aria-label*="Next response"]'
            }
        },
        gemini: {
            domain: 'gemini.google.com',
            includePath: ['gemini.google.com/app/','gemini.google.com/gem/', 'gemini.google.com/u/1/app/', 'gemini.google.com/u/2/app/'],
            userMessage: '.query-text',
            shiftTarget: 'chat-app, .boqOnegoogleliteOgbOneGoogleBar, top-bar-actions',
            shiftHeader: '.boqOnegoogleliteOgbOneGoogleBar, top-bar-actions',
            collapsedTop: '13px'
        },
        aistudio: {
            domain: 'aistudio.google.com',
            includePath: ['aistudio.google.com/prompts/','aistudio.google.com/u/1/prompts/', 'aistudio.google.com/u/2/prompts/'],
            customFinder: getAIStudioData,
            useClick: true,
            shiftTarget: '.layout-wrapper',
            fastUpdate: true,
            debounceTime: AISTUDIO_DEBOUNCE_TIME,
            shiftHeader: '.toolbar-container',
            collapsedTop: '14px'
        },
        notebooklm: {
            domain: 'notebooklm.google.com',
            includePath: 'notebooklm.google.com/notebook/',
            userMessage: 'chat-message .from-user-container',
            shiftTarget: 'notebook, .boqOnegoogleliteOgbOneGoogleBar',
            shiftHeader: '.notebook-header-container, .boqOnegoogleliteOgbOneGoogleBar',
            collapsedTop: '15px'
        },
        grok: {
            domain: 'grok.com',
            includePath: 'grok.com/c/',
            userMessage: '.relative.group.flex.flex-col.justify-center.items-end',
            shiftTarget: 'main',
            shiftHeader: '.ms-auto.end-3',
            collapsedTop: '13px'
        },
        claude: {
            domain: 'claude.ai',
            includePath: ['claude.ai/chat/', 'claude.ai/new'],
            customFinder: getClaudeData,
            shiftTarget: '#main-content',
            shiftHeader: '[data-testid="wiggle-controls-actions"]',
            collapsedTop: '10px'
        },
        mistral: {
            domain: 'chat.mistral.ai',
            includePath: 'chat.mistral.ai/chat/',
            userMessage: 'div[data-message-author-role="user"] div[dir="auto"]',
            shiftTarget: 'main.bg-sidebar-subtle',
            shiftHeader: '.items-center.p-3',
            collapsedTop: '7px'
        },
        perplexity: {
            domain: 'perplexity.ai',
            includePath: 'www.perplexity.ai/search/',
            userMessage: 'div.group\\/title',
            shiftTarget: '#root',
            shiftHeader: '.pr-md',
            collapsedTop: '5px'
        },
        meta: {
            domain: 'meta.ai',
            includePath: 'www.meta.ai/prompt/',
            userMessage: '.x78zum5.x15zctf7',
            shiftTarget: '.xph554m.x73z65k',
            shiftHeader: '.x78zum5.xfex06f',
            collapsedTop: '10px'
        },
        poe: {
            domain: 'poe.com',
            includePath: 'poe.com/chat/',
            userMessage: '[class*="ChatMessagesView_tupleGroupContainer"] > div > div:first-child',
            shiftTarget: '[class*="CanvasSidebarLayout_chat-column"]'
        },
        deepai: {
            domain: 'deepai.org',
            includePath: 'deepai.org/chat',
            userMessage: '.chatbox',
            shiftTarget: '.chat-layout-container, .new-chat-button-container, .persistent-compose-area, .nav-items'
        },
        huggingface: {
            domain: 'huggingface.co',
            includePath: 'huggingface.co/chat/conversation/',
            userMessage: '.disabled.w-full.appearance-none',
            shiftTarget: '.relative.min-h-0.min-w-0'
        },
        deepseek: {
            domain: 'chat.deepseek.com',
            includePath: 'chat.deepseek.com/a/chat/',
            userMessage: '._9663006 .fbb737a4',
            shiftTarget: '._8f60047, ._189b4a0, ._2be88ba',
            shiftHeader: '._2be88ba',
            collapsedTop: '10px'
        },
        kimi: {
            domain: 'www.kimi.com',
            includePath: 'www.kimi.com/chat/',
            userMessage: '.user-content',
            shiftTarget: '.has-sidebar',
            shiftHeader: '[class="chat-header-actions"]',
            collapsedTop: '8px'
        },
        glm: {
            domain: 'chat.z.ai',
            includePath: 'chat.z.ai/c/',
            userMessage: '.chat-user',
            shiftTarget:'#chat-container',
            shiftHeader: '.flex.px-1',
            collapsedTop: '15px'
        },
        qwen: {
            domain: 'chat.qwen.ai',
            includePath: 'chat.qwen.ai/c/',
            userMessage: '.chat-user-message',
            shiftTarget: '.desktop-layout-content',
            shiftHeader: '.header-right',
            collapsedTop: '5px'
        },
        manus: {
            domain: 'manus.im',
            includePath: 'manus.im/app/',
            userMessage: '.flex.relative.flex-col.gap-2.items-end',
            shiftTarget: '.simplebar-content'
        },
        longcat: {
            domain: 'longcat.chat',
            includePath: 'longcat.chat/c/',
            userMessage: '.user-message',
            shiftTarget: '.content',
        },
        chatglm: {
            domain: 'chatglm.cn',
            includePath: 'chatglm.cn/main/',
            userMessage: '.question-txt.dots',
            shiftTarget: '.detail-container',
            shiftHeader: '.right-box',
            collapsedTop: '5px',
        },
        ernie: {
            domain: 'ernie.baidu.com',
            includePath: 'ernie.baidu.com/chat/',
            userMessage: '#question_text_id',
            shiftTarget: '#root',
            shiftHeader: '[class*="TopRightTools"]',
            collapsedTop: '3px',
            reverse: true,
        },
        chatboxai: {
            domain: 'web.chatboxai.app',
            includePath: 'web.chatboxai.app/session/',
            userMessage: '.user-msg',
            shiftTarget: '.h-full.w-full.MuiBox-root'
        },
        lmarena: {
            domain: 'lmarena.ai',
            includePath: 'lmarena.ai/c/',
            userMessage: '.justify-end.gap-2',
            shiftTarget: '#chat-area',
            reverse: true
        },
        quillbot: {
            domain: 'quillbot.com',
            includePath: 'quillbot.com/ai-chat/c/',
            userMessage: 'div.MuiGrid-root.MuiGrid-container > div.MuiGrid-root > p.MuiTypography-root.MuiTypography-bodyMedium.MuiTypography-paragraph',
            shiftTarget: '#root-client'
        },
        canva: {
            domain: 'www.canva.com',
            includePath: 'www.canva.com/ai/',
            userMessage: '#_r_1_ .uV9Uzw .Ka9auQ p',
            shiftTarget: '#root'
        },
        genspark: {
            domain: 'www.genspark.ai',
            includePath: 'www.genspark.ai/agents?',
            userMessage: '.conversation-item-desc.user',
            shiftTarget: '.n-config-provider'
        },
        character: {
            domain: 'character.ai',
            includePath: 'character.ai/chat/',
            userMessage: '.w-full .bg-surface-elevation-3.opacity-90',
            shiftTarget: '#__next, #chat-header-background',
            reverse: true
        },
        spacefrontiers: {
            domain: 'spacefrontiers.org',
            includePath: 'spacefrontiers.org/c/',
            userMessage: '.inline.whitespace-pre-line',
            shiftTarget: '#app'
        },
        scienceos: {
            domain: 'app.scienceos.ai',
            includePath: 'app.scienceos.ai/chat/',
            userMessage: 'div[data-prompt]',
            shiftTarget: 'div[data-strategy]'
        },
        evidencehunt: {
            domain: 'evidencehunt.com',
            includePath: 'evidencehunt.com/chat',
            userMessage: '.chat__message:has(.message__user-image) .message__content p',
            shiftTarget: '.v-main'
        },
        playground: {
            domain: 'playground.allenai.org',
            includePath: 'playground.allenai.org/thread/',
            userMessage: 'div[class*="chat-message"]:nth-of-type(even)',
            shiftTarget: '.MuiPaper-outlined'
        },
        paperfigure: {
            domain: 'paperfigureqa.allen.ai',
            includePath: 'paperfigureqa.allen.ai/app',
            userMessage: '#chat-scroll-container > div > div:nth-of-type(odd) .MuiPaper-root',
            shiftTarget: '#root'
        },
        scira: {
            domain: 'scira.ai',
            includePath: 'scira.ai/search/',
            userMessage: '.max-w-full .relative',
            shiftTarget: '.sm\\:max-w-2xl'
        },
        exa: {
            domain: 'exa.ai',
            includePath: 'exa.ai/search/',
            userMessage: 'div[data-test-id="UserMessage"]',
            shiftTarget: 'div[data-test-id="ChatPresentation"]'
        },
        consensus: {
            domain: 'consensus.app',
            includePath: 'consensus.app/search/',
            userMessage: '.flex.flex-col.pt-6.w-full.max-w-page h2',
            shiftTarget: '#__next'
        },
        openevidence: {
            domain: 'openevidence.com',
            includePath: 'www.openevidence.com/ask/',
            userMessage: '.brandable--query-bar--container form',
            shiftTarget: '#__next, .brandable--query-bar--container.hide-on-print.follow-up'
        },
        pathway: {
            domain: 'pathway.md',
            includePath: 'www.pathway.md/ai',
            userMessage: '[id] > div > div > div .chakra-text',
        },
        mathgpt: {
            domain: 'math-gpt.org',
            includePath: 'math-gpt.org/chat/',
            userMessage: '.w-full.flex.items-end.flex-col.pb-8.relative',
            shiftTarget: '.overflow-x-hidden, .px-2.flex.flex-col.gap-1'
        },
    };

    function getCurrentConfig() {
        const hostname = window.location.hostname;
        for (const key in SITE_CONFIGS) {
            if (hostname.includes(SITE_CONFIGS[key].domain)) {
                return SITE_CONFIGS[key];
            }
        }
        return null;
    }

    const CURRENT_SITE = getCurrentConfig();
    if (!CURRENT_SITE) return;

    function checkURL(url) {
        if (!CURRENT_SITE.includePath) return false;
        if (Array.isArray(CURRENT_SITE.includePath)) {
            return CURRENT_SITE.includePath.some(path => url.includes(path));
        }
        return url.includes(CURRENT_SITE.includePath);
    }

    const BASE_CONTAINER_CSS = `
        right: 0px; width: ${NAV_WIDTH}px; bottom: 0px; overflow-y: auto;
        z-index: 9999;
        transition: width 0.3s, padding 0.3s, opacity 0.3s, transform 0.3s;
        font-family: Calibri, sans-serif; font-size: 17px; color: CanvasText; position: fixed;text-align: left;
        border-left: 1px solid color-mix(in srgb, CanvasText 15%, transparent);
    `;

    const getShiftStyle = (width, selector = '', isHeader = false) => {
        if (!selector) return '';
        const selectors = selector.split(',');
        const prefixedSelector = selectors.map(s => `body.navigator-expanded ${s.trim()}`).join(', ');
        const preventNesting = isHeader && CURRENT_SITE.shiftTarget
            ? `:not(${CURRENT_SITE.shiftTarget} *)`
            : '';

        return `
            ${selector} {
                transition: margin-right 0.3s ease, max-width 0.3s ease, margin-left 0.3s ease;
            }
            ${prefixedSelector}${preventNesting} {
                margin-left: 0 !important;
                margin-right: ${width}px !important;
                max-width: calc(100% - ${width}px) !important;
            }
        `;
    };

    function updateShiftStyles(shouldInject) {
        let existingStyle = document.getElementById(injectedStyleId);
        if (shouldInject && !existingStyle) {
            const currentWidth = CURRENT_SITE.width || NAV_WIDTH;
            let cssContent = '';

            if (CURRENT_SITE.shiftTarget) {
                cssContent += getShiftStyle(currentWidth, CURRENT_SITE.shiftTarget);
            }

            if (CURRENT_SITE.shiftHeader) {
                cssContent += `
                    body.navigator-collapsed ${CURRENT_SITE.shiftHeader} {
                        margin-right: ${NAV_COLLAPSED_WIDTH}px !important;
                    }
                `;
            }

            if (cssContent) {
                const styleElement = document.createElement('style');
                styleElement.id = injectedStyleId;
                styleElement.textContent = cssContent;
                document.head.appendChild(styleElement);
            }
        } else if (!shouldInject && existingStyle) {
            existingStyle.remove();
        }
    }

    GM_addStyle(`
        .nav-list-item { font-weight: normal; transition: font-weight 0.1s ease; }
        .nav-list-item.active { font-weight: bold !important; background-color: color-mix(in srgb, CanvasText 10%, transparent); }
        @keyframes nav-blink-animation { 0% { opacity: 1; } 50% { opacity: 0.1; } 100% { opacity: 1; } }
        .nav-blink-active { animation: nav-blink-animation 0.5s ease-in-out 4; }

        .nav-item-number {
            display: inline;
            cursor: pointer;
            user-select: none;
        }

        .nav-item-number.bookmarked {
            background-color: #fff59d !important;
            color: black !important;
            padding: 2px 4px;
            border-radius: 3px;
        }

        .nav-version-controls {
            display: inline-flex;
            align-items: center;
            margin-left: 5px;
            gap: 2px;
        }

        .nav-version-btn {
            background: none;
            border: none;
            cursor: pointer;
            font-size: 12px;
            padding: 1px 4px;
            border-radius: 3px;
            color: inherit;
            line-height: 1;
        }

        .nav-version-btn:hover {
            background-color: color-mix(in srgb, CanvasText 10%, transparent);
        }

        .nav-version-btn:disabled {
            opacity: 0.3;
            cursor: not-allowed;
        }

        .nav-version-text {
            font-size: 12px;
            color: color-mix(in srgb, CanvasText 70%, transparent);
            margin: 0 2px;
        }
    `);

    const allUserSelectors = Object.values(SITE_CONFIGS)
            .map(config => config.userMessage)
            .filter(selector => typeof selector === 'string' && selector.length > 0)
            .join(', ');

    if (allUserSelectors) {
        GM_addStyle(`${allUserSelectors} { scroll-margin-top: 10px !important; }`);
    }

    let conversationObserver = null;
    let isCollapsed = false;
    window.navigatorUpdateTimeout = null;

    function updateBodyClassForLayout() {
        const container = document.getElementById('message-nav');
        const content = document.getElementById('message-nav-content');
        if (!container || container.style.display === 'none') {
            document.body.classList.remove('navigator-expanded', 'navigator-collapsed');
            return;
        }
        if (content && content.style.display !== 'none') {
            document.body.classList.add('navigator-expanded');
            document.body.classList.remove('navigator-collapsed');
        } else {
            document.body.classList.remove('navigator-expanded');
            document.body.classList.add('navigator-collapsed');
        }
    }

    function toggleBookmark(index) {
        if (bookmarkedMessages.has(index)) {
            bookmarkedMessages.delete(index);
        } else {
            bookmarkedMessages.add(index);
        }
        updateBookmarkVisuals();
    }

    function updateBookmarkVisuals() {
        const content = document.getElementById('message-nav-content');
        if (!content) return;

        const list = content.querySelector('ul');
        if (!list) return;

        const items = list.querySelectorAll('.nav-list-item');
        items.forEach((item, idx) => {
            const numberContainer = item.querySelector('.nav-item-number');
            if (numberContainer) {
                const index = idx + 1;
                if (bookmarkedMessages.has(index)) {
                    numberContainer.textContent = `${index}`;
                    numberContainer.classList.add('bookmarked');
                } else {
                    numberContainer.textContent = `${index}.`;
                    numberContainer.classList.remove('bookmarked');
                }
            }
        });
    }

    function navigateToMessage(messageIndex) {
        const targetElement = findPromptElementByIndex(messageIndex - 1);
        if (!targetElement) return;


        const content = document.getElementById('message-nav-content');
        if (content) {
            const list = content.querySelector('ul');
            if (list) {
                list.querySelectorAll('.nav-list-item').forEach(li => li.classList.remove('active'));
                const targetItem = list.children[messageIndex - 1];
                if (targetItem) {
                    targetItem.classList.add('active');
                    targetItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
                }
            }
        }

        activeMessageIndex = messageIndex;

        const waitForImages = (element) => {
            const images = element.querySelectorAll('img');
            const promises = Array.from(images).map(img => {
                if (img.complete) return Promise.resolve();
                return new Promise((resolve) => {
                    img.addEventListener('load', resolve);
                    img.addEventListener('error', resolve);
                    setTimeout(resolve, 3000);
                });
            });
            return Promise.all(promises);
        };

        if (CURRENT_SITE.useClick) {
            targetElement.click();
        } else {
            targetElement.scrollIntoView({ behavior: 'instant', block: 'start' });
            waitForImages(targetElement).then(() => {
                targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' });
            });
        }

        const observer = new IntersectionObserver((entries) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    targetElement.classList.add('nav-blink-active');
                    setTimeout(() => targetElement.classList.remove('nav-blink-active'), 2000);
                    observer.unobserve(targetElement);
                }
            });
        }, { threshold: 0.5 });

        observer.observe(targetElement);
    }

    function createContainer() {
        let container = document.getElementById('message-nav');
        if (!container) {
            container = document.createElement('div');
            container.id = 'message-nav';
            container.style.cssText = `top: 0; ${BASE_CONTAINER_CSS}`;
            const header = document.createElement('div');
            Object.assign(header.style, {
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                cursor: 'pointer', position: 'sticky', top: '0', zIndex: '10',
                padding: '15px 10px', backgroundColor: 'Canvas',
                borderBottom : '1px solid color-mix(in srgb, CanvasText 15%, transparent)'
            });

            const navButtonsContainer = document.createElement('div');
            Object.assign(navButtonsContainer.style, {
                display: 'flex', gap: '5px', alignItems: 'center'
            });

            const firstBtn = document.createElement('button');
            Object.assign(firstBtn.style, {
                background: 'none', border: 'none', cursor: 'pointer',
                fontSize: '16px', color: 'inherit', padding: '2px 5px'
            });
            firstBtn.textContent = '|◀';
            firstBtn.title = 'Go to first message';
            firstBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (cachedPrompts.length > 0) {
                    navigateToMessage(1);
                }
            });

            const prevBtn = document.createElement('button');
            Object.assign(prevBtn.style, {
                background: 'none', border: 'none', cursor: 'pointer',
                fontSize: '16px', color: 'inherit', padding: '2px 5px'
            });
            prevBtn.textContent = '◀';
            prevBtn.title = 'Go to previous message';
            prevBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (cachedPrompts.length > 0 && activeMessageIndex > 1) {
                    navigateToMessage(activeMessageIndex - 1);
                }
            });

            const nextBtn = document.createElement('button');
            Object.assign(nextBtn.style, {
                background: 'none', border: 'none', cursor: 'pointer',
                fontSize: '16px', color: 'inherit', padding: '2px 5px'
            });
            nextBtn.textContent = '▶';
            nextBtn.title = 'Go to next message';
            nextBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (cachedPrompts.length > 0 && activeMessageIndex < cachedPrompts.length) {
                    navigateToMessage(activeMessageIndex + 1);
                }
            });

            const lastBtn = document.createElement('button');
            Object.assign(lastBtn.style, {
                background: 'none', border: 'none', cursor: 'pointer',
                fontSize: '16px', color: 'inherit', padding: '2px 5px'
            });
            lastBtn.textContent = '▶|';
            lastBtn.title = 'Go to last message';
            lastBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (cachedPrompts.length > 0) {
                    navigateToMessage(cachedPrompts.length);
                }
            });

            navButtonsContainer.appendChild(firstBtn);
            navButtonsContainer.appendChild(prevBtn);
            navButtonsContainer.appendChild(nextBtn);
            navButtonsContainer.appendChild(lastBtn);

            const toggleBtn = document.createElement('button');
            Object.assign(toggleBtn.style, {
                background: 'none', border: 'none', cursor: 'pointer', fontSize: '20px', color: 'inherit',
            });
            toggleBtn.textContent = 'Close';

            header.appendChild(navButtonsContainer);
            header.appendChild(toggleBtn);

            const content = document.createElement('div');
            content.id = 'message-nav-content';
            content.style.padding = '5px';
            container.appendChild(header);
            container.appendChild(content);
            document.body.appendChild(container);

            const currentWidth = CURRENT_SITE.width || NAV_WIDTH;
            const toggleHandler = (e) => {
                e.stopPropagation();
                isCollapsed = !isCollapsed;
                container.classList.add('transitioning');

                if (!isCollapsed) {
                    Object.assign(container.style, {
                        width: `${currentWidth}px`, bottom: '0px', height: 'auto', top: '0px', right: '0px',
                        borderLeft: '1px solid color-mix(in srgb, CanvasText 15%, transparent)'
                    });
                    Object.assign(header.style, {
                        backgroundColor: 'Canvas', padding: '15px 10px',
                        borderBottom: '1px solid color-mix(in srgb, CanvasText 15%, transparent)',
                        justifyContent: 'space-between'
                    });
                    content.style.display = 'block';
                    navButtonsContainer.style.display = 'flex';
                    toggleBtn.textContent = 'Close';
                } else {
                    Object.assign(container.style, {
                        width: `${NAV_COLLAPSED_WIDTH}px`,
                        borderLeft: 'none', bottom: 'auto', height: 'min-content', right: '10px',
                        top: CURRENT_SITE.collapsedTop || '55px'
                    });
                    Object.assign(header.style, {
                        backgroundColor: 'transparent', borderBottom: 'none', padding: '10px 0',
                        justifyContent: 'center'
                    });
                    content.style.display = 'none';
                    navButtonsContainer.style.display = 'none';
                    toggleBtn.textContent = 'Open';
                }

                updateBodyClassForLayout();
                setTimeout(() => container.classList.remove('transitioning'), 300);
            };
            toggleBtn.addEventListener('click', toggleHandler);
            updateBodyClassForLayout();
        }
        return container;
    }

    function findUserPrompts() {
        if (CURRENT_SITE.customFinder) return CURRENT_SITE.customFinder();
        let prompts = [];
        if (!CURRENT_SITE.userMessage) return prompts;

        const userElements = Array.from(document.querySelectorAll(CURRENT_SITE.userMessage));
        let containerElements = [];

        if (CURRENT_SITE.versionControl && CURRENT_SITE.versionControl.containerSelector) {
            containerElements = Array.from(document.querySelectorAll(CURRENT_SITE.versionControl.containerSelector));
        }

        if (CURRENT_SITE.reverse) {
            userElements.reverse();
            containerElements.reverse();
        }

        userElements.forEach((element, index) => {
            let text = element.textContent.trim();
            if (!text && (element.querySelector('img') || element.querySelector('canvas') || element.querySelector('svg'))) {
                text = "image";
            }

            if (text) {
                const promptData = { element, text };
                if (CURRENT_SITE.versionControl && containerElements[index]) {
                    const versionInfo = getVersionInfo(containerElements[index], CURRENT_SITE.versionControl);
                    if (versionInfo) {
                        promptData.versionInfo = versionInfo;
                    }
                }

                prompts.push(promptData);
            }
        });

        return prompts;
    }

    function findPromptElementByIndex(targetIndex) {
        if (CURRENT_SITE.customFinder) {
            const prompts = CURRENT_SITE.customFinder();
            return prompts[targetIndex] ? prompts[targetIndex].element : null;
        }
        if (!CURRENT_SITE.userMessage) return null;
        const elements = Array.from(document.querySelectorAll(CURRENT_SITE.userMessage));
        if (CURRENT_SITE.reverse) elements.reverse();
        return elements[targetIndex] || null;
    }

    function createListItem(prompt, index) {
        const listItem = document.createElement('li');
        const preview = prompt.text.length > 80 ? prompt.text.slice(0, 80) + '...' : prompt.text;

        const numberContainer = document.createElement('span');
        numberContainer.className = 'nav-item-number';
        numberContainer.style.cursor = 'pointer';

        if (bookmarkedMessages.has(index)) {
            numberContainer.textContent = `${index}`;
            numberContainer.classList.add('bookmarked');
        } else {
            numberContainer.textContent = `${index}.`;
        }

        numberContainer.addEventListener('click', (e) => {
            e.stopPropagation();
            toggleBookmark(index);
        });

        const textSpan = document.createElement('span');
        textSpan.textContent = ` ${preview}`;

        listItem.appendChild(numberContainer);
        listItem.appendChild(textSpan);

        if (prompt.versionInfo && prompt.versionInfo.hasMultipleVersions) {
            const versionControls = document.createElement('span');
            versionControls.className = 'nav-version-controls';

            const prevVersionBtn = document.createElement('button');
            prevVersionBtn.className = 'nav-version-btn';
            prevVersionBtn.textContent = '◀';
            prevVersionBtn.title = 'Previous version';
            prevVersionBtn.disabled = !prompt.versionInfo.prevButton || prompt.versionInfo.prevButton.disabled;

            prevVersionBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (prompt.versionInfo.prevButton && !prompt.versionInfo.prevButton.disabled) {
                    prompt.versionInfo.prevButton.click();
                    setTimeout(() => updateMessageList(true), 300);
                }
            });

            const versionText = document.createElement('span');
            versionText.className = 'nav-version-text';
            versionText.textContent = `${prompt.versionInfo.currentVersion}/${prompt.versionInfo.totalVersions}`;

            const nextVersionBtn = document.createElement('button');
            nextVersionBtn.className = 'nav-version-btn';
            nextVersionBtn.textContent = '▶';
            nextVersionBtn.title = 'Next version';
            nextVersionBtn.disabled = !prompt.versionInfo.nextButton || prompt.versionInfo.nextButton.disabled;

            nextVersionBtn.addEventListener('click', (e) => {
                e.stopPropagation();
                if (prompt.versionInfo.nextButton && !prompt.versionInfo.nextButton.disabled) {
                    prompt.versionInfo.nextButton.click();
                    setTimeout(() => updateMessageList(true), 300);
                }
            });

            versionControls.appendChild(prevVersionBtn);
            versionControls.appendChild(versionText);
            versionControls.appendChild(nextVersionBtn);

            listItem.appendChild(versionControls);
        }

        Object.assign(listItem.style, { cursor: 'pointer', padding: '5px 0px 5px 5px' });
        listItem.classList.add('nav-list-item');
        if (index === activeMessageIndex) listItem.classList.add('active');

        textSpan.addEventListener('click', () => {
            navigateToMessage(index);
        });

        return listItem;
    }

    function updateMessageList(forceUpdate = false) {
        const currentUrl = window.location.href;
        let container = document.getElementById('message-nav');

        if (currentUrl !== lastUrl) {
            lastUrl = currentUrl;
            lastPromptsContent = "";
            activeMessageIndex = -1;
            cachedPrompts = [];
            bookmarkedMessages.clear();
            forceUpdate = true;
            if (loadingTimeout) {
                clearTimeout(loadingTimeout);
                loadingTimeout = null;
            }
        }

        const shouldShow = checkURL(currentUrl);
        updateShiftStyles(shouldShow);

        if (!shouldShow) {
            if (container) container.style.display = 'none';
            document.body.classList.remove('navigator-expanded', 'navigator-collapsed');
            updateBodyClassForLayout();
            return;
        }

        const activeContainer = createContainer();
        activeContainer.style.display = 'block';
        updateBodyClassForLayout();

        const content = document.getElementById('message-nav-content');
        if (!content) return;

        let list = content.querySelector('ul');
        if (!list) {
            list = document.createElement('ul');
            list.style.cssText = 'padding: 0; margin: 0; list-style: none;';
            content.appendChild(list);
        }

        const prompts = findUserPrompts();
        const currentPromptsContent = prompts.map(p => p.text).join('|');

        if (!forceUpdate && currentPromptsContent === lastPromptsContent) return;

        lastPromptsContent = currentPromptsContent;
        cachedPrompts = prompts;

        while (list.firstChild) list.removeChild(list.firstChild);

        if (prompts.length === 0) {
            activeMessageIndex = -1;
            const noContent = document.createElement('div');
            noContent.id = 'nav-status-display';
            noContent.textContent = 'Loading...';
            noContent.style.cssText = 'color: #999; font-style: italic; text-align: center; padding: 15px 0;';
            list.appendChild(noContent);

            if (!loadingTimeout) {
                loadingTimeout = setTimeout(() => {
                    const statusDiv = document.getElementById('nav-status-display');
                    if (statusDiv && cachedPrompts.length === 0) {
                        statusDiv.textContent = 'No message found';
                    }
                }, 5000);
            }
        } else {
            if (loadingTimeout) {
                clearTimeout(loadingTimeout);
                loadingTimeout = null;
            }
            prompts.forEach((prompt, index) => {
                const listItem = createListItem(prompt, index + 1);
                list.appendChild(listItem);
            });
        }
    }

    function startUrlWatcher() {
        if (!CURRENT_SITE.fastUpdate) return;
        if (urlCheckInterval) clearInterval(urlCheckInterval);
        urlCheckInterval = setInterval(() => {
            const currentUrl = window.location.href;
            if (currentUrl !== lastUrl) updateMessageList(true);
        }, 300);
    }

    function observeConversation() {
        if (conversationObserver) conversationObserver.disconnect();
        const debounceTime = CURRENT_SITE.debounceTime || DEBOUNCE_TIME;
        conversationObserver = new MutationObserver(() => {
            clearTimeout(window.navigatorUpdateTimeout);
            window.navigatorUpdateTimeout = setTimeout(() => updateMessageList(), debounceTime);
        });
        conversationObserver.observe(document.body, { childList: true, subtree: true });

        window.addEventListener('popstate', () => {
            lastPromptsContent = ""; cachedPrompts = []; updateMessageList(true);
        });

        const originalPushState = history.pushState;
        history.pushState = function() {
            originalPushState.apply(this, arguments);
            lastPromptsContent = ""; cachedPrompts = [];
            setTimeout(() => updateMessageList(true), 100);
        };
    }

    setTimeout(() => { updateMessageList(true); startUrlWatcher(); }, 1000);
    observeConversation();
})();