export const createSidebarWorkspaceRuntime = (dependencies = {}) => {
  const {
    cssEscape,
    currentDocumentId,
    escapeHtml,
    parseJsonScript,
    setCommandPending,
    sidebarShellRuntimeFunction,
  } = dependencies;
  const MNOTE_SIDEBAR_TREE_MODE_KEY = 'mnote.sidebar.tree.mode';
  const MNOTE_RECENT_LOCAL_ROOTS_KEY_PREFIX = 'mnote.localFolder.recentRoots:';
  const MNOTE_LAST_CLOUD_WORKSPACE_KEY = 'mnote.workspace.lastCloudWorkspaceId';

  function normalizeSidebarTreeMode(value) {
    var mode = String(value || '').trim();
    return mode === 'filetree' ? 'filetree' : 'page';
  }

  function readStoredSidebarTreeMode() {
    var runtimeFn = sidebarShellRuntimeFunction('readStoredSidebarTreeMode');
    if (runtimeFn) return runtimeFn();
    var params = new URLSearchParams(window.location.search);
    var fromUrl = normalizeSidebarTreeMode(params.get('treeView') || params.get('sidebarTree'));
    if (params.has('treeView') || params.has('sidebarTree')) return fromUrl;
    try {
      var stored = window.sessionStorage ? window.sessionStorage.getItem(MNOTE_SIDEBAR_TREE_MODE_KEY) : '';
      return normalizeSidebarTreeMode(stored);
    } catch (_) {
      return 'page';
    }
  }

  function persistSidebarTreeMode(mode) {
    var runtimeFn = sidebarShellRuntimeFunction('persistSidebarTreeMode');
    if (runtimeFn) return runtimeFn(mode);
    var normalized = normalizeSidebarTreeMode(mode);
    document.documentElement.setAttribute('data-mnote-sidebar-tree-mode', normalized);
    try {
      if (window.sessionStorage) window.sessionStorage.setItem(MNOTE_SIDEBAR_TREE_MODE_KEY, normalized);
    } catch (_) {}
    return normalized;
  }

  function activeSidebarTreeMode() {
    var runtimeFn = sidebarShellRuntimeFunction('activeSidebarTreeMode');
    if (runtimeFn) return runtimeFn();
    var active = document.querySelector('[data-mnote-sidebar-tree-tab][aria-selected="true"]');
    if (active instanceof HTMLElement) {
      return normalizeSidebarTreeMode(active.getAttribute('data-mnote-sidebar-tree-tab'));
    }
    return readStoredSidebarTreeMode();
  }

  function resolveWorkspaceId(trigger) {
    var direct = (trigger.getAttribute('data-workspace-id') || '').trim();
    if (direct) return direct;
    var root = trigger.closest('[data-workspace-id]');
    if (root) {
      var value = (root.getAttribute('data-workspace-id') || '').trim();
      if (value) return value;
    }
    var documentId = currentDocumentId();
    if (documentId) {
      var shell = document.querySelector('.document-shell[data-document-id="' + cssEscape(documentId) + '"][data-workspace-id]');
      if (shell instanceof HTMLElement) {
        var shellWorkspaceId = (shell.getAttribute('data-workspace-id') || '').trim();
        if (shellWorkspaceId) return shellWorkspaceId;
      }
    }
    var activePane = document.querySelector('[data-pane-visible="true"][data-pane-workspace-id]');
    if (activePane instanceof HTMLElement) {
      var paneWorkspaceId = (activePane.getAttribute('data-pane-workspace-id') || '').trim();
      if (paneWorkspaceId) return paneWorkspaceId;
    }
    var anyDocumentShell = document.querySelector('.document-shell[data-workspace-id]');
    if (anyDocumentShell instanceof HTMLElement) {
      var documentWorkspaceId = (anyDocumentShell.getAttribute('data-workspace-id') || '').trim();
      if (documentWorkspaceId) return documentWorkspaceId;
    }
    var fromDom = document.querySelector('[data-workspace-id]');
    if (fromDom instanceof HTMLElement) {
      var domWorkspaceId = (fromDom.getAttribute('data-workspace-id') || '').trim();
      if (domWorkspaceId) return domWorkspaceId;
    }
    return (new URLSearchParams(window.location.search).get('workspaceId') || 'default').trim() || 'default';
  }

  function currentWorkspaceId() {
    return resolveWorkspaceId(document.body);
  }

  function currentSourceKind() {
    var params = new URLSearchParams(window.location.search);
    var fromUrl = (params.get('sourceKind') || '').trim();
    if (fromUrl) return fromUrl;
    var fromBody = document.body instanceof HTMLElement ? (document.body.getAttribute('data-mnote-source-kind') || '').trim() : '';
    if (fromBody) return fromBody;
    if (
      window.location.pathname === '/' &&
      !(params.get('workspaceId') || '').trim() &&
      !(params.get('rootUri') || '').trim() &&
      !(params.get('pageId') || '').trim()
    ) {
      return 'local_folder';
    }
    return 'convex_workspace';
  }

  function currentRootUri() {
    var params = new URLSearchParams(window.location.search);
    var fromUrl = (params.get('rootUri') || '').trim();
    if (fromUrl) return fromUrl;
    return document.body instanceof HTMLElement ? (document.body.getAttribute('data-mnote-root-uri') || '').trim() : '';
  }

  function rememberCloudWorkspaceId(workspaceId) {
    var normalized = String(workspaceId || '').trim();
    if (!normalized || normalized === 'local-folder' || normalized === 'default' || normalized.indexOf('local-ws:') === 0) return;
    try {
      if (window.localStorage) window.localStorage.setItem(MNOTE_LAST_CLOUD_WORKSPACE_KEY, normalized);
    } catch (_) {}
  }

  function readCurrentCloudWorkspaceIdFromPage() {
    if (currentSourceKind() === 'local_folder') return '';
    var params = new URLSearchParams(window.location.search);
    var fromUrl = (params.get('workspaceId') || '').trim();
    if (fromUrl && fromUrl !== 'default' && fromUrl.indexOf('local-ws:') !== 0) return fromUrl;
    var fromDom = document.querySelector('[data-workspace-id]');
    if (fromDom instanceof HTMLElement) {
      var value = (fromDom.getAttribute('data-workspace-id') || '').trim();
      if (value && value !== 'local-folder' && value !== 'default' && value.indexOf('local-ws:') !== 0) return value;
    }
    return '';
  }

  function rememberCurrentCloudWorkspaceId() {
    rememberCloudWorkspaceId(readCurrentCloudWorkspaceIdFromPage());
  }

  function readLastCloudWorkspaceId() {
    try {
      var stored = window.localStorage ? window.localStorage.getItem(MNOTE_LAST_CLOUD_WORKSPACE_KEY) : '';
      if (stored && stored.trim() && stored.trim() !== 'default' && stored.trim().indexOf('local-ws:') !== 0) return stored.trim();
    } catch (_) {}
    var params = new URLSearchParams(window.location.search);
    var fromUrl = (params.get('workspaceId') || '').trim();
    if (fromUrl && currentSourceKind() !== 'local_folder' && fromUrl.indexOf('local-ws:') !== 0) return fromUrl;
    var fromDom = document.querySelector('[data-workspace-id]');
    if (fromDom instanceof HTMLElement) {
      var value = (fromDom.getAttribute('data-workspace-id') || '').trim();
      if (value && value !== 'local-folder' && value.indexOf('local-ws:') !== 0) return value;
    }
    return '';
  }

  function copyWorkspaceSourceParams(targetUrl) {
    var params = new URLSearchParams(window.location.search);
    ['sourceKind', 'rootUri', 'fileTreeScope', 'secondaryDocumentId', 'secondarySourceKind', 'secondaryRootUri'].forEach(function(name) {
      var value = (params.get(name) || '').trim();
      if (value) targetUrl.searchParams.set(name, value);
    });
    var sourceKind = currentSourceKind();
    var rootUri = currentRootUri();
    if (sourceKind && !targetUrl.searchParams.get('sourceKind')) targetUrl.searchParams.set('sourceKind', sourceKind);
    if (rootUri && !targetUrl.searchParams.get('rootUri')) targetUrl.searchParams.set('rootUri', rootUri);
  }

  function currentWorkspaceSourcePayload() {
    var params = new URLSearchParams(window.location.search);
    var payload = {};
    ['sourceKind', 'rootUri'].forEach(function(name) {
      var value = (params.get(name) || '').trim();
      if (value) payload[name] = value;
    });
    var sourceKind = currentSourceKind();
    var rootUri = currentRootUri();
    if (sourceKind && !payload.sourceKind) payload.sourceKind = sourceKind;
    if (rootUri && !payload.rootUri) payload.rootUri = rootUri;
    return payload;
  }

  function currentActorStorageId() {
    var fromBody = document.body instanceof HTMLElement ? (document.body.getAttribute('data-mnote-actor-id') || '').trim() : '';
    if (fromBody && fromBody !== 'anonymous') return fromBody;
    return '';
  }

  function recentLocalRootsStorageKey() {
    var actorId = currentActorStorageId();
    return actorId ? MNOTE_RECENT_LOCAL_ROOTS_KEY_PREFIX + encodeURIComponent(actorId) : '';
  }

  function readRecentLocalRoots() {
    try {
      var storageKey = recentLocalRootsStorageKey();
      if (!storageKey) return [];
      var raw = window.localStorage ? window.localStorage.getItem(storageKey) : '';
      var parsed = raw ? JSON.parse(raw) : [];
      return Array.isArray(parsed) ? parsed.filter(function(value) {
        return typeof value === 'string' && value.trim();
      }).slice(0, 10) : [];
    } catch (_) {
      return [];
    }
  }

  function rememberLocalRoot(rootUri) {
    try {
      if (!window.localStorage) return;
      var storageKey = recentLocalRootsStorageKey();
      if (!storageKey) return;
      var roots = readRecentLocalRoots().filter(function(value) { return value !== rootUri; });
      roots.unshift(rootUri);
      window.localStorage.setItem(storageKey, JSON.stringify(roots.slice(0, 10)));
    } catch (_) {}
  }

  function pathToFileRootUri(value) {
    var trimmed = String(value || '').trim();
    if (!trimmed) return '';
    if (/^file:\/\//i.test(trimmed)) return trimmed;
    if (trimmed.charAt(0) !== '/') return '';
    return 'file://' + trimmed.split('/').map(function(part, index) {
      return index === 0 ? '' : encodeURIComponent(part);
    }).join('/');
  }

  function fileRootUriToPathInput(rootUri) {
    var value = String(rootUri || '').replace(/^file:\/\//, '');
    try {
      return decodeURIComponent(value);
    } catch (_) {
      return value;
    }
  }

  function recentLocalRootLabel(rootUri) {
    var label = fileRootUriToPathInput(rootUri);
    return label || '本地文件夹';
  }

  function normalizeGrantedLocalFolderRootUri(grant) {
    var rootUri = String(grant && grant.rootUri || '').trim();
    if (rootUri && /^file:\/\//i.test(rootUri)) return rootUri;
    var rootPath = String(grant && grant.rootPath || '').trim();
    if (rootPath) return pathToFileRootUri(rootPath);
    if (rootUri) return pathToFileRootUri(rootUri);
    return '';
  }

  function isDefaultWorkspaceAutoGrant(grant) {
    var source = String(grant && grant.source || '').trim();
    var workspaceId = String(grant && grant.workspaceId || '').trim();
    var rootUri = String(grant && grant.rootUri || '').trim();
    var permission = String(grant && grant.permission || '').trim();
    var createdBy = String(grant && (grant.createdBy || grant.ownerUserId) || '').trim();
    var targetUser = String(grant && (grant.userId || grant.targetUserId) || '').trim();
    return source === 'auto'
      && workspaceId
      && permission === 'write'
      && createdBy === targetUser
      && /^local:\/\/users\/.+\/workspaces\/my-space$/.test(rootUri);
  }

  function openLocalFolderRoot(rootUri) {
    if (currentSourceKind() !== 'local_folder') {
      rememberCurrentCloudWorkspaceId();
    }
    rememberLocalRoot(rootUri);
    var targetUrl = new URL('/', window.location.origin);
    targetUrl.searchParams.set('treeView', 'filetree');
    targetUrl.searchParams.set('sourceKind', 'local_folder');
    targetUrl.searchParams.set('rootUri', rootUri);
    window.location.href = targetUrl.toString();
  }

  function switchToCloudWorkspace() {
    var targetUrl = new URL('/', window.location.origin);
    targetUrl.searchParams.set('treeView', activeSidebarTreeMode() || 'filetree');
    targetUrl.searchParams.set('mnoteHome', '1');
    window.location.href = targetUrl.toString();
  }

  function closeTrashModal() {
    var modal = document.querySelector('[data-testid="mnote-trash-modal"]');
    if (!modal) return;
    var workbench = modal.querySelector('[data-testid="mnote-trash-workbench"]');
    if (workbench && workbench.__mnoteTrashEventSource && typeof workbench.__mnoteTrashEventSource.close === 'function') {
      workbench.__mnoteTrashEventSource.close();
    }
    var fileScrollTop = Number(modal.getAttribute('data-file-scroll-top') || '0');
    var fileRoot = document.getElementById('sidebar-file-tree-root');
    if (fileRoot instanceof HTMLElement && Number.isFinite(fileScrollTop)) fileRoot.scrollTop = fileScrollTop;
    if (modal.parentElement) modal.parentElement.removeChild(modal);
    document.documentElement.removeAttribute('data-mnote-trash-modal-open');
  }

  function executeTrashWorkbenchScripts(parsed) {
    parsed.querySelectorAll('script').forEach(function(script) {
      var nextScript = document.createElement('script');
      Array.from(script.attributes || []).forEach(function(attr) {
        nextScript.setAttribute(attr.name, attr.value);
      });
      nextScript.textContent = script.textContent || '';
      document.body.appendChild(nextScript);
      if (nextScript.parentElement) nextScript.parentElement.removeChild(nextScript);
    });
  }

  function renderLocalFolderTrashPlaceholder(content, rootUri) {
    content.innerHTML = [
      '<section class="mnote-trash-workbench" data-testid="mnote-trash-workbench" data-trash-source-kind="local_folder">',
      '<header class="mnote-trash-header"><h1>本地文件夹垃圾箱</h1>',
      '<p>本地删除项保存在当前目录的 <code>.mnote/trash</code> 与 <code>.mnote/trash-index.json</code> 中。</p></header>',
      '<section class="mnote-trash-section"><div class="mnote-trash-empty">当前弹窗已保持在本地文件夹上下文：' + escapeHtml(rootUri || '未选择本地目录') + '</div></section>',
      '</section>'
    ].join('');
  }

  function openTrashModal(trigger) {
    var existing = document.querySelector('[data-testid="mnote-trash-modal"]');
    if (existing) return;
    var fileRoot = document.getElementById('sidebar-file-tree-root');
    var activeRow = document.querySelector('#sidebar-file-tree-root .tree-row[data-selected="true"], #sidebar-tree-root .tree-row[data-active="true"]');
    var overlay = document.createElement('div');
    overlay.className = 'mnote-trash-modal';
    overlay.setAttribute('data-testid', 'mnote-trash-modal');
    overlay.setAttribute('role', 'dialog');
    overlay.setAttribute('aria-modal', 'true');
    overlay.setAttribute('aria-label', '垃圾箱');
    overlay.setAttribute('data-file-scroll-top', fileRoot instanceof HTMLElement ? String(fileRoot.scrollTop) : '0');
    if (activeRow instanceof HTMLElement) {
      overlay.setAttribute('data-active-row-id', activeRow.getAttribute('data-row-id') || activeRow.getAttribute('data-node-id') || '');
    }
    overlay.innerHTML = '<div class="mnote-trash-modal__backdrop" data-mnote-trash-modal-close="true"></div>' +
      '<section class="mnote-trash-modal__panel">' +
      '<button type="button" class="mnote-trash-modal__close" data-testid="mnote-trash-modal-close" data-mnote-trash-modal-close="true" aria-label="关闭垃圾箱">×</button>' +
      '<div class="mnote-trash-modal__content" data-testid="mnote-trash-modal-content"><div class="mnote-trash-empty">正在加载垃圾箱...</div></div>' +
      '</section>';
    document.body.appendChild(overlay);
    document.documentElement.setAttribute('data-mnote-trash-modal-open', 'true');
    var content = overlay.querySelector('[data-testid="mnote-trash-modal-content"]');
    var sourceKind = currentSourceKind();
    var workspaceId = resolveWorkspaceId(trigger || document.body);
    var url = new URL('/trash', window.location.origin);
    if (sourceKind === 'local_folder') {
      var rootUri = currentRootUri();
      if (!rootUri) {
        renderLocalFolderTrashPlaceholder(content, '');
        return;
      }
      url.searchParams.set('sourceKind', 'local_folder');
      url.searchParams.set('rootUri', rootUri);
    } else if (workspaceId) {
      url.searchParams.set('workspaceId', workspaceId);
    }
    fetch(url.toString(), { headers: { 'x-mnote-trash-modal': '1' } }).then(function(response) {
      return response.text().then(function(html) {
        if (!response.ok) throw new Error('trash_modal_load_failed_' + response.status);
        var parsed = new DOMParser().parseFromString(html, 'text/html');
        var workbench = parsed.querySelector('[data-testid="mnote-trash-workbench"]');
        if (!workbench) throw new Error('trash_modal_missing_workbench');
        content.innerHTML = '';
        content.appendChild(workbench);
        executeTrashWorkbenchScripts(parsed);
      });
    }).catch(function(error) {
      content.innerHTML = '<div class="mnote-trash-empty" data-testid="mnote-trash-modal-error">' + escapeHtml(error && error.message ? error.message : String(error)) + '</div>';
    });
  }

  function closeLocalFolderDialog() {
    var existing = document.querySelector('[data-testid="mnote-local-folder-dialog"]');
    if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
  }

  function readPathFromDirectoryFiles(files) {
    var first = files && files.length ? files[0] : null;
    if (!first) return '';
    var rawPath = typeof first.path === 'string' ? first.path : '';
    var relative = typeof first.webkitRelativePath === 'string' ? first.webkitRelativePath : '';
    if (rawPath && relative) {
      var suffix = relative.split('/').filter(Boolean).join('/');
      if (suffix && rawPath.endsWith(suffix)) {
        return rawPath.slice(0, rawPath.length - suffix.length).replace(/[\/\\]$/, '');
      }
    }
    if (rawPath) return rawPath;
    return '';
  }

  function requestBrowserFolderChoice(statusNode) {
    return new Promise(function(resolve) {
      var input = document.createElement('input');
      input.type = 'file';
      input.multiple = true;
      input.setAttribute('webkitdirectory', '');
      input.setAttribute('directory', '');
      input.style.position = 'fixed';
      input.style.left = '-9999px';
      input.addEventListener('change', function() {
        var selectedPath = readPathFromDirectoryFiles(input.files || []);
        if (input.parentElement) input.parentElement.removeChild(input);
        if (!selectedPath && statusNode instanceof HTMLElement) {
          statusNode.textContent = '当前浏览器没有暴露本机绝对路径，请在下方输入路径。';
        }
        resolve(selectedPath);
      }, { once: true });
      document.body.appendChild(input);
      input.click();
    });
  }

  async function requestNativeFolderChoice(statusNode) {
    var desktopPicker = window.__mnoteDesktop && typeof window.__mnoteDesktop.selectLocalFolder === 'function'
      ? window.__mnoteDesktop.selectLocalFolder
      : null;
    if (desktopPicker) {
      var selected = await desktopPicker();
      return typeof selected === 'string' ? selected : '';
    }
    if (typeof window.showDirectoryPicker === 'function') {
      var handle = await window.showDirectoryPicker({ mode: 'read' });
      var handlePath = handle && (handle.path || handle.mnotePath || handle.nativePath);
      if (typeof handlePath === 'string' && handlePath.trim()) return handlePath;
      if (statusNode instanceof HTMLElement) {
        statusNode.textContent = '已选择“' + (handle && handle.name ? handle.name : '文件夹') + '”，但浏览器没有暴露本机绝对路径，请在下方确认路径。';
      }
      return '';
    }
    return requestBrowserFolderChoice(statusNode);
  }

  function openLocalFolderDialog(initialMessage) {
    closeLocalFolderDialog();
    var recent = readRecentLocalRoots();
    var dialog = document.createElement('div');
    dialog.className = 'mnote-local-folder-dialog';
    dialog.setAttribute('data-testid', 'mnote-local-folder-dialog');
    dialog.setAttribute('role', 'dialog');
    dialog.setAttribute('aria-modal', 'true');
    dialog.style.position = 'fixed';
    dialog.style.inset = '0';
    dialog.style.zIndex = '2147483646';
    dialog.style.background = 'rgba(15, 23, 42, 0.28)';
    dialog.style.display = 'flex';
    dialog.style.alignItems = 'center';
    dialog.style.justifyContent = 'center';
    var card = document.createElement('div');
    card.className = 'mnote-local-folder-dialog__card';
    card.style.width = 'min(640px, calc(100vw - 32px))';
    card.style.background = '#fff';
    card.style.border = '1px solid rgba(27, 28, 28, 0.12)';
    card.style.borderRadius = '8px';
    card.style.padding = '16px';
    card.style.boxShadow = '0 18px 48px rgba(15, 23, 42, 0.22)';
    card.style.display = 'grid';
    card.style.gap = '12px';
    var title = document.createElement('h2');
    title.textContent = '打开本地文件夹';
    title.style.margin = '0';
    title.style.fontSize = '18px';
    title.style.lineHeight = '1.4';
    var status = document.createElement('p');
    status.className = 'mnote-local-folder-dialog__status';
    status.setAttribute('data-testid', 'mnote-local-folder-status');
    status.textContent = initialMessage || '选择一个本机文件夹，或输入绝对路径。';
    status.style.margin = '0';
    status.style.color = '#4b5563';
    status.style.fontSize = '13px';
    var input = document.createElement('input');
    input.type = 'text';
    input.autocomplete = 'off';
    input.spellcheck = false;
    input.placeholder = '/mnt/Data1T/mnote/design/04-tree-domain/done';
    input.setAttribute('data-testid', 'mnote-local-folder-path-input');
    input.value = recent.length ? fileRootUriToPathInput(recent[0]) : '';
    input.style.width = '100%';
    input.style.boxSizing = 'border-box';
    input.style.border = '1px solid rgba(27, 28, 28, 0.18)';
    input.style.borderRadius = '6px';
    input.style.padding = '10px 12px';
    input.style.fontSize = '14px';
    var actions = document.createElement('div');
    actions.className = 'mnote-local-folder-dialog__actions';
    actions.style.display = 'flex';
    actions.style.gap = '8px';
    actions.style.justifyContent = 'flex-end';
    var choose = document.createElement('button');
    choose.type = 'button';
    choose.textContent = '选择文件夹';
    choose.setAttribute('data-testid', 'mnote-local-folder-native-picker');
    var cancel = document.createElement('button');
    cancel.type = 'button';
    cancel.textContent = '取消';
    var confirm = document.createElement('button');
    confirm.type = 'button';
    confirm.textContent = '打开';
    confirm.setAttribute('data-testid', 'mnote-local-folder-open-confirm');
    [choose, cancel, confirm].forEach(function(button) {
      button.style.border = '1px solid rgba(27, 28, 28, 0.14)';
      button.style.borderRadius = '6px';
      button.style.padding = '8px 12px';
      button.style.background = '#fff';
      button.style.cursor = 'pointer';
      button.style.fontSize = '14px';
    });
    function submit() {
      var rootUri = pathToFileRootUri(input.value);
      if (!rootUri) {
        status.textContent = '请输入以 / 开头的绝对路径，或 file:// URI。';
        input.focus();
        return;
      }
      closeLocalFolderDialog();
      openLocalFolderRoot(rootUri);
    }
    choose.addEventListener('click', function(event) {
      event.preventDefault();
      requestNativeFolderChoice(status).then(function(selectedPath) {
        if (selectedPath) {
          input.value = selectedPath;
          submit();
        }
      }).catch(function(error) {
        status.textContent = error && error.name === 'AbortError'
          ? '已取消选择。'
          : '无法打开系统文件夹选择器，请输入路径。';
      });
    });
    cancel.addEventListener('click', function(event) {
      event.preventDefault();
      closeLocalFolderDialog();
    });
    confirm.addEventListener('click', function(event) {
      event.preventDefault();
      submit();
    });
    input.addEventListener('keydown', function(event) {
      if (event.key === 'Enter') {
        event.preventDefault();
        submit();
      }
    });
    actions.appendChild(choose);
    actions.appendChild(cancel);
    actions.appendChild(confirm);
    card.appendChild(title);
    card.appendChild(status);
    card.appendChild(input);
    var authorizedSection = document.createElement('div');
    authorizedSection.className = 'mnote-local-folder-dialog__authorized';
    authorizedSection.setAttribute('data-testid', 'mnote-local-folder-authorized-roots');
    authorizedSection.hidden = true;
    card.appendChild(authorizedSection);
    fetch('/api/user/access-policy', {
      method: 'GET',
      headers: { 'accept': 'application/json' },
      credentials: 'include'
    }).then(function(response) {
      return response.ok ? response.json() : null;
    }).then(function(payload) {
      var grants = payload && Array.isArray(payload.grants) ? payload.grants : [];
      var activeGrants = grants.filter(function(grant) {
        return grant && grant.active !== false && grant.status !== 'revoked';
      });
      if (!activeGrants.length) return;
      authorizedSection.hidden = false;
      var authorizedTitle = document.createElement('div');
      authorizedTitle.style.fontSize = '12px';
      authorizedTitle.style.color = '#6b7280';
      authorizedTitle.textContent = '已授权文件夹';
      var authorizedList = document.createElement('div');
      authorizedList.className = 'mnote-local-folder-dialog__recent';
      activeGrants.slice(0, 8).forEach(function(grant) {
        if (isDefaultWorkspaceAutoGrant(grant)) return;
        var rootUri = normalizeGrantedLocalFolderRootUri(grant);
        if (!rootUri) return;
        var button = document.createElement('button');
        button.type = 'button';
        button.setAttribute('data-testid', 'mnote-local-folder-authorized-root');
        button.textContent = fileRootUriToPathInput(rootUri);
        button.addEventListener('click', function(event) {
          event.preventDefault();
          closeLocalFolderDialog();
          openLocalFolderRoot(rootUri);
        });
        authorizedList.appendChild(button);
      });
      if (!authorizedList.childElementCount) return;
      authorizedSection.appendChild(authorizedTitle);
      authorizedSection.appendChild(authorizedList);
    }).catch(function() {});
    if (recent.length) {
      var recentTitle = document.createElement('div');
      recentTitle.style.fontSize = '12px';
      recentTitle.style.color = '#6b7280';
      recentTitle.textContent = '最近使用';
      card.appendChild(recentTitle);
      var recentList = document.createElement('div');
      recentList.className = 'mnote-local-folder-dialog__recent';
      recent.slice(0, 5).forEach(function(rootUri) {
        var button = document.createElement('button');
        button.type = 'button';
        button.textContent = recentLocalRootLabel(rootUri);
        button.addEventListener('click', function(event) {
          event.preventDefault();
          closeLocalFolderDialog();
          openLocalFolderRoot(rootUri);
        });
        recentList.appendChild(button);
      });
      card.appendChild(recentList);
    }
    card.appendChild(actions);
    dialog.appendChild(card);
    dialog.addEventListener('click', function(event) {
      if (event.target === dialog) closeLocalFolderDialog();
    });
    document.body.appendChild(dialog);
    input.focus();
    input.select();
  }

  function requestOpenLocalFolder() {
    openLocalFolderDialog('');
  }

  async function createDefaultLocalWorkspace(trigger) {
    setCommandPending(trigger, true);
    try {
      var response = await fetch('/api/local-folder/workspaces/default', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: '{}'
      });
      var payload = await response.json().catch(function() { return null; });
      if (!response.ok) {
        throw new Error((payload && payload.message) || ('local_workspace_create_failed_' + response.status));
      }
      var workspace = payload && payload.workspace || {};
      var rootUri = String(workspace.rootUri || '').trim();
      if (!rootUri) throw new Error('local_workspace_create_missing_root_uri');
      openLocalFolderRoot(rootUri);
    } catch (error) {
      var status = document.querySelector('[data-testid="mnote-local-folder-status"]');
      if (status instanceof HTMLElement) {
        status.textContent = error && error.message ? error.message : String(error);
      } else {
        openLocalFolderDialog(error && error.message ? error.message : String(error));
      }
    } finally {
      setCommandPending(trigger, false);
    }
  }

  function autoOpenRecentLocalRootOnHome() {
    if (window.location.pathname !== '/') return false;
    var params = new URLSearchParams(window.location.search);
    if ((params.get('sourceKind') || '').trim()) return false;
    if ((params.get('rootUri') || '').trim()) return false;
    if ((params.get('workspaceId') || '').trim()) return false;
    if ((params.get('pageId') || '').trim()) return false;
    if ((params.get('mnoteHome') || '').trim() === '1') return false;
    var recent = readRecentLocalRoots();
    if (!recent.length) return false;
    openLocalFolderRoot(recent[0]);
    return true;
  }

  function closeWorkspaceSourceMenu() {
    var existing = document.querySelector('[data-testid="mnote-workspace-source-menu"]');
    if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
    document.querySelectorAll('[data-testid="mnote-workspace-source-trigger"]').forEach(function(trigger) {
      if (trigger instanceof HTMLElement) trigger.setAttribute('aria-expanded', 'false');
    });
  }

  function workspaceSourceLabel(rootUri) {
    var label = String(rootUri || '').replace(/^file:\/\//, '');
    try {
      label = decodeURIComponent(label);
    } catch (_) {}
    return label || '本地文件夹';
  }

  function openWorkspaceSourceMenu(trigger) {
    closeWorkspaceSourceMenu();
    if (!(trigger instanceof HTMLElement)) return;
    trigger.setAttribute('aria-expanded', 'true');
    var menu = document.createElement('div');
    menu.className = 'mnote-workspace-source-menu';
    menu.setAttribute('data-testid', 'mnote-workspace-source-menu');
    menu.setAttribute('role', 'menu');
    var cloudButton = document.createElement('button');
    cloudButton.type = 'button';
    cloudButton.className = 'mnote-workspace-source-menu__item';
    cloudButton.setAttribute('data-testid', 'mnote-switch-cloud-workspace');
    cloudButton.setAttribute('role', 'menuitem');
    cloudButton.textContent = '我的空间';
    cloudButton.addEventListener('click', function(event) {
      event.preventDefault();
      closeWorkspaceSourceMenu();
      switchToCloudWorkspace();
    });
    menu.appendChild(cloudButton);
    var recent = readRecentLocalRoots();
    if (recent.length) {
      var label = document.createElement('div');
      label.className = 'mnote-workspace-source-menu__label';
      label.textContent = '最近本地文件夹';
      menu.appendChild(label);
      recent.slice(0, 8).forEach(function(rootUri) {
        var button = document.createElement('button');
        button.type = 'button';
        button.className = 'mnote-workspace-source-menu__item';
        button.setAttribute('data-testid', 'mnote-recent-local-root');
        button.setAttribute('data-root-uri', rootUri);
        button.setAttribute('role', 'menuitem');
        button.textContent = workspaceSourceLabel(rootUri);
        button.addEventListener('click', function(event) {
          event.preventDefault();
          closeWorkspaceSourceMenu();
          openLocalFolderRoot(rootUri);
        });
        menu.appendChild(button);
      });
    }
    var openOther = document.createElement('button');
    openOther.type = 'button';
    openOther.className = 'mnote-workspace-source-menu__item mnote-workspace-source-menu__item--primary';
    openOther.setAttribute('data-testid', 'mnote-open-other-local-folder');
    openOther.setAttribute('role', 'menuitem');
    openOther.textContent = '打开其他本地文件夹';
    openOther.addEventListener('click', function(event) {
      event.preventDefault();
      closeWorkspaceSourceMenu();
      requestOpenLocalFolder();
    });
    menu.appendChild(openOther);
    trigger.closest('[data-testid="wolai-workspace-identity"]')?.appendChild(menu);
  }

  function closeAccountMenu() {
    var existing = document.querySelector('[data-testid="mnote-account-menu"]');
    if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
    document.querySelectorAll('[data-testid="mnote-account-menu-trigger"]').forEach(function(trigger) {
      if (trigger instanceof HTMLElement) trigger.setAttribute('aria-expanded', 'false');
    });
  }

  function closeProfileDialog() {
    var existing = document.querySelector('[data-testid="mnote-profile-dialog"]');
    if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
  }

  function closeAdminAccessPolicyDialog() {
    var existing = document.querySelector('[data-testid="mnote-admin-access-policy-modal"]');
    if (existing && existing.parentElement) existing.parentElement.removeChild(existing);
    document.documentElement.removeAttribute('data-mnote-admin-access-policy-modal-open');
  }

  function accountMenuFallbackSession() {
    var body = document.body instanceof HTMLElement ? document.body : null;
    var actorId = body ? String(body.getAttribute('data-mnote-actor-id') || '').trim() : '';
    return {
      ok: true,
      name: actorId || '当前用户',
      email: '',
      userId: actorId || 'anonymous',
      actorType: actorId && actorId !== 'anonymous' ? 'user' : 'anonymous',
      authMode: 'browser'
    };
  }

  function renderAccountInfo(menu, session) {
    var nameNode = menu.querySelector('[data-account-info="name"]');
    var emailNode = menu.querySelector('[data-account-info="email"]');
    var idNode = menu.querySelector('[data-account-info="user-id"]');
    var typeNode = menu.querySelector('[data-account-info="actor-type"]');
    if (nameNode) nameNode.textContent = session.name || session.userId || '当前用户';
    if (emailNode) emailNode.textContent = session.email || '未提供邮箱';
    if (idNode) {
      idNode.textContent = session.userId || 'anonymous';
      idNode.setAttribute('title', session.userId || 'anonymous');
    }
    if (typeNode) typeNode.textContent = session.actorType || session.authMode || 'unknown';
    var copyButton = menu.querySelector('[data-account-copy-user-id]');
    if (copyButton instanceof HTMLElement) {
      copyButton.dataset.copyValue = session.userId || 'anonymous';
      copyButton.setAttribute('title', '复制用户 ID');
    }
  }

  function sessionIsAdmin(session) {
    return String(session && session.actorType || '').trim() === 'admin';
  }

  async function loadAccountInfo(menu) {
    try {
      var response = await fetch('/api/auth/session', {
        method: 'GET',
        headers: { 'accept': 'application/json' },
        credentials: 'include'
      });
      var payload = await response.json().catch(function() { return null; });
      if (!response.ok || !payload) throw new Error('session_failed_' + response.status);
      renderAccountInfo(menu, payload);
    } catch (_) {
      renderAccountInfo(menu, accountMenuFallbackSession());
    }
  }

  async function fetchAccountSession() {
    try {
      var response = await fetch('/api/auth/session', {
        method: 'GET',
        headers: { 'accept': 'application/json' },
        credentials: 'include'
      });
      var payload = await response.json().catch(function() { return null; });
      if (!response.ok || !payload) throw new Error('session_failed_' + response.status);
      return payload;
    } catch (_) {
      return accountMenuFallbackSession();
    }
  }

  function openProfileDialog(session) {
    closeProfileDialog();
    closeAccountMenu();
    var dialog = document.createElement('div');
    dialog.className = 'mnote-profile-dialog';
    dialog.setAttribute('data-testid', 'mnote-profile-dialog');
    dialog.setAttribute('role', 'dialog');
    dialog.setAttribute('aria-modal', 'true');
    dialog.setAttribute('aria-labelledby', 'mnote-profile-dialog-title');
    var userId = escapeHtml(session.userId || 'anonymous');
    dialog.innerHTML =
      '<div class="mnote-profile-dialog__backdrop" data-profile-dialog-close></div>' +
      '<section class="mnote-profile-dialog__panel">' +
        '<header class="mnote-profile-dialog__header">' +
          '<div>' +
            '<div class="mnote-profile-dialog__eyebrow">个人信息</div>' +
            '<h2 id="mnote-profile-dialog-title">个人信息</h2>' +
          '</div>' +
          '<button type="button" class="mnote-profile-dialog__close" data-profile-dialog-close aria-label="关闭"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
        '</header>' +
        '<div class="mnote-profile-dialog__identity">' +
          '<div class="mnote-profile-dialog__avatar">' + escapeHtml(String(session.name || session.email || session.userId || '用').slice(0, 1).toUpperCase()) + '</div>' +
          '<div><strong>' + escapeHtml(session.name || session.userId || '当前用户') + '</strong><span>' + escapeHtml(session.email || '未提供邮箱') + '</span></div>' +
        '</div>' +
        '<dl class="mnote-profile-dialog__list">' +
          '<div><dt>用户名</dt><dd>' + escapeHtml(session.name || '未设置') + '</dd></div>' +
          '<div><dt>邮箱</dt><dd>' + escapeHtml(session.email || '未提供邮箱') + '</dd></div>' +
          '<div><dt>用户 ID</dt><dd><code title="' + userId + '">' + userId + '</code><button type="button" data-profile-copy-user-id data-copy-value="' + userId + '"><span class="material-symbols-outlined" data-icon="content_copy" aria-hidden="true"></span></button></dd></div>' +
          '<div><dt>身份</dt><dd>' + escapeHtml(session.actorType || session.authMode || 'unknown') + '</dd></div>' +
        '</dl>' +
      '</section>';
    dialog.querySelectorAll('[data-profile-dialog-close]').forEach(function(button) {
      button.addEventListener('click', function(event) {
        event.preventDefault();
        closeProfileDialog();
      });
    });
    var copyButton = dialog.querySelector('[data-profile-copy-user-id]');
    if (copyButton) {
      copyButton.addEventListener('click', function(event) {
        event.preventDefault();
        void copyTreeContextValue(copyButton.getAttribute('data-copy-value') || '', 'profile-user-id');
      });
    }
    document.body.appendChild(dialog);
    var closeButton = dialog.querySelector('.mnote-profile-dialog__close');
    if (closeButton instanceof HTMLElement) closeButton.focus();
  }

  function openAdminAccessPolicyDialog(trigger) {
    closeAdminAccessPolicyDialog();
    closeAccountMenu();
    if (!(trigger instanceof HTMLElement)) return;
    var role = trigger.getAttribute('data-access-policy-role') === 'admin' ? 'admin' : 'user';
    var template = document.querySelector('[data-testid="mnote-admin-access-policy-template-' + role + '"]');
    var dialog = document.createElement('div');
    dialog.className = 'mnote-admin-policy-modal';
    dialog.setAttribute('data-testid', 'mnote-admin-access-policy-modal');
    dialog.setAttribute('role', 'dialog');
    dialog.setAttribute('aria-modal', 'true');
    dialog.setAttribute('aria-labelledby', 'mnote-admin-policy-dialog-title');
    dialog.innerHTML =
      '<div class="mnote-admin-policy-modal__backdrop" data-admin-access-policy-close></div>' +
      '<section class="mnote-admin-policy-modal__panel">' +
        '<button type="button" class="mnote-admin-policy-modal__close" data-admin-access-policy-close aria-label="关闭授权管理"><span class="material-symbols-outlined" data-icon="close" aria-hidden="true"></span></button>' +
        '<div class="mnote-admin-policy-modal__content" data-testid="mnote-admin-access-policy-modal-content"></div>' +
      '</section>';
    var content = dialog.querySelector('[data-testid="mnote-admin-access-policy-modal-content"]');
    if (content) {
      content.innerHTML = template ? template.innerHTML : '<div class="mnote-admin-policy-empty">授权管理面板加载失败</div>';
    }
    if (typeof window.MNOTEInitAccessPolicyPanel === 'function') {
      window.MNOTEInitAccessPolicyPanel(dialog);
    }
    dialog.querySelectorAll('[data-admin-access-policy-close]').forEach(function(button) {
      button.addEventListener('click', function(event) {
        event.preventDefault();
        closeAdminAccessPolicyDialog();
      });
    });
    document.body.appendChild(dialog);
    document.documentElement.setAttribute('data-mnote-admin-access-policy-modal-open', 'true');
    var closeButton = dialog.querySelector('.mnote-admin-policy-modal__close');
    if (closeButton instanceof HTMLElement) closeButton.focus();
  }

  async function signOutAccount(trigger) {
    setCommandPending(trigger, true);
    try {
      var response = await fetch('/api/auth', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        credentials: 'include',
        body: JSON.stringify({ action: 'auth:signOut', args: {} })
      });
      var payload = await response.json().catch(function() { return {}; });
      payload = payload || {};
      if (!response.ok || payload.error) {
        throw new Error(payload.error || '退出登录失败');
      }
      window.location.assign('/auth');
    } catch (error) {
      var menu = document.querySelector('[data-testid="mnote-account-menu"]');
      var errorNode = menu ? menu.querySelector('[data-account-error]') : null;
      if (errorNode instanceof HTMLElement) {
        errorNode.textContent = error && error.message ? error.message : '退出登录失败';
        errorNode.hidden = false;
      }
      setCommandPending(trigger, false);
    }
  }

  function openAccountMenu(trigger) {
    closeAccountMenu();
    if (!(trigger instanceof HTMLElement)) return;
    trigger.setAttribute('aria-expanded', 'true');
    var menu = document.createElement('div');
    menu.className = 'mnote-workspace-source-menu mnote-account-menu';
    menu.setAttribute('data-testid', 'mnote-account-menu');
    menu.setAttribute('role', 'menu');
    menu.innerHTML =
      '<button type="button" class="mnote-workspace-source-menu__item mnote-account-menu__item" data-testid="mnote-account-profile" role="menuitem"><span class="material-symbols-outlined" data-icon="account_circle" aria-hidden="true"></span><span>个人信息</span></button>' +
      '<button type="button" class="mnote-workspace-source-menu__item mnote-account-menu__item" data-testid="mnote-account-access-policy" role="menuitem" hidden><span class="material-symbols-outlined" data-icon="admin_panel_settings" aria-hidden="true"></span><span>授权管理</span></button>' +
      '<button type="button" class="mnote-workspace-source-menu__item mnote-account-menu__logout" data-testid="mnote-account-sign-out" role="menuitem">退出登录</button>' +
      '<div class="mnote-account-menu__error" data-account-error hidden></div>';
    var sessionPromise = fetchAccountSession();
    var profileButton = menu.querySelector('[data-testid="mnote-account-profile"]');
    if (profileButton) {
      profileButton.addEventListener('click', function(event) {
        event.preventDefault();
        sessionPromise.then(openProfileDialog);
      });
    }
    var accessPolicyLink = menu.querySelector('[data-testid="mnote-account-access-policy"]');
    sessionPromise.then(function(session) {
      if (!(accessPolicyLink instanceof HTMLElement)) return;
      accessPolicyLink.hidden = false;
      accessPolicyLink.setAttribute('data-access-policy-role', sessionIsAdmin(session) ? 'admin' : 'user');
    });
    if (accessPolicyLink) {
      accessPolicyLink.addEventListener('click', function(event) {
        event.preventDefault();
        openAdminAccessPolicyDialog(accessPolicyLink);
      });
    }
    var signOutButton = menu.querySelector('[data-testid="mnote-account-sign-out"]');
    if (signOutButton) {
      signOutButton.addEventListener('click', function(event) {
        event.preventDefault();
        void signOutAccount(signOutButton);
      });
    }
    var host = trigger.closest('[data-testid="wolai-sidebar-quick-actions"]') || trigger.parentElement;
    if (host) host.appendChild(menu);
  }


  return {
    activeSidebarTreeMode,
    autoOpenRecentLocalRootOnHome,
    closeAccountMenu,
    closeLocalFolderDialog,
    closeTrashModal,
    closeWorkspaceSourceMenu,
    copyWorkspaceSourceParams,
    createDefaultLocalWorkspace,
    currentRootUri,
    currentSourceKind,
    currentWorkspaceId,
    currentWorkspaceSourcePayload,
    normalizeSidebarTreeMode,
    openAccountMenu,
    openTrashModal,
    openWorkspaceSourceMenu,
    persistSidebarTreeMode,
    readStoredSidebarTreeMode,
    requestOpenLocalFolder,
    resolveWorkspaceId,
  };
};
