<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CyberStrikeAI</title>
    <link rel="icon" type="image/x-icon" href="/static/favicon.ico?v=20260728">
    <link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico?v=20260728">
    <script>
        (function () {
            try {
                var stored = localStorage.getItem('cyberstrike-theme') || 'system';
                if (stored !== 'system' && stored !== 'light' && stored !== 'dark') {
                    stored = 'system';
                }
                var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
                var resolved = stored === 'dark' || (stored !== 'light' && prefersDark) ? 'dark' : 'light';
                document.documentElement.setAttribute('data-theme-preference', stored);
                document.documentElement.setAttribute('data-theme', resolved);
                document.documentElement.style.colorScheme = resolved;
            } catch (e) {
                document.documentElement.setAttribute('data-theme', 'light');
            }
        })();
    </script>
    <script>
        (function () {
            var initialPage = String(window.location.hash || '').replace(/^#/, '').split('?')[0];
            if (initialPage && initialPage !== 'dashboard') {
                document.documentElement.classList.add('initial-route-pending');
            }
        })();
    </script>
    <link rel="stylesheet" href="/static/css/style.css?v=20260907-blocked-1">
    <link rel="stylesheet" href="/static/css/tool-guard.css?v=20260907-7">
    <link rel="stylesheet" href="/static/css/chat-plan-progress.css?v=20260813-4">
    <link rel="stylesheet" href="/static/css/c2.css">
    <link rel="stylesheet" href="/static/vendor/xterm.css">
    <script src="/static/js/router.js?v=20260907-1"></script>
</head>
<body>
    <div id="login-overlay" class="login-overlay" style="display: none;">
        <div class="login-card">
            <div class="login-brand">
                <h2 class="login-title">
                    <span data-i18n="login.titlePrefix">登录</span>
                    <span class="brand-wordmark brand-wordmark--sm" aria-label="CyberStrikeAI">
                        <span class="brand-wordmark__core">CyberStrike</span><span class="brand-wordmark__ai">AI</span>
                    </span>
                </h2>
                <p class="login-subtitle" data-i18n="login.subtitle">使用平台账号登录，默认管理员为 admin。</p>
            </div>
            <form id="login-form" class="login-form">
                <div class="form-group">
                    <label for="login-username" data-i18n="login.usernameLabel">用户名</label>
                    <input type="text" id="login-username" placeholder="admin" autocomplete="username" data-i18n="login.usernamePlaceholder" data-i18n-attr="placeholder" />
                </div>
                <div class="form-group">
                    <label for="login-password" data-i18n="login.passwordLabel">密码</label>
                    <input type="password" id="login-password" placeholder="输入登录密码" required autocomplete="current-password" data-i18n="login.passwordPlaceholder" data-i18n-attr="placeholder" />
                </div>
                <div id="login-error" class="login-error" role="alert" style="display: none;"></div>
                <button type="submit" class="btn-primary login-submit">
                    <span data-i18n="login.submit">登录</span>
                </button>
            </form>
        </div>
    </div>

    <div class="container">
        <header>
            <div class="header-content">
                <div class="logo header-logo-link" onclick="switchPage('dashboard')" role="button" data-i18n="header.backToDashboard" data-i18n-attr="title" data-i18n-skip-text="true" title="返回仪表盘">
                    <img src="/static/logo.png" alt="CyberStrikeAI Logo" class="brand-logo" width="36" height="36">
                    <h1 class="brand-wordmark brand-wordmark--lg">
                        <span class="brand-wordmark__core">CyberStrike</span><span class="brand-wordmark__ai">AI</span>
                    </h1>
                    <span class="version-badge" data-i18n="header.version" data-i18n-attr="title" data-i18n-skip-text="true" title="当前版本">{{.Version}}</span>
                </div>
                <div class="header-right">
                    <div class="header-actions">
                        <button class="openapi-doc-btn" onclick="window.open('/api-docs', '_blank')" data-i18n="header.apiDocs" data-i18n-attr="title" data-i18n-skip-text="true" title="API 文档">
                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                <polyline points="14 2 14 8 20 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                <path d="M16 13H8M16 17H8M10 9H8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                            <span data-i18n="header.apiDocs">API 文档</span>
                        </button>
                        <button class="openapi-doc-btn" onclick="window.open('https://github.com/Ed1s0nZ/CyberStrikeAI', '_blank')" data-i18n="header.github" data-i18n-attr="title" data-i18n-skip-text="true" title="GitHub">
                                            <svg width="16" height="16" viewBox="0 0 98 96" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
                                                <path d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z"/>
                                            </svg>
                                            <span data-i18n="header.github">GitHub</span>
                                        </button>
                        <button id="theme-toggle-btn" class="theme-toggle-btn" type="button" onclick="window.cycleThemePreference && window.cycleThemePreference()" data-i18n="theme.toggle" data-i18n-attr="title" title="切换主题" aria-label="切换主题">
                            <svg class="theme-toggle-icon theme-toggle-icon--system" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                <rect x="3" y="4" width="18" height="13" rx="2" stroke="currentColor" stroke-width="2"/>
                                <path d="M8 21h8M12 17v4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                            </svg>
                            <svg class="theme-toggle-icon theme-toggle-icon--light" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                <circle cx="12" cy="12" r="4" stroke="currentColor" stroke-width="2"/>
                                <path d="M12 2v2M12 20v2M4 12H2M22 12h-2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                            </svg>
                            <svg class="theme-toggle-icon theme-toggle-icon--dark" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                <path d="M21 14.5A8.5 8.5 0 0 1 9.5 3a7 7 0 1 0 11.5 11.5z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/>
                            </svg>
                            <span id="theme-toggle-label">跟随系统</span>
                        </button>
                        <div class="lang-switcher">
                            <button class="btn-secondary lang-switcher-btn" onclick="toggleLangDropdown()" data-i18n="header.language" data-i18n-attr="title" data-i18n-skip-text="true" title="界面语言">
                                <span class="lang-switcher-icon">🌐</span>
                                <span id="current-lang-label">中文</span>
                            </button>
                            <div id="lang-dropdown" class="lang-dropdown" style="display: none;">
                                <div class="lang-option" data-lang="zh-CN" onclick="onLanguageSelect('zh-CN')">中文</div>
                                <div class="lang-option" data-lang="en-US" onclick="onLanguageSelect('en-US')">English</div>
                            </div>
                        </div>
                        <div class="notification-menu-container">
                            <button class="notification-btn" id="notification-bell-btn" onclick="toggleNotificationDropdown()" data-i18n="notifications.title" data-i18n-attr="title" data-i18n-skip-text="true" title="事件通知">
                                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M18 8a6 6 0 0 0-12 0c0 7-3 9-3 9h18s-3-2-3-9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <path d="M13.73 21a2 2 0 0 1-3.46 0" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                                <span class="notification-badge" id="notification-badge" style="display: none;">0</span>
                            </button>
                            <div id="notification-dropdown" class="notification-dropdown" style="display: none;">
                                <div class="notification-dropdown-header">
                                    <span id="notification-dropdown-title" data-i18n="notifications.title">事件通知</span>
                                    <button class="notification-mark-read-btn" id="notification-mark-all-read-btn" type="button" data-require-permission="notification:write" onclick="markAllNotificationsSeen()" data-i18n="notifications.markAllRead">标记已读</button>
                                </div>
                                <div id="notification-list" class="notification-list">
                                    <div class="notification-empty" data-i18n="notifications.empty">暂无新事件</div>
                                </div>
                            </div>
                        </div>
                        <div class="user-menu-container">
                            <button id="user-avatar-btn" class="user-avatar-btn" onclick="toggleUserMenu()" data-i18n="header.userMenu" data-i18n-attr="title" data-i18n-skip-text="true" title="用户菜单" aria-haspopup="menu" aria-expanded="false" aria-controls="user-menu-dropdown">
                                <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                    <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    <circle cx="12" cy="7" r="4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                </svg>
                            </button>
                            <div id="user-menu-dropdown" class="user-menu-dropdown" role="menu" style="display: none;">
                                <div class="user-menu-profile" role="presentation">
                                    <div class="user-menu-profile-row">
                                        <div class="user-menu-profile-main">
                                            <div id="user-menu-current-label" class="user-menu-profile-label" data-i18n="header.currentUser">当前用户</div>
                                            <div id="user-menu-display-name" class="user-menu-profile-name">-</div>
                                            <div id="user-menu-username" class="user-menu-profile-username">-</div>
                                        </div>
                                    </div>
                                    <div class="user-menu-profile-meta" aria-labelledby="user-menu-current-label">
                                        <span id="user-menu-scope" class="user-menu-profile-pill">-</span>
                                        <span id="user-menu-roles" class="user-menu-profile-pill">-</span>
                                        <span id="user-menu-permissions" class="user-menu-profile-pill">-</span>
                                    </div>
                                </div>
                                <div class="user-menu-divider" role="separator"></div>
                                <div class="user-menu-item" role="menuitem" tabindex="0" onclick="openRobotAccountBinding()" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();openRobotAccountBinding();}">
                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                        <path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                    </svg>
                                    <span>绑定机器人账号</span>
                                </div>
                                <div class="user-menu-item" role="menuitem" tabindex="0" onclick="logout()" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();logout();}">
                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        <polyline points="16 17 21 12 16 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        <line x1="21" y1="12" x2="9" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    </svg>
                                    <span data-i18n="header.logout">退出登录</span>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </header>

        <div class="main-layout">
            <!-- 主侧边栏 -->
            <aside class="main-sidebar" id="main-sidebar">
                <div class="sidebar-collapse-btn" onclick="toggleSidebar()" data-i18n="header.toggleSidebar" data-i18n-attr="title" data-i18n-skip-text="true" title="折叠/展开侧边栏">
                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                        <path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                    </svg>
                </div>
                <nav class="main-sidebar-nav">
                    <div class="nav-section-label" role="presentation">
                        <span data-i18n="navGroups.workbench">工作台</span>
                    </div>
                    <div class="nav-item" data-page="dashboard">
                        <div class="nav-item-content" data-title="仪表盘" onclick="switchPage('dashboard')" data-i18n="nav.dashboard" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="3" y="3" width="7" height="9"></rect>
                                <rect x="14" y="3" width="7" height="5"></rect>
                                <rect x="14" y="12" width="7" height="9"></rect>
                                <rect x="3" y="16" width="7" height="5"></rect>
                            </svg>
                            <span data-i18n="nav.dashboard">仪表盘</span>
                        </div>
                    </div>
                    <div class="nav-item" data-page="chat">
                        <div class="nav-item-content" data-title="对话" onclick="switchPage('chat')" data-i18n="nav.chat" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
                            </svg>
                            <span data-i18n="nav.chat">对话</span>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="security" data-require-permission-any="hitl:read config:read">
                        <div class="nav-item-content" data-title="安全防护" onclick="window.toggleSubmenu('security')" data-i18n="nav.security" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                                <rect x="4" y="10" width="16" height="11" rx="2"></rect>
                                <path d="M8 10V7a4 4 0 0 1 8 0v3M12 14v3"></path>
                            </svg>
                            <span data-i18n="nav.security">安全防护</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="m9 18 6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="hitl" data-require-permission="hitl:read" onclick="switchPage('hitl')" data-i18n="nav.hitl">人机协同</div>
                            <div class="nav-submenu-item" data-page="tool-guard" data-require-permission="config:read" onclick="switchPage('tool-guard')" data-i18n="nav.toolGuard">调用拦截</div>
                        </div>
                    </div>
                    <div class="nav-section-label" role="presentation">
                        <span data-i18n="navGroups.operations">安全作业</span>
                    </div>
                    <div class="nav-item" data-page="projects">
                        <div class="nav-item-content" data-title="项目管理" onclick="switchPage('projects')" data-i18n="nav.projects" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M8 6h11"></path>
                                <path d="M5 12h10"></path>
                                <path d="M10 18h9"></path>
                            </svg>
                            <span data-i18n="nav.projects">项目管理</span>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="assets" data-require-permission-any="asset:read fofa:execute">
                        <div class="nav-item-content" data-title="资产管理" onclick="window.toggleSubmenu('assets')" data-i18n="nav.assets" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M3 7l9-4 9 4-9 4-9-4z"></path><path d="M3 12l9 4 9-4"></path><path d="M3 17l9 4 9-4"></path>
                            </svg>
                            <span data-i18n="nav.assets">资产管理</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="m9 18 6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="asset-overview" onclick="switchPage('asset-overview')" data-i18n="nav.assetOverview">资产概览</div>
                            <div class="nav-submenu-item" data-page="asset-library" onclick="switchPage('asset-library')" data-i18n="nav.assetLibrary">资产库</div>
                            <div class="nav-submenu-item" data-page="info-collect" onclick="switchPage('info-collect')" data-i18n="nav.infoCollect">信息收集</div>
                        </div>
                    </div>
                    <div class="nav-item" data-page="vulnerabilities">
                        <div class="nav-item-content" data-title="漏洞管理" onclick="switchPage('vulnerabilities')" data-i18n="nav.vulnerabilities" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
                                <path d="M9 12l2 2 4-4"></path>
                            </svg>
                            <span data-i18n="nav.vulnerabilities">漏洞管理</span>
                        </div>
                    </div>
                    <div class="nav-item" data-page="tasks">
                        <div class="nav-item-content" data-title="任务管理" onclick="switchPage('tasks')" data-i18n="nav.tasks" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M9 11l3 3L22 4"></path>
                                <path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
                            </svg>
                            <span data-i18n="nav.tasks">任务管理</span>
                        </div>
                    </div>
                    <div class="nav-item" data-page="workflows">
                        <div class="nav-item-content" data-title="工作流" onclick="switchPage('workflows')" data-i18n="nav.workflows" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <rect x="3" y="3" width="8" height="8" rx="2"/>
                                <path d="M7 11v4a2 2 0 0 0 2 2h4"/>
                                <rect x="13" y="13" width="8" height="8" rx="2"/>
                            </svg>
                            <span data-i18n="nav.workflows">工作流</span>
                        </div>
                    </div>
                    <div class="nav-item" data-page="webshell">
                        <div class="nav-item-content" data-title="WebShell管理" onclick="switchPage('webshell')" data-i18n="nav.webshell" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <polyline points="4 17 10 11 4 5"></polyline>
                                <line x1="12" y1="19" x2="20" y2="19"></line>
                            </svg>
                            <span data-i18n="nav.webshell">WebShell管理</span>
                        </div>
                    </div>
                    <!-- C2 侧栏入口（带子菜单） -->
                    <div class="nav-item nav-item-has-submenu" data-page="c2" id="nav-c2">
                        <div class="nav-item-content" data-title="C2" onclick="window.toggleSubmenu('c2')" data-i18n="nav.c2" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
                                <path d="M4.9 19.1C1 15.2 1 8.8 4.9 4.9"></path>
                                <path d="M7.8 16.2c-2.3-2.3-2.3-6.1 0-8.5"></path>
                                <circle cx="12" cy="12" r="2"></circle>
                                <path d="M16.2 7.8c2.3 2.3 2.3 6.1 0 8.5"></path>
                                <path d="M19.1 4.9C23 8.8 23 15.2 19.1 19"></path>
                            </svg>
                            <span data-i18n="nav.c2">C2</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu" id="submenu-c2">
                            <div class="nav-submenu-item" data-page="c2-listeners" onclick="switchPage('c2-listeners')" data-i18n="nav.c2Listeners">监听器</div>
                            <div class="nav-submenu-item" data-page="c2-sessions" onclick="switchPage('c2-sessions')" data-i18n="nav.c2Sessions">会话</div>
                            <div class="nav-submenu-item" data-page="c2-tasks" onclick="switchPage('c2-tasks')" data-i18n="nav.c2Tasks">任务</div>
                            <div class="nav-submenu-item" data-page="c2-payloads" onclick="switchPage('c2-payloads')" data-i18n="nav.c2Payloads">Payload</div>
                            <div class="nav-submenu-item" data-page="c2-events" onclick="switchPage('c2-events')" data-i18n="nav.c2Events">事件</div>
                            <div class="nav-submenu-item" data-page="c2-profiles" onclick="switchPage('c2-profiles')" data-i18n="nav.c2Profiles">流量伪装</div>
                        </div>
                    </div>
                    <div class="nav-item" data-page="chat-files">
                        <div class="nav-item-content" data-title="文件管理" onclick="switchPage('chat-files')" data-i18n="nav.chatFiles" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
                            </svg>
                            <span data-i18n="nav.chatFiles">文件管理</span>
                        </div>
                    </div>
                    <div class="nav-section-label" role="presentation">
                        <span data-i18n="navGroups.capabilities">能力中心</span>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="mcp">
                        <div class="nav-item-content" data-title="MCP" onclick="window.toggleSubmenu('mcp')" data-i18n="nav.mcp" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"></path>
                            </svg>
                            <span data-i18n="nav.mcp">MCP</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="mcp-monitor" onclick="switchPage('mcp-monitor')">
                                <span data-i18n="nav.mcpMonitor">MCP状态监控</span>
                            </div>
                            <div class="nav-submenu-item" data-page="mcp-management" onclick="switchPage('mcp-management')">
                                <span data-i18n="nav.mcpManagement">MCP管理</span>
                            </div>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="knowledge">
                        <div class="nav-item-content" data-title="知识" onclick="window.toggleSubmenu('knowledge')" data-i18n="nav.knowledge" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
                                <path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
                            </svg>
                            <span data-i18n="nav.knowledge">知识</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="knowledge-retrieval-logs" onclick="switchPage('knowledge-retrieval-logs')">
                                <span data-i18n="nav.knowledgeRetrievalLogs">检索历史</span>
                            </div>
                            <div class="nav-submenu-item" data-page="knowledge-management" onclick="switchPage('knowledge-management')">
                                <span data-i18n="nav.knowledgeManagement">知识管理</span>
                            </div>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="skills">
                        <div class="nav-item-content" data-title="技能" onclick="window.toggleSubmenu('skills')" data-i18n="nav.skills" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"></path>
                                <polyline points="14 2 14 8 20 8"></polyline>
                                <line x1="16" y1="13" x2="8" y2="13"></line>
                                <line x1="16" y1="17" x2="8" y2="17"></line>
                                <polyline points="10 9 9 9 8 9"></polyline>
                            </svg>
                            <span data-i18n="nav.skills">技能</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="skills-monitor" onclick="switchPage('skills-monitor')">
                                <span data-i18n="nav.skillsMonitor">技能状态</span>
                            </div>
                            <div class="nav-submenu-item" data-page="skills-management" onclick="switchPage('skills-management')">
                                <span data-i18n="nav.skillsManagement">技能管理</span>
                            </div>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="agents">
                        <div class="nav-item-content" data-title="智能体" onclick="window.toggleSubmenu('agents')" data-i18n="nav.agents" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <polygon points="12 2 2 7 12 12 22 7 12 2"></polygon>
                                <polyline points="2 17 12 22 22 17"></polyline>
                                <polyline points="2 12 12 17 22 12"></polyline>
                            </svg>
                            <span data-i18n="nav.agents">智能体</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="agents-management" onclick="switchPage('agents-management')">
                                <span data-i18n="nav.agentsManagement">智能体管理</span>
                            </div>
                        </div>
                    </div>
                    <div class="nav-item nav-item-has-submenu" data-page="roles">
                        <div class="nav-item-content" data-title="角色" onclick="window.toggleSubmenu('roles')" data-i18n="nav.roles" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
                                <circle cx="9" cy="7" r="4"></circle>
                                <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
                                <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
                            </svg>
                            <span data-i18n="nav.roles">角色</span>
                            <svg class="submenu-arrow" width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                            </svg>
                        </div>
                        <div class="nav-submenu">
                            <div class="nav-submenu-item" data-page="roles-management" onclick="switchPage('roles-management')">
                                <span data-i18n="nav.rolesManagement">角色管理</span>
                            </div>
                        </div>
                    </div>
                    <div class="nav-section-label" role="presentation">
                        <span data-i18n="navGroups.administration">平台管理</span>
                    </div>
                    <div class="nav-item" data-page="platform-rbac">
                        <div class="nav-item-content" data-title="平台权限" onclick="switchPage('platform-rbac')" data-i18n="nav.platformRbac" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <circle cx="7.5" cy="14.5" r="3.5"></circle>
                                <path d="M10.3 12.3 21 1.6"></path>
                                <path d="m15 7 2 2"></path>
                                <path d="m18 4 2 2"></path>
                                <path d="M4 4h4"></path>
                                <path d="M6 2v4"></path>
                                <path d="M18 18h4"></path>
                                <path d="M20 16v4"></path>
                            </svg>
                            <span data-i18n="nav.platformRbac">平台权限</span>
                        </div>
                    </div>
                    <div class="nav-item" data-page="settings">
                        <div class="nav-item-content" data-title="系统设置" onclick="switchPage('settings')" data-i18n="nav.settings" data-i18n-attr="data-title" data-i18n-skip-text="true">
                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                                <circle cx="12" cy="12" r="3"></circle>
                                <path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path>
                            </svg>
                            <span data-i18n="nav.settings">系统设置</span>
                        </div>
                    </div>
                </nav>
            </aside>

            <!-- 内容区域 -->
            <div class="content-area">
                <!-- 仪表盘页面 -->
                <div id="page-dashboard" class="page active">
                    <div class="dashboard-page">
                        <div class="page-header">
                            <h2 data-i18n="dashboard.title">仪表盘</h2>
                            <div class="page-header-actions">
                                <span class="dashboard-last-updated" id="dashboard-last-updated" aria-live="polite">
                                    <svg class="dashboard-last-updated-icon" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
                                    <span data-i18n="dashboard.lastUpdated">上次更新</span>
                                    <span class="dashboard-last-updated-time" id="dashboard-last-updated-time">-</span>
                                    <span class="dashboard-last-updated-stale" id="dashboard-last-updated-stale" hidden data-i18n="dashboard.dataStale" data-i18n-attr="title" title="数据可能已过期">
                                        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
                                    </span>
                                </span>
                                <button class="btn-secondary" onclick="refreshDashboard()" data-i18n="dashboard.refreshData" data-i18n-attr="title" title="刷新数据"><span data-i18n="common.refresh">刷新</span></button>
                            </div>
                        </div>
                        <div class="dashboard-content">
                            <!-- 关键提醒条（仅当存在严重风险时渲染，默认 hidden）；右侧 × 可在 session 内忽略 -->
                            <div class="dashboard-alert-banner" id="dashboard-alert-banner" hidden>
                                <span class="dashboard-alert-icon" aria-hidden="true">
                                    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
                                </span>
                                <div class="dashboard-alert-content">
                                    <div class="dashboard-alert-title" id="dashboard-alert-title" data-i18n="dashboard.alertTitle">需要关注</div>
                                    <div class="dashboard-alert-desc" id="dashboard-alert-desc"></div>
                                </div>
                                <div class="dashboard-alert-actions" id="dashboard-alert-actions"></div>
                                <button type="button" class="dashboard-alert-close" id="dashboard-alert-close" data-i18n="dashboard.alertDismiss" data-i18n-attr="title" data-i18n-skip-text="true" title="忽略此提醒（仅本次会话）" aria-label="dismiss">
                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
                                </button>
                            </div>
                            <!-- 第一行：核心 KPI（关键指标置顶 + 副标徽章承载次级信息） -->
                            <div class="dashboard-kpi-row" id="dashboard-cards">
                                <div class="dashboard-kpi-card" role="button" tabindex="0" onclick="switchPage('chat')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('chat'); }" data-i18n="dashboard.clickToViewChat" data-i18n-attr="title" title="点击查看对话">
                                    <div class="dashboard-kpi-head">
                                        <div class="dashboard-kpi-label" data-i18n="dashboard.runningConversations">运行中对话</div>
                                        <span class="dashboard-kpi-icon dashboard-kpi-icon-tasks" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v4"/><path d="M12 18v4"/><path d="M4.93 4.93l2.83 2.83"/><path d="M16.24 16.24l2.83 2.83"/><path d="M2 12h4"/><path d="M18 12h4"/><path d="M4.93 19.07l2.83-2.83"/><path d="M16.24 7.76l2.83-2.83"/></svg></span>
                                    </div>
                                    <div class="dashboard-kpi-value" id="dashboard-running-tasks">-</div>
                                    <div class="dashboard-kpi-sub" id="dashboard-kpi-tasks-sub">
                                        <span class="dashboard-kpi-sub-text" id="dashboard-kpi-tasks-sub-text">-</span>
                                    </div>
                                </div>
                                <div class="dashboard-kpi-card" role="button" tabindex="0" onclick="switchPage('vulnerabilities')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('vulnerabilities'); }" data-i18n="dashboard.clickToViewVuln" data-i18n-attr="title" title="点击查看漏洞管理">
                                    <div class="dashboard-kpi-head">
                                        <div class="dashboard-kpi-label" data-i18n="dashboard.vulnTotal">漏洞总数</div>
                                        <span class="dashboard-kpi-icon dashboard-kpi-icon-vuln" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg></span>
                                    </div>
                                    <div class="dashboard-kpi-value" id="dashboard-vuln-total">-</div>
                                    <div class="dashboard-kpi-sub" id="dashboard-kpi-vuln-sub">
                                        <span class="dashboard-kpi-sub-badge dashboard-kpi-sub-badge-critical" id="dashboard-kpi-vuln-critical-badge" hidden>
                                            <span class="dashboard-kpi-sub-badge-dot"></span>
                                            <span data-i18n="dashboard.severityCritical">严重</span>
                                            <span id="dashboard-kpi-vuln-critical-count">0</span>
                                        </span>
                                        <span class="dashboard-kpi-sub-text" id="dashboard-kpi-vuln-sub-text" data-i18n="dashboard.allClear">暂无新增风险</span>
                                    </div>
                                </div>
                                <div class="dashboard-kpi-card" role="button" tabindex="0" onclick="switchPage('mcp-monitor')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('mcp-monitor'); }" data-i18n="dashboard.clickToViewMCP" data-i18n-attr="title" title="点击查看 MCP 监控">
                                    <div class="dashboard-kpi-head">
                                        <div class="dashboard-kpi-label" data-i18n="dashboard.toolCalls">工具调用次数</div>
                                        <span class="dashboard-kpi-icon dashboard-kpi-icon-calls" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg></span>
                                    </div>
                                    <div class="dashboard-kpi-value" id="dashboard-kpi-tools-calls">-</div>
                                    <div class="dashboard-kpi-sub">
                                        <span class="dashboard-kpi-sub-text" id="dashboard-kpi-tools-sub-text">-</span>
                                    </div>
                                </div>
                                <div class="dashboard-kpi-card" role="button" tabindex="0" onclick="switchPage('mcp-monitor')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('mcp-monitor'); }" data-i18n="dashboard.clickToViewMCP" data-i18n-attr="title" title="点击查看 MCP 监控">
                                    <div class="dashboard-kpi-head">
                                        <div class="dashboard-kpi-label" data-i18n="dashboard.successRate">工具执行成功率</div>
                                        <span class="dashboard-kpi-icon dashboard-kpi-icon-rate" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg></span>
                                    </div>
                                    <div class="dashboard-kpi-value" id="dashboard-kpi-success-rate">-</div>
                                    <div class="dashboard-kpi-sub">
                                        <span class="dashboard-kpi-sub-text" id="dashboard-kpi-rate-sub-text" data-i18n="dashboard.healthyStatus">运行平稳</span>
                                    </div>
                                </div>
                                <div class="dashboard-kpi-card" role="button" tabindex="0" onclick="switchPage('chat')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('chat'); }" data-i18n="dashboard.clickToViewChat" data-i18n-attr="title" title="点击查看对话">
                                    <div class="dashboard-kpi-head">
                                        <div class="dashboard-kpi-label" data-i18n="dashboard.tokenUsage">Token 用量</div>
                                        <span class="dashboard-kpi-icon dashboard-kpi-icon-tokens" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16"/><path d="M4 12h16"/><path d="M4 17h16"/><path d="M8 3 6 21"/><path d="m18 3-2 18"/></svg></span>
                                    </div>
                                    <div class="dashboard-kpi-value" id="dashboard-kpi-token-usage">-</div>
                                    <div class="dashboard-kpi-sub">
                                        <span class="dashboard-kpi-sub-text" id="dashboard-kpi-token-sub-text">-</span>
                                    </div>
                                </div>
                            </div>
                            <!-- 两列主内容区 -->
                            <div class="dashboard-grid">
                                <div class="dashboard-main">
                                    <section class="dashboard-section dashboard-section-chart">
                                        <div class="dashboard-section-header dashboard-section-header--severity">
                                            <h3 class="dashboard-section-title" data-i18n="dashboard.severityDistribution">漏洞严重程度分布</h3>
                                            <div class="dashboard-section-actions">
                                                <div class="dashboard-severity-status-filter" id="dashboard-severity-status-filter" data-value="">
                                                    <button type="button" class="dashboard-severity-status-filter-btn" id="dashboard-severity-status-filter-btn" aria-haspopup="listbox" aria-expanded="false" aria-controls="dashboard-severity-status-filter-menu" data-i18n="dashboard.statusFilter" data-i18n-attr="title" data-i18n-skip-text="true" title="状态筛选" onclick="toggleDashboardSeverityStatusFilterMenu(event)">
                                                        <span class="dashboard-severity-status-filter-dot" aria-hidden="true"></span>
                                                        <span class="dashboard-severity-status-filter-text" id="dashboard-severity-status-filter-text" data-i18n="dashboard.allStatuses">全部状态</span>
                                                        <span class="dashboard-severity-status-filter-caret" aria-hidden="true"></span>
                                                    </button>
                                                    <div class="dashboard-severity-status-filter-menu" id="dashboard-severity-status-filter-menu" role="listbox" aria-labelledby="dashboard-severity-status-filter-btn" hidden>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="" onclick="selectDashboardSeverityStatusFilter('', event)"><span data-i18n="dashboard.allStatuses">全部状态</span></button>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="open" onclick="selectDashboardSeverityStatusFilter('open', event)"><span data-i18n="dashboard.statusOpen">待处理</span></button>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="confirmed" onclick="selectDashboardSeverityStatusFilter('confirmed', event)"><span data-i18n="dashboard.statusConfirmed">已确认</span></button>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="fixed" onclick="selectDashboardSeverityStatusFilter('fixed', event)"><span data-i18n="dashboard.statusFixed">已修复</span></button>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="ignored" onclick="selectDashboardSeverityStatusFilter('ignored', event)"><span data-i18n="dashboard.statusIgnored">已忽略</span></button>
                                                        <button type="button" class="dashboard-severity-status-filter-option" role="option" data-status="false_positive" onclick="selectDashboardSeverityStatusFilter('false_positive', event)"><span data-i18n="dashboard.statusFalsePositive">误报</span></button>
                                                    </div>
                                                </div>
                                                <a class="dashboard-section-link" onclick="openDashboardSeverityVulnerabilities()" data-i18n="dashboard.viewAll">查看全部 →</a>
                                            </div>
                                        </div>
                                        <div class="dashboard-severity-wrap">
                                            <!-- 风险概览卡：填充 donut 左侧留白；提供「结论性」洞察（风险等级/加权分/待处理计数/最新时间），
                                                 与右侧 legend 的「明细」形成互补，避免和下方「最近漏洞」列表重复 -->
                                            <aside class="dashboard-severity-insights" aria-label="风险概览">
                                                <div class="dashboard-severity-insight-risk" data-level="safe">
                                                    <div class="dashboard-severity-insight-head">
                                                        <span class="dashboard-severity-insight-label" data-i18n="dashboard.riskLevel">风险等级</span>
                                                        <span class="dashboard-severity-insight-risk-badge" id="dashboard-severity-risk-level" data-i18n="dashboard.riskSafe">安全</span>
                                                    </div>
                                                    <div class="dashboard-severity-insight-score-track" aria-hidden="true">
                                                        <div class="dashboard-severity-insight-score-fill" id="dashboard-severity-risk-fill" style="width: 0%"></div>
                                                    </div>
                                                    <div class="dashboard-severity-insight-score-meta">
                                                        <span class="dashboard-severity-insight-score-label" data-i18n="dashboard.riskScore">加权风险分</span>
                                                        <span class="dashboard-severity-insight-score-value" id="dashboard-severity-risk-score">0</span>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-insight-urgent-group">
                                                    <span class="dashboard-severity-insight-label" data-i18n="dashboard.statusOpen">待处理</span>
                                                    <div class="dashboard-severity-insight-urgent">
                                                        <div class="dashboard-severity-insight-urgent-item u-critical" role="button" tabindex="0" onclick="switchPage('vulnerabilities')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('vulnerabilities'); }" title="查看待处理严重漏洞">
                                                            <span class="dashboard-severity-insight-urgent-value" id="dashboard-severity-urgent-critical">0</span>
                                                            <span class="dashboard-severity-insight-urgent-label" data-i18n="dashboard.severityCritical">严重</span>
                                                        </div>
                                                        <div class="dashboard-severity-insight-urgent-item u-high" role="button" tabindex="0" onclick="switchPage('vulnerabilities')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('vulnerabilities'); }" title="查看待处理高危漏洞">
                                                            <span class="dashboard-severity-insight-urgent-value" id="dashboard-severity-urgent-high">0</span>
                                                            <span class="dashboard-severity-insight-urgent-label" data-i18n="dashboard.severityHigh">高危</span>
                                                        </div>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-insight-latest">
                                                    <span class="dashboard-severity-insight-label" data-i18n="dashboard.latestFound">最近发现</span>
                                                    <span class="dashboard-severity-insight-time" id="dashboard-severity-latest-time" data-i18n="dashboard.noneYet">暂无</span>
                                                </div>
                                            </aside>
                                            <div class="dashboard-severity-chart">
                                                <svg class="dashboard-severity-donut" id="dashboard-severity-donut" viewBox="0 0 480 260" preserveAspectRatio="xMidYMid meet" role="img" aria-labelledby="dashboard-severity-donut-title">
                                                    <title id="dashboard-severity-donut-title" data-i18n="dashboard.severityDistribution">漏洞严重程度分布</title>
                                                    <defs id="dashboard-severity-donut-defs"></defs>
                                                    <g id="dashboard-severity-donut-track"></g>
                                                    <g id="dashboard-severity-donut-leaders"></g>
                                                    <g id="dashboard-severity-donut-segments"></g>
                                                    <g id="dashboard-severity-donut-hits"></g>
                                                    <g id="dashboard-severity-donut-labels"></g>
                                                </svg>
                                                <div class="dashboard-severity-center" id="dashboard-severity-center">
                                                    <div class="dashboard-severity-center-value" id="dashboard-severity-total">0</div>
                                                    <div class="dashboard-severity-center-label" id="dashboard-severity-center-label" data-i18n="dashboard.totalVulns">总漏洞数</div>
                                                </div>
                                            </div>
                                            <div class="dashboard-severity-legend" id="dashboard-vuln-bars">
                                                <div class="dashboard-severity-legend-item" data-severity="critical" role="button" tabindex="0">
                                                    <span class="dashboard-severity-legend-dot critical"></span>
                                                    <span class="dashboard-severity-legend-label" data-i18n="dashboard.severityCritical">严重</span>
                                                    <span class="dashboard-severity-legend-value" id="dashboard-severity-critical">0</span>
                                                    <span class="dashboard-severity-legend-pct" id="dashboard-severity-critical-pct">0%</span>
                                                </div>
                                                <div class="dashboard-severity-legend-item" data-severity="high" role="button" tabindex="0">
                                                    <span class="dashboard-severity-legend-dot high"></span>
                                                    <span class="dashboard-severity-legend-label" data-i18n="dashboard.severityHigh">高危</span>
                                                    <span class="dashboard-severity-legend-value" id="dashboard-severity-high">0</span>
                                                    <span class="dashboard-severity-legend-pct" id="dashboard-severity-high-pct">0%</span>
                                                </div>
                                                <div class="dashboard-severity-legend-item" data-severity="medium" role="button" tabindex="0">
                                                    <span class="dashboard-severity-legend-dot medium"></span>
                                                    <span class="dashboard-severity-legend-label" data-i18n="dashboard.severityMedium">中危</span>
                                                    <span class="dashboard-severity-legend-value" id="dashboard-severity-medium">0</span>
                                                    <span class="dashboard-severity-legend-pct" id="dashboard-severity-medium-pct">0%</span>
                                                </div>
                                                <div class="dashboard-severity-legend-item" data-severity="low" role="button" tabindex="0">
                                                    <span class="dashboard-severity-legend-dot low"></span>
                                                    <span class="dashboard-severity-legend-label" data-i18n="dashboard.severityLow">低危</span>
                                                    <span class="dashboard-severity-legend-value" id="dashboard-severity-low">0</span>
                                                    <span class="dashboard-severity-legend-pct" id="dashboard-severity-low-pct">0%</span>
                                                </div>
                                                <div class="dashboard-severity-legend-item" data-severity="info" role="button" tabindex="0">
                                                    <span class="dashboard-severity-legend-dot info"></span>
                                                    <span class="dashboard-severity-legend-label" data-i18n="dashboard.severityInfo">信息</span>
                                                    <span class="dashboard-severity-legend-value" id="dashboard-severity-info">0</span>
                                                    <span class="dashboard-severity-legend-pct" id="dashboard-severity-info-pct">0%</span>
                                                </div>
                                            </div>
                                        </div>
                                        <!-- 处置状态 + 修复进度（利用 by_status 数据，避免下半部分留白） -->
                                        <div class="dashboard-severity-status">
                                            <div class="dashboard-severity-status-grid">
                                                <div class="dashboard-severity-status-cell s-open" role="button" tabindex="0" onclick="navigateToVulnerabilitiesWithFilter({status:'open'})" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); navigateToVulnerabilitiesWithFilter({status:'open'}); }">
                                                    <span class="dashboard-severity-status-icon" aria-hidden="true">
                                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
                                                    </span>
                                                    <div class="dashboard-severity-status-text">
                                                        <span class="dashboard-severity-status-value" id="dashboard-status-open">0</span>
                                                        <span class="dashboard-severity-status-label" data-i18n="dashboard.statusOpen">待处理</span>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-status-cell s-confirmed" role="button" tabindex="0" onclick="navigateToVulnerabilitiesWithFilter({status:'confirmed'})" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); navigateToVulnerabilitiesWithFilter({status:'confirmed'}); }">
                                                    <span class="dashboard-severity-status-icon" aria-hidden="true">
                                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
                                                    </span>
                                                    <div class="dashboard-severity-status-text">
                                                        <span class="dashboard-severity-status-value" id="dashboard-status-confirmed">0</span>
                                                        <span class="dashboard-severity-status-label" data-i18n="dashboard.statusConfirmed">已确认</span>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-status-cell s-fixed" role="button" tabindex="0" onclick="navigateToVulnerabilitiesWithFilter({status:'fixed'})" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); navigateToVulnerabilitiesWithFilter({status:'fixed'}); }">
                                                    <span class="dashboard-severity-status-icon" aria-hidden="true">
                                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/><polyline points="9 12 11 14 15 10"/></svg>
                                                    </span>
                                                    <div class="dashboard-severity-status-text">
                                                        <span class="dashboard-severity-status-value" id="dashboard-status-fixed">0</span>
                                                        <span class="dashboard-severity-status-label" data-i18n="dashboard.statusFixed">已修复</span>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-status-cell s-ignored" role="button" tabindex="0" onclick="navigateToVulnerabilitiesWithFilter({status:'ignored'})" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); navigateToVulnerabilitiesWithFilter({status:'ignored'}); }">
                                                    <span class="dashboard-severity-status-icon" aria-hidden="true">
                                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4l16 16"/><path d="M10.58 10.58A3 3 0 0 0 12 15a3 3 0 0 0 2.12-.88"/><path d="M9.88 4.24A9.77 9.77 0 0 1 12 4c7 0 10 8 10 8a18.5 18.5 0 0 1-2.5 3.66"/><path d="M6.61 6.61C3.98 8.38 2 12 2 12s3 8 10 8a9.86 9.86 0 0 0 5.39-1.61"/></svg>
                                                    </span>
                                                    <div class="dashboard-severity-status-text">
                                                        <span class="dashboard-severity-status-value" id="dashboard-status-ignored">0</span>
                                                        <span class="dashboard-severity-status-label" data-i18n="dashboard.statusIgnored">已忽略</span>
                                                    </div>
                                                </div>
                                                <div class="dashboard-severity-status-cell s-fp" role="button" tabindex="0" onclick="navigateToVulnerabilitiesWithFilter({status:'false_positive'})" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); navigateToVulnerabilitiesWithFilter({status:'false_positive'}); }">
                                                    <span class="dashboard-severity-status-icon" aria-hidden="true">
                                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></svg>
                                                    </span>
                                                    <div class="dashboard-severity-status-text">
                                                        <span class="dashboard-severity-status-value" id="dashboard-status-fp">0</span>
                                                        <span class="dashboard-severity-status-label" data-i18n="dashboard.statusFalsePositive">误报</span>
                                                    </div>
                                                </div>
                                            </div>
                                            <div class="dashboard-severity-progress">
                                                <div class="dashboard-severity-progress-meta">
                                                    <span class="dashboard-severity-progress-title" data-i18n="dashboard.fixRate">修复率</span>
                                                    <span class="dashboard-severity-progress-value">
                                                        <span id="dashboard-fix-rate">0%</span>
                                                        <span class="dashboard-severity-progress-detail" id="dashboard-fix-detail">(0 / 0)</span>
                                                    </span>
                                                </div>
                                                <div class="dashboard-severity-progress-track" aria-hidden="true">
                                                    <div class="dashboard-severity-progress-fixed" id="dashboard-fix-progress-fixed" style="width: 0%"></div>
                                                    <div class="dashboard-severity-progress-confirmed" id="dashboard-fix-progress-confirmed" style="width: 0%"></div>
                                                </div>
                                                <div class="dashboard-severity-progress-legend">
                                                    <span class="dashboard-severity-progress-legend-item"><span class="dashboard-severity-progress-legend-dot legend-fixed"></span><span data-i18n="dashboard.statusFixed">已修复</span></span>
                                                    <span class="dashboard-severity-progress-legend-item"><span class="dashboard-severity-progress-legend-dot legend-confirmed"></span><span data-i18n="dashboard.statusConfirmed">已确认</span></span>
                                                    <span class="dashboard-severity-progress-legend-item"><span class="dashboard-severity-progress-legend-dot legend-open"></span><span data-i18n="dashboard.statusOpen">待处理</span></span>
                                                </div>
                                            </div>
                                        </div>
                                    </section>
                                    <section class="dashboard-section dashboard-section-recent-feed">
                                        <div class="dashboard-section-header dashboard-section-header--tabs">
                                            <nav class="dashboard-feed-tabs" role="tablist" aria-label="最近漏洞与近期事实">
                                                <button type="button" class="dashboard-feed-tab is-active" role="tab" id="dashboard-feed-tab-vulns" aria-selected="true" aria-controls="dashboard-feed-panel-vulns" onclick="switchDashboardFeedTab('vulns')" data-i18n="dashboard.recentVulns">最近漏洞</button>
                                                <button type="button" class="dashboard-feed-tab" role="tab" id="dashboard-feed-tab-facts" aria-selected="false" aria-controls="dashboard-feed-panel-facts" onclick="switchDashboardFeedTab('facts')" data-i18n="dashboard.recentFacts">近期事实</button>
                                            </nav>
                                            <a class="dashboard-section-link" id="dashboard-feed-view-all" onclick="switchPage('vulnerabilities')" data-i18n="dashboard.viewAll">查看全部 →</a>
                                        </div>
                                        <div class="dashboard-feed-panel" id="dashboard-feed-panel-vulns" role="tabpanel" aria-labelledby="dashboard-feed-tab-vulns">
                                            <div class="dashboard-recent-vulns" id="dashboard-recent-vulns">
                                                <div class="dashboard-recent-vulns-empty" id="dashboard-recent-vulns-empty" data-i18n="dashboard.noVulnYet">暂无最近漏洞</div>
                                            </div>
                                        </div>
                                        <div class="dashboard-feed-panel" id="dashboard-feed-panel-facts" role="tabpanel" aria-labelledby="dashboard-feed-tab-facts" hidden>
                                            <div class="dashboard-recent-facts" id="dashboard-recent-facts">
                                                <div class="dashboard-recent-facts-empty" id="dashboard-recent-facts-empty" data-i18n="dashboard.noFactsYet">暂无近期事实</div>
                                            </div>
                                        </div>
                                    </section>
                                    <!-- 接入概览：C2 / WebShell Tab 切换（样式同「最近漏洞 / 近期事实」） -->
                                    <section class="dashboard-section dashboard-section-access" id="dashboard-section-access" hidden>
                                        <div class="dashboard-section-header dashboard-section-header--tabs">
                                            <nav class="dashboard-feed-tabs" id="dashboard-access-tabs" role="tablist" aria-label="C2 与 WebShell" data-i18n="dashboard.accessTabsAria" data-i18n-attr="aria-label">
                                                <button type="button" class="dashboard-feed-tab is-active" role="tab" id="dashboard-access-tab-c2" aria-selected="true" aria-controls="dashboard-access-panel-c2" onclick="switchDashboardAccessTab('c2')" data-i18n="nav.c2">C2</button>
                                                <button type="button" class="dashboard-feed-tab" role="tab" id="dashboard-access-tab-webshell" aria-selected="false" aria-controls="dashboard-access-panel-webshell" onclick="switchDashboardAccessTab('webshell')" data-i18n="dashboard.webshellLabel">WebShell</button>
                                            </nav>
                                            <a class="dashboard-section-link" id="dashboard-access-view-all" onclick="switchPage('c2-listeners')" data-i18n="dashboard.c2GoManage">进入 C2 →</a>
                                        </div>
                                        <div class="dashboard-feed-panel" id="dashboard-access-panel-c2" role="tabpanel" aria-labelledby="dashboard-access-tab-c2">
                                            <div class="dashboard-access-strip">
                                                <div class="dashboard-access-stat dashboard-access-stat--c2" role="button" tabindex="0" onclick="switchPage('c2-listeners')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('c2-listeners'); }" data-i18n="dashboard.c2ClickListeners" data-i18n-attr="title" title="查看监听器">
                                                    <span class="dashboard-access-stat-value" id="dashboard-c2-listeners-running">-</span>
                                                    <span class="dashboard-access-stat-label" data-i18n="dashboard.c2ListenersRunning">运行中监听器</span>
                                                </div>
                                                <div class="dashboard-access-stat dashboard-access-stat--c2" role="button" tabindex="0" onclick="switchPage('c2-sessions')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('c2-sessions'); }" data-i18n="dashboard.c2ClickSessions" data-i18n-attr="title" title="查看会话">
                                                    <span class="dashboard-access-stat-value" id="dashboard-c2-sessions-online">-</span>
                                                    <span class="dashboard-access-stat-label" data-i18n="dashboard.c2SessionsOnline">在线会话</span>
                                                </div>
                                                <div class="dashboard-access-stat dashboard-access-stat--c2" role="button" tabindex="0" onclick="switchPage('c2-tasks')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('c2-tasks'); }" data-i18n="dashboard.c2ClickTasks" data-i18n-attr="title" title="查看任务">
                                                    <span class="dashboard-access-stat-value" id="dashboard-c2-tasks-pending">-</span>
                                                    <span class="dashboard-access-stat-label" data-i18n="dashboard.c2TasksPending">待审 / 排队任务</span>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="dashboard-feed-panel" id="dashboard-access-panel-webshell" role="tabpanel" aria-labelledby="dashboard-access-tab-webshell" hidden>
                                            <div class="dashboard-access-strip dashboard-access-strip--webshell">
                                                <div class="dashboard-access-stat dashboard-access-stat--webshell" role="button" tabindex="0" onclick="switchPage('webshell')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('webshell'); }" data-i18n="dashboard.webshellClickConnections" data-i18n-attr="title" title="查看连接">
                                                    <span class="dashboard-access-stat-value" id="dashboard-webshell-connections">-</span>
                                                    <span class="dashboard-access-stat-label" data-i18n="dashboard.webshellConnections">活跃连接</span>
                                                </div>
                                            </div>
                                            <div class="dashboard-webshell-recent" id="dashboard-webshell-recent" hidden></div>
                                        </div>
                                    </section>
                                    <!-- 推荐操作：基于当前数据状态智能生成（如「修复 4 个待处理严重漏洞」「审批 2 个 HITL」），
                                         比纯静态导航更有意义；当没有任何推荐时整个 section 隐藏 -->
                                    <section class="dashboard-section dashboard-section-recommend" id="dashboard-section-recommend" hidden>
                                        <div class="dashboard-section-header">
                                            <h3 class="dashboard-section-title" data-i18n="dashboard.recommendedActions">推荐操作</h3>
                                            <span class="dashboard-section-hint" data-i18n="dashboard.recommendedActionsHint">基于当前状态自动生成</span>
                                        </div>
                                        <div class="dashboard-recommend-list" id="dashboard-recommend-list"></div>
                                    </section>
                                </div>
                                <div class="dashboard-side">
                                    <section class="dashboard-section dashboard-section-batch-side">
                                        <div class="dashboard-section-header">
                                            <h3 class="dashboard-section-title" data-i18n="dashboard.batchQueues">批量任务队列</h3>
                                            <a class="dashboard-section-link" onclick="switchPage('tasks')" data-i18n="dashboard.viewAll">查看全部 →</a>
                                        </div>
                                        <div class="dashboard-batch-side-body" role="button" tabindex="0" onclick="switchPage('tasks')" onkeydown="if(event.key==='Enter'||event.key===' ') { event.preventDefault(); switchPage('tasks'); }">
                                            <div class="dashboard-batch-side-total" id="dashboard-batch-total">-</div>
                                            <div class="dashboard-batch-side-stats">
                                                <div class="dashboard-batch-side-stat dashboard-batch-side-stat--pending">
                                                    <span class="dashboard-batch-side-stat-value" id="dashboard-batch-pending">-</span>
                                                    <span class="dashboard-batch-side-stat-label" data-i18n="dashboard.pending">待执行</span>
                                                </div>
                                                <div class="dashboard-batch-side-stat dashboard-batch-side-stat--running">
                                                    <span class="dashboard-batch-side-stat-value" id="dashboard-batch-running">-</span>
                                                    <span class="dashboard-batch-side-stat-label" data-i18n="dashboard.executing">执行中</span>
                                                </div>
                                                <div class="dashboard-batch-side-stat dashboard-batch-side-stat--done">
                                                    <span class="dashboard-batch-side-stat-value" id="dashboard-batch-done">-</span>
                                                    <span class="dashboard-batch-side-stat-label" data-i18n="dashboard.completed">已完成</span>
                                                </div>
                                            </div>
                                            <div class="dashboard-batch-side-progress" aria-hidden="true">
                                                <div class="dashboard-batch-side-progress-bar">
                                                    <div class="dashboard-batch-side-progress-segment dashboard-batch-side-progress-pending" id="dashboard-batch-progress-pending" style="width: 0%"></div>
                                                    <div class="dashboard-batch-side-progress-segment dashboard-batch-side-progress-running" id="dashboard-batch-progress-running" style="width: 0%"></div>
                                                    <div class="dashboard-batch-side-progress-segment dashboard-batch-side-progress-done" id="dashboard-batch-progress-done" style="width: 0%"></div>
                                                </div>
                                            </div>
                                        </div>
                                    </section>
                                    <section class="dashboard-section dashboard-section-tools">
                                        <div class="dashboard-section-header">
                                            <h3 class="dashboard-section-title" data-i18n="dashboard.toolsExecCount">工具执行次数</h3>
                                            <a class="dashboard-section-link" onclick="switchPage('mcp-monitor')" data-i18n="dashboard.viewAll">查看全部 →</a>
                                        </div>
                                        <div class="dashboard-tools-chart-wrap">
                                            <div class="dashboard-tools-chart-placeholder" id="dashboard-tools-pie-placeholder" data-i18n="common.noData">暂无数据</div>
                                            <div class="dashboard-tools-bar-chart" id="dashboard-tools-bar-chart"></div>
                                        </div>
                                    </section>
                                    <!-- 最近事件：拉 /api/notifications/summary 取最新 3 条；空时整个隐藏 -->
                                    <section class="dashboard-section dashboard-section-events" id="dashboard-section-events" hidden>
                                        <div class="dashboard-section-header">
                                            <h3 class="dashboard-section-title" data-i18n="dashboard.recentEvents">最近事件</h3>
                                            <a class="dashboard-section-link" onclick="if(typeof toggleNotificationDropdown==='function') toggleNotificationDropdown()" data-i18n="dashboard.viewAll">查看全部 →</a>
                                        </div>
                                        <div class="dashboard-events-list" id="dashboard-events-list"></div>
                                    </section>
                                    <section class="dashboard-section dashboard-section-resources">
                                        <h3 class="dashboard-section-title" data-i18n="dashboard.capabilities">能力总览</h3>
                                        <div class="dashboard-resource-list" id="dashboard-resource-list">
                                            <a class="dashboard-resource-item" onclick="switchPage('mcp-management')" role="button" tabindex="0">
                                                <span class="dashboard-resource-icon dashboard-resource-icon-mcp" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.mcpTools">MCP 工具</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-tools">-</span>
                                            </a>
                                            <!-- External MCP 服务器健康度：N 运行 / N 异常；只有配置过 External MCP 才显示 -->
                                            <a class="dashboard-resource-item" id="dashboard-resource-external-mcp-row" onclick="switchPage('mcp-management')" role="button" tabindex="0" hidden>
                                                <span class="dashboard-resource-icon dashboard-resource-icon-external" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.externalMcpServers">External MCP</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-external-mcp">
                                                    <span id="dashboard-resource-external-mcp-text">-</span>
                                                    <span class="dashboard-resource-health" id="dashboard-resource-external-mcp-health" hidden></span>
                                                </span>
                                            </a>
                                            <a class="dashboard-resource-item" onclick="switchPage('skills-management')" role="button" tabindex="0">
                                                <span class="dashboard-resource-icon dashboard-resource-icon-skills" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.skillsLabel">Skills</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-skills">-</span>
                                            </a>
                                            <a class="dashboard-resource-item" onclick="switchPage('knowledge-management')" role="button" tabindex="0">
                                                <span class="dashboard-resource-icon dashboard-resource-icon-knowledge" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.knowledgeLabel">知识</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-knowledge">-</span>
                                            </a>
                                            <a class="dashboard-resource-item" onclick="switchPage('roles-management')" role="button" tabindex="0">
                                                <span class="dashboard-resource-icon dashboard-resource-icon-roles" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.rolesLabel">角色</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-roles">-</span>
                                            </a>
                                            <a class="dashboard-resource-item" onclick="switchPage('agents-management')" role="button" tabindex="0">
                                                <span class="dashboard-resource-icon dashboard-resource-icon-agents" aria-hidden="true">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>
                                                </span>
                                                <span class="dashboard-resource-label" data-i18n="dashboard.agentsLabel">Agents</span>
                                                <span class="dashboard-resource-value" id="dashboard-resource-agents">-</span>
                                            </a>
                                        </div>
                                    </section>
                                </div>
                            </div>
                            <!-- "开始你的安全之旅" CTA：默认显示；当用户已经有数据（任务/漏洞/调用）后，由 JS 隐藏避免冗余 -->
                            <div class="dashboard-cta-block" id="dashboard-cta-block">
                                <div class="dashboard-cta-content">
                                    <div class="dashboard-cta-icon" aria-hidden="true">
                                        <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
                                    </div>
                                    <div class="dashboard-cta-copy">
                                        <p class="dashboard-cta-text" data-i18n="dashboard.ctaTitle">开始你的安全之旅</p>
                                        <p class="dashboard-cta-sub" data-i18n="dashboard.ctaSub">在对话中描述目标，AI 将协助执行扫描与漏洞分析</p>
                                    </div>
                                </div>
                                <button class="dashboard-cta-btn" onclick="switchPage('chat')">
                                    <span data-i18n="dashboard.goToChat">前往对话</span>
                                    <span class="dashboard-cta-btn-arrow" aria-hidden="true"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M5 12h14M12 5l7 7-7 7"/></svg></span>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 对话页面 -->
                <div id="page-chat" class="page">
                    <div class="chat-page-layout">
                        <!-- 历史对话侧边栏（可折叠，与主导航侧边栏类似） -->
                        <aside class="conversation-sidebar" id="conversation-sidebar">
                            <!-- 头部一行：折叠与「新任务」并排；任务底层复用会话数据 -->
                            <div class="sidebar-header conversation-sidebar-header">
                                <button type="button" class="new-chat-btn" data-require-permission="chat:write" onclick="startNewConversation()">
                                    <span>+</span> <span data-i18n="chat.newTask">新任务</span>
                                </button>
                                <button type="button" class="conversation-sidebar-collapse-btn" onclick="toggleConversationSidebar()" data-i18n="chat.toggleConversationPanel" data-i18n-attr="title" data-i18n-skip-text="true" title="折叠/展开对话列表" aria-label="折叠/展开对话列表">
                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                        <path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                    </svg>
                                </button>
                            </div>
                            <div class="sidebar-content">
                                <!-- 项目搜索 -->
                                <div class="conversation-search-box">
                                    <input type="text" id="conversation-search-input" data-i18n="projects.searchProjectsPlaceholder" data-i18n-attr="placeholder" placeholder="搜索项目…"
                                           oninput="handleProjectFolderSearch(this.value)"
                                           onkeypress="if(event.key === 'Enter') handleProjectFolderSearch(this.value)" />
                                    <button class="conversation-search-clear" id="conversation-search-clear" 
                                            onclick="clearProjectFolderSearch()" style="display: none;" data-i18n="common.clearSearch" data-i18n-attr="title" title="清除搜索">
                                        <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                            <circle cx="8" cy="8" r="7" fill="currentColor" fill-opacity="0.2"/>
                                            <path d="M5.25 5.25l5.5 5.5M10.75 5.25l-5.5 5.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                                        </svg>
                                    </button>
                                </div>

                                <!-- 项目文件夹：复用对话底部项目选择器的真实项目数据 -->
                                <section class="project-folders-section" aria-labelledby="project-folders-title">
                                    <div class="section-header project-folders-header">
                                        <span id="project-folders-title" class="section-title" data-i18n="chat.projectFolders">项目</span>
                                        <button type="button" class="add-group-btn project-folders-add-btn" data-require-permission="project:write" onclick="showNewProjectModalFromChatSidebar()" data-i18n="projects.newProject" data-i18n-attr="title,aria-label" data-i18n-skip-text="true" title="新建项目" aria-label="新建项目">
                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                <path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                        </button>
                                    </div>
                                    <div id="project-folders-list" class="project-folders-list"></div>
                                </section>

                                <!-- 按项目筛选对话 -->
                                <div class="conversation-project-filter" hidden>
                                    <label class="conversation-project-filter-label" for="conversation-project-filter" data-i18n="chat.filterByProject">按项目筛选</label>
                                    <select id="conversation-project-filter" class="conversation-project-filter-native" onchange="onConversationProjectFilterChange(this.value)" data-i18n="chat.filterByProject" data-i18n-attr="title" title="按项目筛选">
                                        <option value="" data-i18n="chat.filterAllProjects">全部项目</option>
                                        <option value="__none__" data-i18n="chat.filterUnboundProjects">未绑定项目</option>
                                    </select>
                                </div>
                                
                                <!-- 最近对话 -->
                                <div class="recent-conversations-section is-collapsed" id="recent-conversations-section">
                                    <button type="button" class="section-header recent-conversations-toggle" id="recent-conversations-toggle" onclick="toggleRecentConversations()" aria-expanded="false" aria-controls="recent-conversations-body" data-i18n="chat.toggleRecentConversations" data-i18n-attr="title,aria-label" data-i18n-skip-text="true" title="展开/折叠最近对话" aria-label="展开/折叠最近对话">
                                        <span class="section-title" data-i18n="chat.recentConversations">最近对话</span>
                                        <span class="recent-conversations-toggle-meta">
                                            <span id="recent-conversations-count" class="recent-conversations-count">0</span>
                                            <svg class="recent-conversations-chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                        </span>
                                    </button>
                                    <div id="recent-conversations-body" class="recent-conversations-body" hidden>
                                        <div class="section-header-actions recent-conversations-actions">
                                            <div class="conversation-sort-dropdown" id="conversation-sort-dropdown">
                                                <button type="button" class="conversation-sort-btn" id="conversation-sort-btn" onclick="toggleConversationSortMenu(event)" aria-haspopup="menu" aria-expanded="false" aria-controls="conversation-sort-menu" data-i18n="chat.sortConversations" data-i18n-attr="title" data-i18n-skip-text="true" title="排序">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                        <path d="M3 6h18M7 12h10M10 18h4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                    </svg>
                                                </button>
                                                <div class="conversation-sort-menu" id="conversation-sort-menu" role="menu" hidden>
                                                    <button type="button" class="conversation-sort-option" role="menuitemradio" data-sort="created_at" onclick="setConversationSortBy('created_at')">
                                                        <span class="conversation-sort-option-icon" aria-hidden="true">
                                                            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                                <rect x="3" y="5" width="18" height="16" rx="2.5" stroke="currentColor" stroke-width="1.75"/>
                                                                <path d="M3 10h18" stroke="currentColor" stroke-width="1.75"/>
                                                                <path d="M8 3v3M16 3v3" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/>
                                                                <circle cx="12" cy="15" r="1.75" fill="currentColor"/>
                                                            </svg>
                                                        </span>
                                                        <span class="conversation-sort-option-label" data-i18n="chat.sortByCreatedAt">创建时间</span>
                                                        <span class="conversation-sort-option-check" aria-hidden="true">✓</span>
                                                    </button>
                                                    <button type="button" class="conversation-sort-option" role="menuitemradio" data-sort="updated_at" onclick="setConversationSortBy('updated_at')">
                                                        <span class="conversation-sort-option-icon" aria-hidden="true">
                                                            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                                <circle cx="12" cy="12" r="8" stroke="currentColor" stroke-width="1.75"/>
                                                                <path d="M12 8v4.5l3 2" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"/>
                                                            </svg>
                                                        </span>
                                                        <span class="conversation-sort-option-label" data-i18n="chat.sortByUpdatedAt">更新时间</span>
                                                        <span class="conversation-sort-option-check" aria-hidden="true">✓</span>
                                                    </button>
                                                </div>
                                            </div>
                                            <button class="batch-manage-btn" data-require-permission="chat:delete" onclick="showBatchManageModal()" data-i18n="chat.batchManage" data-i18n-attr="title" data-i18n-skip-text="true" title="批量管理">
                                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <line x1="3" y1="12" x2="21" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                    <line x1="3" y1="6" x2="21" y2="6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                    <line x1="3" y1="18" x2="21" y2="18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                    <circle cx="8" cy="6" r="1" fill="currentColor"/>
                                                    <circle cx="8" cy="12" r="1" fill="currentColor"/>
                                                    <circle cx="8" cy="18" r="1" fill="currentColor"/>
                                                </svg>
                                            </button>
                                        </div>
                                        <div id="conversations-list" class="conversations-list"></div>
                                    </div>
                                </div>
                            </div>
                            <div id="conversations-pagination" class="sidebar-list-pagination conversation-sidebar-pagination"></div>
                            <div id="chat-reasoning-wrapper" class="chat-reasoning-wrapper conversation-reasoning-card conversation-reasoning-collapsed" style="display: none;">
                                <button type="button" id="conversation-reasoning-toggle" class="conversation-reasoning-card-header" onclick="toggleConversationReasoningCard()" aria-expanded="false" aria-controls="conversation-reasoning-body" data-i18n="chat.sessionSettingsAria" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="会话设置" title="会话设置">
                                    <div class="conversation-reasoning-heading">
                                        <span class="conversation-reasoning-icon" aria-hidden="true">
                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="1.75"/>
                                                <path d="M16 16l5 5" stroke="currentColor" stroke-width="1.75" stroke-linecap="round"/>
                                            </svg>
                                        </span>
                                        <div class="conversation-reasoning-heading-text">
                                            <span class="conversation-reasoning-title" data-i18n="chat.sessionSettingsTitle">会话设置</span>
                                            <span id="chat-reasoning-summary" class="conversation-reasoning-summary"></span>
                                        </div>
                                    </div>
                                    <span class="sidebar-card-chevron conversation-reasoning-chevron" aria-hidden="true">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                    </span>
                                </button>
                                <div id="conversation-reasoning-body" class="conversation-reasoning-body" role="region">
                                    <p class="chat-reasoning-panel-hint" data-i18n="chat.sessionSettingsHint">人机协同设置只影响后续消息。</p>
                                    <div class="chat-reasoning-fields">
	                                        <div class="chat-reasoning-field session-hitl-field session-settings-group">
	                                            <div class="session-settings-group-title" data-i18n="chat.hitlTitle">人机协同</div>
	                                            <div id="hitl-apply-feedback" class="hitl-apply-feedback" role="status" aria-live="polite"></div>
	                                            <div class="hitl-sidebar-config session-hitl-config">
	                                                <div class="hitl-config-field">
	                                                    <label class="hitl-config-label" for="hitl-mode-select" data-i18n="chat.reasoningModeLabel">模式</label>
	                                                    <select id="hitl-mode-select" class="hitl-config-select">
	                                                        <option value="off" data-i18n="chat.hitlModeOff">关闭</option>
	                                                        <option value="approval" data-i18n="chat.hitlModeApproval">审批模式</option>
	                                                        <option value="review_edit" data-i18n="chat.hitlModeReviewEdit">审查编辑</option>
	                                                    </select>
	                                                </div>
	                                                <div class="hitl-config-field" id="hitl-reviewer-field">
	                                                    <label class="hitl-config-label" data-i18n="chat.hitlReviewerLabel">审批方</label>
	                                                    <div class="hitl-reviewer-toggle" role="group" aria-label="Reviewer">
	                                                        <button type="button" class="hitl-reviewer-toggle-btn is-active" data-reviewer="human" aria-pressed="true">
	                                                            <span data-i18n="chat.hitlReviewerHuman">人工审批</span>
	                                                        </button>
	                                                        <button type="button" class="hitl-reviewer-toggle-btn" data-reviewer="audit_agent" aria-pressed="false">
	                                                            <span data-i18n="chat.hitlReviewerAgent">审计 Agent</span>
	                                                        </button>
	                                                    </div>
	                                                    <input type="hidden" id="hitl-reviewer-select" value="human" />
	                                                    <p class="hitl-config-hint" data-i18n="chat.hitlReviewerHint">可在人工与审计 Agent 之间随时切换；规则与白名单不变。人机协同为「关闭」时也可预先选择。</p>
	                                                </div>
	                                                <div class="hitl-config-field" id="hitl-timeout-field">
	                                                    <label class="hitl-config-label" for="hitl-timeout-select" data-i18n="chat.hitlTimeoutLabel">审批等待时限</label>
	                                                    <select id="hitl-timeout-select" class="hitl-config-select">
	                                                        <option value="60" data-i18n="chat.hitlTimeoutOneMinute">1 分钟</option>
	                                                        <option value="300" selected data-i18n="chat.hitlTimeoutFiveMinutes">5 分钟</option>
	                                                        <option value="600" data-i18n="chat.hitlTimeoutTenMinutes">10 分钟</option>
	                                                        <option value="0" data-i18n="chat.hitlTimeoutUnlimited">不限制</option>
	                                                    </select>
	                                                    <p class="hitl-config-hint" data-i18n="chat.hitlTimeoutHint">到期未处理将自动拒绝；审批卡片会显示倒计时。</p>
	                                                </div>
	                                                <div class="hitl-config-field hitl-config-field--tools">
	                                                    <label class="hitl-config-label" for="hitl-sensitive-tools" data-i18n="chat.hitlWhitelistTools">白名单工具（免审批，逗号分隔）</label>
	                                                    <textarea id="hitl-sensitive-tools" class="hitl-config-textarea" rows="6" spellcheck="false" autocomplete="off" data-i18n="chat.hitlWhitelistPlaceholder" data-i18n-attr="placeholder" placeholder=""></textarea>
	                                                    <p class="hitl-config-hint" data-i18n="chat.hitlWhitelistHint">每行一个或逗号分隔；与 config 中全局白名单合并生效。</p>
	                                                </div>
	                                            </div>
	                                        </div>
	                                    </div>
	                                </div>
	                            </div>
	                        </aside>
                        
                        <!-- 对话界面 -->
                        <div class="chat-container">
                            <!-- 会话顶部栏（只在有会话选中时显示） -->
                            <div id="conversation-header" class="conversation-header" style="display: none;">
                                <div class="conversation-header-content">
                                    <button id="attack-chain-btn" class="attack-chain-btn" data-i18n="chat.viewAttackChain" data-i18n-attr="title" data-i18n-skip-text="true" title="查看攻击链" disabled>
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <path d="M10.5 13.5l3-3M8 8H5a4 4 0 1 0 0 8h3m8-8h3a4 4 0 0 1 0 8h-3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                        <span data-i18n="chat.attackChain">攻击链</span>
                                    </button>
                                </div>
                            </div>
                            <div id="active-tasks-bar" class="active-tasks-bar"></div>
                            <div id="chat-messages" class="chat-messages"></div>
                            <nav id="chat-turn-rail" class="chat-turn-rail" aria-label="对话轮次导航" hidden>
                                <div id="chat-turn-rail-markers" class="chat-turn-rail-markers"></div>
                            </nav>
                            <div id="chat-turn-rail-preview" class="chat-turn-rail-preview" role="tooltip" hidden>
                                <div id="chat-turn-rail-preview-title" class="chat-turn-rail-preview-title"></div>
                                <div id="chat-turn-rail-preview-summary" class="chat-turn-rail-preview-summary"></div>
                            </div>
                            <button type="button" id="chat-return-latest" class="chat-return-latest" hidden
                                    data-i18n="chat.returnToLatest" data-i18n-attr="title,aria-label" data-i18n-skip-text="true"
                                    title="回到最新消息" aria-label="回到最新消息">
                                <span class="chat-return-latest-dots" aria-hidden="true">
                                    <span class="chat-return-latest-dot"></span>
                                    <span class="chat-return-latest-dot"></span>
                                    <span class="chat-return-latest-dot"></span>
                                </span>
                            </button>
                            <div id="agent-plan-progress" class="agent-plan-progress" hidden aria-live="polite"></div>
                            <div id="chat-input-container" class="chat-input-container">
                                <div class="chat-composer-context" aria-label="当前会话上下文">
                                <div class="chat-input-leading">
                                <div class="role-selector-wrapper project-selector-wrapper">
                                    <button type="button" id="chat-project-btn" class="role-selector-btn" onclick="toggleChatProjectPanel()" aria-label="选择项目" aria-haspopup="listbox" aria-expanded="false" title="绑定项目后共享事实黑板（跨对话）" data-i18n="projects.chatSelectorButton" data-i18n-attr="aria-label,title">
                                        <span class="role-selector-icon" aria-hidden="true">
                                            <svg width="19" height="19" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                <path d="M3.5 6.5A2.5 2.5 0 0 1 6 4h4l2 2h6A2.5 2.5 0 0 1 20.5 8.5v8A2.5 2.5 0 0 1 18 19H6a2.5 2.5 0 0 1-2.5-2.5v-10z" stroke="currentColor" stroke-width="1.7" stroke-linejoin="round"/>
                                            </svg>
                                        </span>
                                        <span id="chat-project-text" class="role-selector-text" data-i18n="projects.noProject">无项目</span>
                                        <svg class="role-selector-arrow" width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                            <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                    </button>
                                    <div id="chat-project-panel" class="role-selection-panel chat-project-panel" style="display: none;" role="listbox" aria-labelledby="chat-project-panel-title">
                                        <div class="role-selection-panel-header">
                                            <h3 id="chat-project-panel-title" class="role-selection-panel-title" data-i18n="projects.selectProject">选择项目</h3>
                                            <button type="button" class="role-selection-panel-close" onclick="closeChatProjectPanel()" title="关闭" aria-label="关闭">
                                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                                </svg>
                                            </button>
                                        </div>
                                        <div class="chat-project-panel-body">
                                            <div class="chat-project-panel-search">
                                                <input type="search" id="chat-project-search" class="chat-project-panel-search-input" autocomplete="off" data-i18n="projects.searchProjectsPlaceholder" data-i18n-attr="placeholder" placeholder="搜索项目…">
                                            </div>
                                            <div id="chat-project-list" class="role-selection-list-main"></div>
                                            <div class="chat-project-panel-footer">
                                                <button type="button" class="role-selection-item-main chat-project-panel-create-btn" data-require-permission="project:write" onclick="showNewProjectModalFromChat()">
                                                    <span class="chat-project-panel-create-icon" aria-hidden="true">+</span>
                                                    <span class="chat-project-panel-create-label" data-i18n="projects.newProject">新建项目</span>
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div id="role-selector-wrapper" class="role-selector-wrapper">
                                    <button type="button" id="role-selector-btn" class="role-selector-btn" onclick="toggleRoleSelectionPanel()" data-i18n="chat.selectRole" data-i18n-attr="title" title="选择角色">
                                        <span id="role-selector-icon" class="role-selector-icon">🔵</span>
                                        <span id="role-selector-text" class="role-selector-text" data-i18n="chat.defaultRole">默认</span>
                                        <svg class="role-selector-arrow" width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                            <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                    </button>
                                    <!-- 角色选择下拉面板 -->
                                    <div id="role-selection-panel" class="role-selection-panel" style="display: none;">
                                        <div class="role-selection-panel-header">
                                            <h3 class="role-selection-panel-title" data-i18n="chat.rolePanelTitle">选择角色</h3>
                                            <button class="role-selection-panel-close" onclick="closeRoleSelectionPanel()" data-i18n="common.close" data-i18n-attr="title" title="关闭">
                                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                                </svg>
                                            </button>
                                        </div>
                                        <div id="role-selection-list" class="role-selection-list-main"></div>
                                    </div>
                                </div>
                                <div id="agent-mode-wrapper" class="agent-mode-wrapper" style="display: none;">
                                    <div class="agent-mode-inner">
                                        <button type="button" id="agent-mode-btn" class="role-selector-btn agent-mode-btn" onclick="toggleAgentModePanel()" data-i18n="chat.agentModeSelectAria" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="选择对话执行模式" aria-haspopup="listbox" aria-expanded="false" title="选择对话执行模式">
                                            <span id="agent-mode-icon" class="role-selector-icon agent-mode-logo agent-mode-logo--default" aria-hidden="true"><svg class="agent-mode-logo__svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h.01"/><path d="M16 16h.01"/></svg></span>
                                            <span id="agent-mode-text" class="role-selector-text">单代理</span>
                                            <svg class="role-selector-arrow" width="10" height="10" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                        </button>
                                        <div id="agent-mode-panel" class="agent-mode-panel" style="display: none;" role="listbox" aria-labelledby="agent-mode-panel-title">
                                            <div class="role-selection-panel-header agent-mode-panel-header">
                                                <h3 id="agent-mode-panel-title" class="role-selection-panel-title" data-i18n="chat.agentModePanelTitle">对话模式</h3>
                                                <button type="button" class="role-selection-panel-close" onclick="closeAgentModePanel()" data-i18n="common.close" data-i18n-attr="title" title="关闭">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                        <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                                    </svg>
                                                </button>
                                            </div>
                                            <div class="agent-mode-options">
                                                <button type="button" class="role-selection-item-main agent-mode-option" data-value="eino_single" role="option" onclick="selectAgentMode('eino_single')" data-agent-mode-detail="CloudWeGo Eino ChatModelAgent + Runner，MCP 工具（/api/eino-agent）" data-i18n="chat.agentModeEinoSingleHint" data-i18n-attr="data-agent-mode-detail" data-i18n-skip-text="true">
                                                    <div class="role-selection-item-icon-main agent-mode-logo agent-mode-logo--eino" aria-hidden="true"><svg class="agent-mode-logo__svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h.01"/><path d="M16 16h.01"/></svg></div>
                                                    <div class="role-selection-item-content-main">
                                                        <div class="role-selection-item-name-main" data-i18n="chat.agentModeEinoSingle">Eino 单代理（ADK）</div>
                                                        <div class="role-selection-item-description-main" data-i18n="chat.agentModeEinoSingleHint">CloudWeGo Eino ChatModelAgent + Runner，MCP 工具（/api/eino-agent）</div>
                                                    </div>
                                                    <div class="role-selection-checkmark-main agent-mode-check" data-agent-mode-check="eino_single">✓</div>
                                                </button>
                                                <button type="button" class="role-selection-item-main agent-mode-option" data-value="deep" role="option" onclick="selectAgentMode('deep')" data-agent-mode-detail="Eino DeepAgent，适合复杂安全测试、多阶段 task 子代理委派与汇总" data-i18n="chat.agentModeDeepHint" data-i18n-attr="data-agent-mode-detail" data-i18n-skip-text="true">
                                                    <div class="role-selection-item-icon-main agent-mode-logo agent-mode-logo--deep" aria-hidden="true"><svg class="agent-mode-logo__svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h.01"/><path d="M16 16h.01"/></svg></div>
                                                    <div class="role-selection-item-content-main">
                                                        <div class="role-selection-item-name-main" data-i18n="chat.agentModeDeep">Deep（DeepAgent）</div>
                                                        <div class="role-selection-item-description-main" data-i18n="chat.agentModeDeepHint">Eino DeepAgent，适合复杂安全测试、多阶段 task 子代理委派与汇总</div>
                                                    </div>
                                                    <div class="role-selection-checkmark-main agent-mode-check" data-agent-mode-check="deep">✓</div>
                                                </button>
                                                <button type="button" class="role-selection-item-main agent-mode-option" data-value="plan_execute" role="option" onclick="selectAgentMode('plan_execute')" data-agent-mode-detail="规划 → 执行 → 重规划（单执行器工具链）" data-i18n="chat.agentModePlanExecuteHint" data-i18n-attr="data-agent-mode-detail" data-i18n-skip-text="true">
                                                    <div class="role-selection-item-icon-main agent-mode-logo agent-mode-logo--plan" aria-hidden="true"><svg class="agent-mode-logo__svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h.01"/><path d="M16 16h.01"/></svg></div>
                                                    <div class="role-selection-item-content-main">
                                                        <div class="role-selection-item-name-main" data-i18n="chat.agentModePlanExecuteLabel">Plan-Execute</div>
                                                        <div class="role-selection-item-description-main" data-i18n="chat.agentModePlanExecuteHint">规划 → 执行 → 重规划（单执行器工具链）</div>
                                                    </div>
                                                    <div class="role-selection-checkmark-main agent-mode-check" data-agent-mode-check="plan_execute">✓</div>
                                                </button>
                                                <button type="button" class="role-selection-item-main agent-mode-option" data-value="supervisor" role="option" onclick="selectAgentMode('supervisor')" data-agent-mode-detail="专家路由场景：监督者通过 transfer 动态分派多个专业子代理" data-i18n="chat.agentModeSupervisorHint" data-i18n-attr="data-agent-mode-detail" data-i18n-skip-text="true">
                                                    <div class="role-selection-item-icon-main agent-mode-logo agent-mode-logo--supervisor" aria-hidden="true"><svg class="agent-mode-logo__svg" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="11" width="18" height="10" rx="2"/><circle cx="12" cy="5" r="2"/><path d="M12 7v4"/><path d="M8 16h.01"/><path d="M16 16h.01"/></svg></div>
                                                    <div class="role-selection-item-content-main">
                                                        <div class="role-selection-item-name-main" data-i18n="chat.agentModeSupervisorLabel">Supervisor（专家路由）</div>
                                                        <div class="role-selection-item-description-main" data-i18n="chat.agentModeSupervisorHint">专家路由场景：监督者通过 transfer 动态分派多个专业子代理</div>
                                                    </div>
                                                    <div class="role-selection-checkmark-main agent-mode-check" data-agent-mode-check="supervisor">✓</div>
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                    <input type="hidden" id="agent-mode-select" value="eino_single" autocomplete="off">
                                </div>
                                </div>
                                </div>
                                <section id="chat-hitl-approval-dock" class="chat-hitl-approval-dock" aria-label="待审批操作" aria-live="polite" hidden></section>
                                <div class="chat-input-primary-row chat-composer-surface">
                                <div class="chat-input-with-files">
                                    <div id="chat-file-list" class="chat-file-list" aria-label="已选文件列表"></div>
                                    <div id="chat-attachment-progress" class="chat-upload-progress-row" hidden role="status" aria-live="polite">
                                        <div class="chat-upload-progress-track" aria-hidden="true"><div class="chat-upload-progress-fill" id="chat-attachment-progress-fill"></div></div>
                                        <span class="chat-upload-progress-label" id="chat-attachment-progress-label"></span>
                                    </div>
                                    <div class="chat-input-field">
                                        <textarea id="chat-input" data-i18n="chat.inputPlaceholder" data-i18n-attr="placeholder" data-i18n-skip-text="true" placeholder="输入测试目标或命令…  @ 选择工具" rows="1"></textarea>
                                        <div id="mention-suggestions" class="mention-suggestions" role="listbox" aria-label="工具提及候选"></div>
                                    </div>
                                </div>
                                <div class="chat-composer-footer">
                                    <div class="chat-composer-footer-leading">
                                        <input type="file" id="chat-file-input" class="chat-file-input-hidden" multiple accept="*" data-i18n="chat.selectFile" data-i18n-attr="title" title="选择文件">
                                        <button type="button" class="chat-upload-btn" onclick="document.getElementById('chat-file-input').click()" data-i18n="chat.uploadFile" data-i18n-attr="title,aria-label" data-i18n-skip-text="true" title="上传文件（可多选或拖拽到此处）" aria-label="上传文件（可多选或拖拽到此处）">
                                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                <path d="M12 5v14M5 12h14" stroke="currentColor" stroke-width="1.8" stroke-linecap="round"/>
                                            </svg>
                                        </button>
                                        <button type="button" id="chat-hitl-shortcut" class="chat-session-shortcut chat-hitl-shortcut" onclick="openChatSessionSettings('hitl', event)" data-i18n="chat.sessionSettingsAria" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="打开会话设置" title="打开会话设置">
                                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                <path d="M12 3l7 3v5c0 4.6-2.8 8.2-7 10-4.2-1.8-7-5.4-7-10V6l7-3z" stroke="currentColor" stroke-width="1.65" stroke-linejoin="round"/>
                                                <path d="M9.5 12l1.7 1.7 3.5-3.7" stroke="currentColor" stroke-width="1.65" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                            <span id="chat-hitl-shortcut-text">Agent 审查：关闭</span>
                                            <svg class="chat-session-shortcut-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                                                <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                        </button>
                                    </div>
                                    <div class="chat-composer-footer-trailing">
                                        <div class="chat-ai-session-state" hidden>
                                            <select id="chat-ai-channel-select" onchange="persistChatAIChannelPref()">
                                                <option value="" data-i18n="chat.aiChannelDefault">跟随默认通道</option>
                                            </select>
                                            <select id="chat-reasoning-mode" onchange="persistChatReasoningPrefs()">
                                                <option value="default" data-i18n="chat.reasoningModeDefault">跟随系统</option>
                                                <option value="off" data-i18n="chat.reasoningModeOff">关闭</option>
                                                <option value="on" data-i18n="chat.reasoningModeOn">开启</option>
                                                <option value="auto" data-i18n="chat.reasoningModeAuto">自动</option>
                                            </select>
                                            <select id="chat-reasoning-effort" onchange="persistChatReasoningPrefs()">
                                                <option value="" data-i18n="chat.reasoningEffortUnset">不指定</option>
                                                <option value="low">low</option>
                                                <option value="medium">medium</option>
                                                <option value="high">high</option>
                                                <option value="xhigh">xhigh</option>
                                                <option value="max">max</option>
                                            </select>
                                        </div>
                                        <div id="chat-model-shortcut-wrap" class="chat-model-shortcut-wrap">
                                            <button type="button" id="chat-model-shortcut" class="chat-session-shortcut chat-session-meta" onclick="openChatSystemModelPicker(event)" data-i18n="chat.modelSettingsAria" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="选择 AI 通道、模型与推理设置" title="选择 AI 通道、模型与推理设置" aria-haspopup="dialog" aria-expanded="false" aria-controls="chat-system-model-menu">
                                                <span id="chat-model-shortcut-text">默认通道</span>
                                                <span id="chat-model-shortcut-effort" class="chat-model-shortcut-effort">不指定</span>
                                                <svg class="chat-system-model-caret" width="12" height="12" viewBox="0 0 24 24" fill="none" aria-hidden="true">
                                                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/>
                                                </svg>
                                            </button>
                                            <div id="chat-system-model-menu" class="chat-system-model-menu" role="dialog" aria-label="AI 通道、模型与推理设置" hidden>
                                                <div id="chat-system-model-main" class="chat-system-model-main">
                                                    <button type="button" class="chat-system-model-setting-row" onclick="openChatSystemModelView('channel', event)">
                                                        <span class="chat-system-model-setting-label" data-i18n="chat.aiChannelLabel">AI 通道</span>
                                                        <span class="chat-system-model-setting-value">
                                                            <span id="chat-system-model-channel-value">默认通道</span>
                                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9 6l6 6-6 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                        </span>
                                                    </button>
                                                    <button type="button" class="chat-system-model-setting-row" onclick="openChatSystemModelView('model', event)">
                                                        <span class="chat-system-model-setting-label" data-i18n="chat.systemModelField">模型</span>
                                                        <span class="chat-system-model-setting-value">
                                                            <span id="chat-system-model-current-value">默认通道</span>
                                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9 6l6 6-6 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                        </span>
                                                    </button>
                                                    <div class="chat-system-model-section-divider" role="separator"></div>
                                                    <button type="button" class="chat-system-model-setting-row" onclick="openChatSystemModelView('mode', event)">
                                                        <span class="chat-system-model-setting-label" data-i18n="chat.reasoningModeLabel">推理模式</span>
                                                        <span class="chat-system-model-setting-value">
                                                            <span id="chat-system-model-mode-value">跟随系统</span>
                                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9 6l6 6-6 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                        </span>
                                                    </button>
                                                    <button type="button" class="chat-system-model-setting-row" onclick="openChatSystemModelView('effort', event)">
                                                        <span class="chat-system-model-setting-label" data-i18n="chat.reasoningEffortLabel">推理强度</span>
                                                        <span class="chat-system-model-setting-value">
                                                            <span id="chat-system-model-effort-value">不指定</span>
                                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M9 6l6 6-6 6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                        </span>
                                                    </button>
                                                    <span id="chat-system-model-status" class="chat-system-model-status chat-system-model-status-live" aria-live="polite"></span>
                                                </div>
                                                <div id="chat-system-model-subview" class="chat-system-model-subview" hidden>
                                                    <div class="chat-system-model-menu-header">
                                                        <button type="button" class="chat-system-model-back" onclick="openChatSystemModelView('main', event)" aria-label="返回">
                                                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M15 18l-6-6 6-6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                        </button>
                                                        <strong id="chat-system-model-subview-title">模型</strong>
                                                        <span id="chat-system-model-subview-status" class="chat-system-model-status"></span>
                                                    </div>
                                                    <div id="chat-system-model-list" class="chat-system-model-list" role="listbox" aria-label="选项列表"></div>
                                                </div>
                                            </div>
                                        </div>
                                        <button type="button" class="send-btn" id="chat-send-btn" data-require-permission="chat:write" onclick="sendMessage()" data-i18n="chat.send" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="发送" title="发送">
                                            <span class="send-btn-label" data-i18n="chat.send">发送</span>
                                            <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                                <path d="M12 19V5M6.5 10.5L12 5l5.5 5.5" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                        </button>
                                    </div>
                                </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <div id="page-tool-guard" class="page tool-guard-page">
                    <div class="page-header">
                        <h2 data-i18n="toolGuard.title">调用拦截</h2>
                        <div class="page-header-actions">
                            <span id="tool-guard-save-state" class="tool-guard-save-state" aria-live="polite"></span>
                            <button type="button" id="tool-guard-open-test" class="btn-secondary" data-require-permission="config:read" onclick="openToolGuardTest()" data-i18n="toolGuard.testEntry" disabled>全部规则验证</button>
                            <button type="button" id="tool-guard-reset" class="btn-secondary" data-require-permission="config:write" onclick="resetToolGuardConfig()" data-i18n="toolGuard.reset" disabled>撤销修改</button>
                            <button type="button" id="tool-guard-save" class="btn-primary" data-require-permission="config:write" onclick="saveToolGuardConfig()" data-i18n="toolGuard.save" disabled>保存并生效</button>
                        </div>
                    </div>
                    <div class="page-content tool-guard-content">
                        <div id="tool-guard-feedback" class="tool-guard-feedback" role="status" aria-live="polite" hidden></div>
                        <section class="tool-guard-card tool-guard-policy" aria-labelledby="tool-guard-protection-status">
                            <div class="tool-guard-policy-info">
                                <span class="tool-guard-policy-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M12 3 4 6v6c0 4 5 7 8 9 3-2 8-5 8-9V6l-8-3Z"/><path d="m8 12 3 3 5-6"/></svg></span>
                                <div class="tool-guard-policy-copy">
                                    <h3 id="tool-guard-protection-status" data-i18n="toolGuard.policyTitle">拦截策略</h3>
                                    <p data-i18n="toolGuard.enableHint">保存后立即作用于后续工具调用，已开始的调用不受影响。</p>
                                </div>
                            </div>
                            <label class="tool-guard-toggle tool-guard-switch"><input id="tool-guard-enabled" type="checkbox" onchange="changeToolGuardEnabled(this.checked)" disabled><span data-i18n="toolGuard.enabled">启用调用拦截</span></label>
                        </section>
                        <section class="tool-guard-card tool-guard-rules-card" aria-labelledby="tool-guard-rules-title">
                            <div class="tool-guard-section-header">
                                <div>
                                    <div class="tool-guard-heading-line"><h3 id="tool-guard-rules-title" data-i18n="toolGuard.rulesTitle">拦截规则</h3><span id="tool-guard-rule-count" class="tool-guard-rule-count" aria-live="polite"></span></div>
                                    <p data-i18n="toolGuard.listHint">点击规则查看和编辑，按列表顺序匹配。</p>
                                </div>
                                <button type="button" id="tool-guard-add" class="btn-secondary tool-guard-add" data-require-permission="config:write" onclick="addToolGuardRule()" disabled><span aria-hidden="true">＋</span><span data-i18n="toolGuard.addRule">添加规则</span></button>
                            </div>
                            <div id="tool-guard-rules" class="tool-guard-rules"></div>
                            <details class="tool-guard-help">
                                <summary><span data-i18n="toolGuard.helpTitle">规则说明与匹配范围</span><span class="tool-guard-chevron" aria-hidden="true">›</span></summary>
                                <div class="tool-guard-help-body">
                                    <p data-i18n="toolGuard.rulesHint">按顺序匹配已启用的规则，使用首条命中规则的提醒。正则采用 RE2 语法，保存和试运行时由服务端校验。</p>
                                    <p data-i18n="toolGuard.messageHint">拦截提醒可使用 {match}（匹配文本）、{tool}（工具名称）、{rule}（规则名称）。</p>
                                    <p data-i18n="toolGuard.description">在 MCP 工具执行前检查工具名称和参数，命中规则立即阻止调用。人机协同审批和工具白名单不会跳过此检查。</p>
                                    <p data-i18n="toolGuard.scopeHint">正则仅检查调用中可见的文本；不会解析 IP 归属、重定向目标或工具读取的文件内容。域名规则不能保证覆盖所有间接访问。</p>
                                </div>
                            </details>
                        </section>
                        <details id="tool-guard-test-panel" class="tool-guard-card tool-guard-test-panel">
                            <summary>
                                <span class="tool-guard-test-icon" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7"><path d="M9 3h6M10 3v6l-6 9a2 2 0 0 0 2 3h12a2 2 0 0 0 2-3l-6-9V3M7 15h10"/></svg></span>
                                <span class="tool-guard-disclosure-copy"><strong id="tool-guard-test-title" data-i18n="toolGuard.testTitle">全部规则验证</strong><span id="tool-guard-test-scope-summary" data-i18n="toolGuard.testSummary">按规则顺序和启停状态，检查整体拦截效果</span></span>
                                <span class="tool-guard-chevron" aria-hidden="true">›</span>
                            </summary>
                            <div class="tool-guard-test-body">
                                <p class="tool-guard-test-hint" data-i18n="toolGuard.testHint">使用页面上的当前配置（包括未保存修改），仅检查匹配结果，不执行任何工具。</p>
                                <div class="tool-guard-field">
                                    <label for="tool-guard-test-tool" data-i18n="toolGuard.testTool">工具名称</label>
                                    <input id="tool-guard-test-tool" type="text" value="http_request" maxlength="512" oninput="invalidateToolGuardTest()" autocomplete="off" spellcheck="false">
                                </div>
                                <div class="tool-guard-field">
                                    <label for="tool-guard-test-arguments" data-i18n="toolGuard.testArguments">工具参数（JSON 对象）</label>
                                    <textarea id="tool-guard-test-arguments" rows="3" oninput="invalidateToolGuardTest()" spellcheck="false">{"url": "https://example.gov.cn"}</textarea>
                                </div>
                                <div class="tool-guard-test-actions"><button type="button" id="tool-guard-test" class="btn-secondary" data-require-permission="config:read" onclick="testToolGuardConfig()" data-i18n="toolGuard.test" disabled>测试匹配</button></div>
                                <div id="tool-guard-test-result" class="tool-guard-test-result" role="status" aria-live="polite" hidden></div>
                            </div>
                        </details>
                    </div>
                    <dialog id="tool-guard-add-dialog" class="tool-guard-add-dialog" aria-labelledby="tool-guard-add-title" aria-describedby="tool-guard-add-description">
                        <form novalidate onsubmit="event.preventDefault();commitToolGuardRule()">
                            <header class="tool-guard-add-header">
                                <div>
                                    <h3 id="tool-guard-add-title" data-i18n="toolGuard.addDialogTitle">添加拦截规则</h3>
                                    <p id="tool-guard-add-description" class="tool-guard-hint" data-i18n="toolGuard.addDialogHint">先配置规则，再用示例参数验证效果，确认后添加到列表。</p>
                                </div>
                                <button type="button" class="tool-guard-dialog-close" onclick="closeToolGuardRuleDialog()" data-i18n="toolGuard.closeDialog" data-i18n-attr="aria-label,title" data-i18n-skip-text="true" aria-label="关闭添加规则" title="关闭添加规则"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg></button>
                            </header>
                            <div id="tool-guard-add-body" class="tool-guard-add-body">
                                <div id="tool-guard-add-fields" class="tool-guard-add-fields"></div>
                                <aside id="tool-guard-add-test" class="tool-guard-add-test"></aside>
                                <div id="tool-guard-add-feedback" class="tool-guard-feedback" role="status" aria-live="polite" hidden></div>
                            </div>
                            <footer class="tool-guard-add-footer">
                                <p class="tool-guard-hint" data-i18n="toolGuard.addToListHint">添加到列表后，点击页面顶部「保存并生效」应用规则。</p>
                                <div class="tool-guard-dialog-actions">
                                    <button type="button" class="btn-secondary" onclick="closeToolGuardRuleDialog()" data-i18n="toolGuard.cancelAdd">取消</button>
                                    <button type="submit" id="tool-guard-add-confirm" class="btn-primary" data-require-permission="config:write" data-i18n="toolGuard.addToList">添加到列表</button>
                                </div>
                            </footer>
                        </form>
                    </dialog>
                </div>

                <div id="page-hitl" class="page">
                    <div class="page-header">
                        <h2 data-i18n="hitl.pageTitle">人机协同审批</h2>
                        <div class="page-header-actions">
                            <button type="button" class="btn-secondary" id="hitl-refresh-btn" onclick="refreshHitlActivePanel()" data-i18n="common.refresh">刷新</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="hitl-page-reviewer-bar" id="hitl-page-reviewer-bar">
                            <div class="hitl-page-reviewer-main">
                                <span class="hitl-page-reviewer-label" data-i18n="hitl.pageReviewerLabel">当前审批方</span>
                                <div class="hitl-reviewer-toggle hitl-reviewer-toggle--page" role="group" aria-label="Reviewer">
                                    <button type="button" class="hitl-reviewer-toggle-btn is-active" data-reviewer="human" aria-pressed="true">
                                        <span data-i18n="chat.hitlReviewerHuman">人工审批</span>
                                    </button>
                                    <button type="button" class="hitl-reviewer-toggle-btn" data-reviewer="audit_agent" aria-pressed="false">
                                        <span data-i18n="chat.hitlReviewerAgent">审计 Agent</span>
                                    </button>
                                </div>
                            </div>
                            <p class="hitl-page-reviewer-hint" data-i18n="hitl.pageReviewerHint">作用于当前选中会话；未选会话时保存到本机，新建会话时沿用。切换后立即生效。</p>
                        </div>
                        <div class="hitl-page-tabs" role="tablist">
                            <button type="button" class="hitl-page-tab hitl-page-tab--active" id="hitl-tab-pending" role="tab" aria-selected="true" onclick="switchHitlPageTab('pending')">
                                <span data-i18n="hitl.tabPending">待审计</span>
                                <span class="hitl-tab-badge" id="hitl-pending-count" hidden>0</span>
                            </button>
                            <button type="button" class="hitl-page-tab" id="hitl-tab-strategy" role="tab" aria-selected="false" onclick="switchHitlPageTab('strategy')">
                                <span data-i18n="hitl.tabStrategy">审计策略</span>
                            </button>
                            <button type="button" class="hitl-page-tab" id="hitl-tab-whitelist" role="tab" aria-selected="false" onclick="switchHitlPageTab('whitelist')">
                                <span data-i18n="hitl.tabWhitelist">工具白名单</span>
                            </button>
                            <button type="button" class="hitl-page-tab" id="hitl-tab-logs" role="tab" aria-selected="false" onclick="switchHitlPageTab('logs')">
                                <span data-i18n="hitl.tabLogs">审计日志</span>
                            </button>
                        </div>

                        <div id="hitl-panel-pending" class="hitl-page-panel">
                            <div class="hitl-filters">
                                <label>
                                    <span data-i18n="hitl.searchLabel">搜索</span>
                                    <input type="search" id="hitl-pending-search" class="hitl-filter-input" data-i18n="hitl.searchPlaceholder" data-i18n-attr="placeholder" placeholder="" onkeydown="if(event.key==='Enter')filterHitlPending()" />
                                </label>
                                <button type="button" class="btn-secondary" onclick="filterHitlPending()" data-i18n="hitl.searchApply">搜索</button>
                            </div>
                            <div id="hitl-pending-list" class="hitl-pending-list"></div>
                            <div id="hitl-pending-pagination" class="hitl-pending-pagination"></div>
                        </div>

                        <div id="hitl-panel-logs" class="hitl-page-panel" hidden>
                            <div class="hitl-filters hitl-filters--logs">
                                <label>
                                    <span data-i18n="hitl.searchLabel">搜索</span>
                                    <input type="search" id="hitl-logs-search" class="hitl-filter-input" data-i18n="hitl.searchPlaceholder" data-i18n-attr="placeholder" placeholder="" onkeydown="if(event.key==='Enter')filterHitlLogs()" />
                                </label>
                                <label>
                                    <span data-i18n="hitl.filterDecision">决策</span>
                                    <select id="hitl-logs-decision-filter" class="hitl-filter-select">
                                        <option value="all" data-i18n="hitl.filterAll">全部</option>
                                        <option value="approve" data-i18n="hitl.decisionApprove">通过</option>
                                        <option value="reject" data-i18n="hitl.decisionReject">拒绝</option>
                                    </select>
                                </label>
                                <label>
                                    <span data-i18n="hitl.filterDecidedBy">审批方</span>
                                    <select id="hitl-logs-decidedby-filter" class="hitl-filter-select">
                                        <option value="all" data-i18n="hitl.filterAll">全部</option>
                                        <option value="human" data-i18n="hitl.reviewerHuman">人工</option>
                                        <option value="audit_agent" data-i18n="hitl.reviewerAgent">审计 Agent</option>
                                        <option value="system" data-i18n="hitl.reviewerSystem">系统</option>
                                        <option value="manual" data-i18n="hitl.reviewerManual">手动录入</option>
                                    </select>
                                </label>
                                <button type="button" class="btn-secondary" onclick="filterHitlLogs()" data-i18n="hitl.searchApply">搜索</button>
                                <button type="button" class="btn-secondary btn-delete" data-require-permission="hitl:write" onclick="clearHitlLogs()" data-i18n="hitl.clearAll">清空</button>
                            </div>
                            <p id="hitl-logs-retention-hint" class="hitl-logs-retention-hint" hidden></p>
                            <div id="hitl-logs-batch-actions" class="monitor-batch-actions" style="display: none;">
                                <div class="batch-actions-info">
                                    <span id="hitl-logs-selected-count" data-i18n="hitl.selectedCount" data-i18n-params='{"count":0}'>已选择 0 项</span>
                                </div>
                                <div class="batch-actions-buttons">
                                    <button type="button" class="btn-secondary" onclick="selectAllHitlLogs()" data-i18n="hitl.selectAll">全选</button>
                                    <button type="button" class="btn-secondary" onclick="deselectAllHitlLogs()" data-i18n="hitl.deselectAll">取消全选</button>
                                    <button type="button" class="btn-secondary btn-delete" data-require-permission="hitl:write" onclick="batchDeleteHitlLogs()" data-i18n="hitl.batchDelete">批量删除</button>
                                </div>
                            </div>
                            <div id="hitl-logs-table-wrap" class="hitl-logs-table-wrap">
                                <div class="loading-spinner" data-i18n="hitl.loading">加载中...</div>
                            </div>
                            <div id="hitl-logs-pagination" class="hitl-logs-pagination"></div>
                        </div>

                        <div id="hitl-panel-strategy" class="hitl-page-panel" hidden>
                            <div class="hitl-page-strategy-bar" id="hitl-page-strategy-bar">
                                <div class="hitl-page-strategy-header">
                                    <span class="hitl-page-strategy-label" data-i18n="hitl.strategyLabel">审计策略</span>
                                    <div class="hitl-page-strategy-actions">
                                        <button type="button" class="btn-link" id="hitl-strategy-reset-btn" onclick="resetHitlAuditStrategy()" data-i18n="hitl.strategyReset">恢复默认</button>
                                        <button type="button" class="btn-secondary" data-require-permission="hitl:write" id="hitl-strategy-save-btn" onclick="saveHitlAuditStrategy()" data-i18n="common.save">保存</button>
                                    </div>
                                </div>
                                <div class="hitl-strategy-subtabs" role="tablist" aria-label="Audit strategy mode">
                                    <button type="button" class="hitl-strategy-subtab hitl-strategy-subtab--active" id="hitl-strategy-tab-approval" role="tab" aria-selected="true" data-strategy-mode="approval" onclick="switchHitlStrategyMode('approval')" data-i18n="hitl.strategyTabApproval">审批模式</button>
                                    <button type="button" class="hitl-strategy-subtab" id="hitl-strategy-tab-review-edit" role="tab" aria-selected="false" data-strategy-mode="review_edit" onclick="switchHitlStrategyMode('review_edit')" data-i18n="hitl.strategyTabReviewEdit">审查编辑模式</button>
                                </div>
                                <p class="hitl-page-strategy-hint" id="hitl-strategy-hint-approval" data-i18n="hitl.strategyHintApproval">白名单内工具免审批；审批模式下审计 Agent 仅裁决通过/拒绝。</p>
                                <p class="hitl-page-strategy-hint" id="hitl-strategy-hint-review-edit" hidden data-i18n="hitl.strategyHintReviewEdit">审查编辑模式下审计 Agent 可通过 editedArguments 收窄参数后放行；无法安全改参时应拒绝。</p>
                                <textarea id="hitl-audit-agent-prompt" class="hitl-strategy-textarea" rows="14" spellcheck="false" autocomplete="off"></textarea>
                                <textarea id="hitl-audit-agent-prompt-review-edit" class="hitl-strategy-textarea" rows="14" spellcheck="false" autocomplete="off" hidden></textarea>
                                <div id="hitl-strategy-feedback" class="hitl-apply-feedback" role="status" aria-live="polite" hidden></div>
                            </div>
                        </div>

                        <div id="hitl-panel-whitelist" class="hitl-page-panel" hidden>
                            <div class="hitl-page-whitelist-bar" id="hitl-page-whitelist-bar">
                                <div class="hitl-page-whitelist-header">
                                    <span class="hitl-page-whitelist-label" data-i18n="hitl.whitelistLabel">免审批工具白名单</span>
                                    <button type="button" class="btn-secondary" data-require-permission="hitl:write" id="hitl-page-whitelist-save-btn" onclick="saveHitlPageWhitelist()" data-i18n="common.save">保存</button>
                                </div>
                                <p class="hitl-page-whitelist-hint" data-i18n="hitl.whitelistHint">每行一个或逗号分隔；保存后写入 config.yaml 全局白名单并立即生效（与聊天侧栏同步展示）。</p>
                                <textarea id="hitl-page-sensitive-tools" class="hitl-page-whitelist-textarea" rows="6" spellcheck="false" autocomplete="off" data-i18n="chat.hitlWhitelistPlaceholder" data-i18n-attr="placeholder" placeholder=""></textarea>
                                <div id="hitl-page-whitelist-feedback" class="hitl-apply-feedback" role="status" aria-live="polite" hidden></div>
                            </div>
                        </div>
                    </div>
                </div>

                <div id="hitl-log-modal" class="modal" style="display:none" role="dialog" aria-modal="true" aria-labelledby="hitl-log-modal-title">
                    <div class="modal-content hitl-log-modal-content">
                        <div class="modal-header">
                            <h3 id="hitl-log-modal-title" data-i18n="hitl.logModalView">审计日志详情</h3>
                            <button type="button" class="modal-close" onclick="closeHitlLogModal()" aria-label="Close">&times;</button>
                        </div>
                        <div class="modal-body">
                            <div id="hitl-log-context-readonly" class="hitl-log-readonly-section" hidden></div>
                            <div id="hitl-log-execution-readonly" class="hitl-log-readonly-section" hidden></div>
                            <dl class="hitl-log-detail-meta">
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colId">ID</dt>
                                    <dd id="hitl-log-detail-id" class="hitl-log-detail-mono">—</dd>
                                </div>
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colTool">工具</dt>
                                    <dd id="hitl-log-detail-tool">—</dd>
                                </div>
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colConversation">会话</dt>
                                    <dd id="hitl-log-detail-conversation" class="hitl-log-detail-mono">—</dd>
                                </div>
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colDecision">决策</dt>
                                    <dd id="hitl-log-detail-decision">—</dd>
                                </div>
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colDecidedBy">审批方</dt>
                                    <dd id="hitl-log-detail-decided-by">—</dd>
                                </div>
                                <div class="hitl-log-detail-row">
                                    <dt data-i18n="hitl.colTime">时间</dt>
                                    <dd id="hitl-log-detail-time">—</dd>
                                </div>
                                <div class="hitl-log-detail-row hitl-log-detail-row--full" id="hitl-log-detail-comment-row" hidden>
                                    <dt data-i18n="hitl.fieldComment">备注</dt>
                                    <dd id="hitl-log-detail-comment">—</dd>
                                </div>
                            </dl>
                            <div class="hitl-log-detail-payload" id="hitl-log-detail-payload-wrap" hidden>
                                <div class="hitl-context-label" data-i18n="hitl.fieldPayload">载荷</div>
                                <pre id="hitl-log-detail-payload" class="hitl-context-text"></pre>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn-secondary" onclick="closeHitlLogModal()" data-i18n="common.close">关闭</button>
                        </div>
                    </div>
                </div>

                <!-- MCP状态监控页面 -->
                <div id="page-mcp-monitor" class="page mcp-monitor-page">
                    <div class="page-header">
                        <div class="page-header-main">
                            <h2 data-i18n="mcp.monitorTitle">MCP 状态监控</h2>
                            <p id="monitor-stats-subtitle" class="monitor-page-subtitle" hidden></p>
                        </div>
                        <div class="page-header-actions">
                            <button type="button" class="btn-secondary btn-icon-text" onclick="refreshMonitorPanel()" aria-label="刷新">
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg>
                                <span data-i18n="common.refresh">刷新</span>
                            </button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="monitor-sections">
                            <section class="monitor-section monitor-overview">
                                <div id="monitor-stats" class="mcp-exec-stats-root">
                                    <div class="monitor-empty" data-i18n="mcpMonitor.loading">加载中...</div>
                                </div>
                            </section>
                            <section class="monitor-section monitor-executions">
                                <div class="section-header">
                                    <h3 data-i18n="mcp.latestExecutions">最新执行记录</h3>
                                    <div class="section-actions">
                                        <label>
                                            <span data-i18n="mcp.toolSearch">工具搜索</span>
                                            <input type="text" id="monitor-tool-filter" data-i18n="mcp.toolSearchPlaceholder" data-i18n-attr="placeholder" placeholder="输入工具名称..." oninput="handleToolFilterInput()" onkeydown="if(event.key==='Enter') applyMonitorFilters()" />
                                        </label>
                                        <label>
                                            <span data-i18n="mcp.statusFilter">状态筛选</span>
                                            <select id="monitor-status-filter" class="monitor-filter-select-native">
                                                <option value="all" data-i18n="mcp.filterAll">全部</option>
                                                <option value="completed" data-i18n="mcpMonitor.statusCompleted">已完成</option>
                                                <option value="running" data-i18n="mcpMonitor.statusRunning">执行中</option>
                                                <option value="queued" data-i18n="mcpMonitor.statusQueued">排队中</option>
                                                <option value="failed" data-i18n="mcpMonitor.statusFailed">失败</option>
                                                <option value="blocked" data-i18n="mcpMonitor.statusBlocked">已拦截</option>
                                                <option value="hard_timeout" data-i18n="mcpMonitor.statusHardTimeout">执行超时</option>
                                                <option value="cancelled" data-i18n="mcpMonitor.statusCancelled">已终止</option>
                                                <option value="orphaned" data-i18n="mcpMonitor.statusOrphaned">孤儿任务</option>
                                            </select>
                                        </label>
                                    </div>
                                </div>
                                <div id="monitor-batch-actions" class="monitor-batch-actions" style="display: none;">
                                    <div class="batch-actions-info">
                                        <span id="monitor-selected-count">已选择 0 项</span>
                                    </div>
                                    <div class="batch-actions-buttons">
                                        <button class="btn-secondary" onclick="selectAllExecutions()" data-i18n="mcp.selectAll">全选</button>
                                        <button class="btn-secondary" onclick="deselectAllExecutions()" data-i18n="mcpMonitor.deselectAll">取消全选</button>
                                        <button class="btn-secondary btn-delete" data-require-permission="monitor:delete" onclick="batchDeleteExecutions()" data-i18n="mcp.deleteSelected">批量删除</button>
                                    </div>
                                </div>
                                <div id="monitor-executions" class="monitor-table-container">
                                    <div class="monitor-empty" data-i18n="mcpMonitor.loading">加载中...</div>
                                </div>
                            </section>
                        </div>
                    </div>
                </div>

                <!-- MCP管理页面 -->
                <div id="page-mcp-management" class="page">
                    <div class="page-header">
                        <h2 data-i18n="mcp.managementTitle">MCP 管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="loadExternalMCPs()"><span data-i18n="common.refresh">刷新</span></button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="mcp-management-layout">
                        <!-- MCP工具配置 -->
                        <div class="settings-section mcp-management-panel mcp-tools-panel" style="margin-bottom: 32px;">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
                                <h3 style="margin: 0;" data-i18n="mcp.toolConfig">MCP 工具配置</h3>
                                <button class="btn-primary" data-require-permission="config:write" onclick="saveToolsConfig()" data-i18n="mcp.saveToolConfig">保存工具配置</button>
                            </div>
                            <div class="tools-controls mcp-panel-body">
                                <div class="tools-actions">
                                    <button class="btn-secondary" onclick="selectAllTools()" data-i18n="mcp.selectAll">全选</button>
                                    <button class="btn-secondary" onclick="deselectAllTools()" data-i18n="mcp.deselectAll">全不选</button>
                                    <div class="tools-status-filter">
                                        <button class="btn-filter active" data-filter="" onclick="filterToolsByStatus('')" data-i18n="mcp.filterAll">全部</button>
                                        <button class="btn-filter" data-filter="true" onclick="filterToolsByStatus('true')" data-i18n="mcp.filterEnabled">已启用</button>
                                        <button class="btn-filter" data-filter="false" onclick="filterToolsByStatus('false')" data-i18n="mcp.filterDisabled">已停用</button>
                                    </div>
                                    <div class="search-box">
                                        <input type="text" id="tools-search" data-i18n="mcp.toolSearchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索工具..." onkeypress="handleSearchKeyPress(event)" oninput="if(this.value.trim() === '') clearSearch()" />
                                        <button class="btn-search" onclick="searchTools()" data-i18n="common.search" data-i18n-attr="title" title="搜索">🔍</button>
                                    </div>
                                    <div class="tools-stats" id="tools-stats"></div>
                                </div>
                                <div id="tools-list" class="tools-list"></div>
                            </div>
                        </div>

                        <!-- 外部MCP配置 -->
                        <div class="settings-section mcp-management-panel mcp-external-panel">
                            <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px;">
                                <h3 style="margin: 0;" data-i18n="mcp.externalConfig">外部 MCP 配置</h3>
                                <button class="btn-primary" data-require-permission="mcp:write" onclick="showAddExternalMCPModal()" data-i18n="mcp.addExternalMCP">添加外部MCP</button>
                            </div>
                            <div class="external-mcp-controls mcp-panel-body">
                                <div class="external-mcp-actions">
                                    <div class="external-mcp-stats" id="external-mcp-stats"></div>
                                </div>
                                <div id="external-mcp-list" class="external-mcp-list"></div>
                            </div>
                        </div>
                        </div>
                    </div>
                </div>

                <!-- 知识管理页面 -->
                <div id="page-knowledge-management" class="page">
                    <div class="page-header">
                        <h2 data-i18n="knowledge.title">知识管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="refreshKnowledgeBase()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-secondary" data-require-permission="knowledge:write" onclick="buildKnowledgeIndex()" data-i18n="knowledge.buildIndex">构建索引</button>
                            <button class="btn-secondary" data-require-permission="knowledge:write" onclick="rebuildKnowledgeIndexFull()" data-i18n="knowledge.rebuildIndexFull">全量重建</button>
                            <button class="btn-primary" data-require-permission="knowledge:write" onclick="showAddKnowledgeItemModal()" data-i18n="knowledge.addKnowledge">添加知识</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="knowledge-controls">
                            <div class="knowledge-stats-bar" id="knowledge-stats">
                                <div class="knowledge-stat-item">
                                    <span class="knowledge-stat-label" data-i18n="knowledge.totalItems">总知识项</span>
                                    <span class="knowledge-stat-value">-</span>
                                </div>
                                <div class="knowledge-stat-item">
                                    <span class="knowledge-stat-label" data-i18n="knowledge.categories">分类数</span>
                                    <span class="knowledge-stat-value">-</span>
                                </div>
                                <div class="knowledge-stat-item">
                                    <span class="knowledge-stat-label" data-i18n="knowledgePage.totalContent">总内容</span>
                                    <span class="knowledge-stat-value">-</span>
                                </div>
                            </div>
                            <div id="knowledge-index-progress" style="display: none; margin-bottom: 16px;"></div>
                            <div class="knowledge-filters">
                                <label>
                                    <span data-i18n="knowledgePage.categoryFilter">分类筛选</span>
                                    <div class="custom-select-wrapper">
                                        <div class="custom-select" id="knowledge-category-filter-wrapper">
                                            <div class="custom-select-trigger" id="knowledge-category-filter-trigger">
                                                <span data-i18n="knowledgePage.all">全部</span>
                                                <svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                    <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                                </svg>
                                            </div>
                                            <div class="custom-select-dropdown" id="knowledge-category-filter-dropdown">
                                                <div class="custom-select-option" data-value="" onclick="selectKnowledgeCategory('')" data-i18n="knowledgePage.all">全部</div>
                                            </div>
                                        </div>
                                    </div>
                                </label>
                                <label class="knowledge-search-field">
                                    <span data-i18n="common.search">搜索</span>
                                    <div class="search-box">
                                        <input type="text" id="knowledge-search" data-i18n="knowledgePage.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索知识..." oninput="handleKnowledgeSearchInput()" onkeydown="if(event.key==='Enter') searchKnowledgeItems()" />
                                        <button class="btn-search" onclick="searchKnowledgeItems()" data-i18n="common.search" data-i18n-attr="title" title="搜索">🔍</button>
                                    </div>
                                </label>
                            </div>
                        </div>
                        <div id="knowledge-items-list" class="knowledge-items-list">
                            <div class="loading-spinner" data-i18n="knowledgePage.loading">加载中...</div>
                        </div>
                        <div id="knowledge-pagination"></div>
                    </div>
                </div>

                <!-- 知识检索历史页面 -->
                <div id="page-knowledge-retrieval-logs" class="page">
                    <div class="page-header">
                        <h2 data-i18n="knowledge.retrievalLogs">检索历史</h2>
                        <button class="btn-secondary" onclick="refreshRetrievalLogs()" data-i18n="common.refresh">刷新</button>
                    </div>
                    <div class="page-content">
                        <div class="retrieval-logs-controls">
                            <div class="retrieval-stats-bar" id="retrieval-stats">
                                <div class="retrieval-stat-item">
                                    <span class="retrieval-stat-label" data-i18n="retrievalLogs.totalRetrievals">总检索次数</span>
                                    <span class="retrieval-stat-value">-</span>
                                </div>
                                <div class="retrieval-stat-item">
                                    <span class="retrieval-stat-label" data-i18n="retrievalLogs.successRetrievals">成功检索</span>
                                    <span class="retrieval-stat-value">-</span>
                                </div>
                                <div class="retrieval-stat-item">
                                    <span class="retrieval-stat-label" data-i18n="retrievalLogs.successRate">成功率</span>
                                    <span class="retrieval-stat-value">-</span>
                                </div>
                                <div class="retrieval-stat-item">
                                    <span class="retrieval-stat-label" data-i18n="retrievalLogs.retrievedItems">检索到知识项</span>
                                    <span class="retrieval-stat-value">-</span>
                                </div>
                            </div>
                            <div class="retrieval-logs-filters">
                                <label>
                                    <span data-i18n="retrievalLogs.conversationId">对话ID</span>
                                    <input type="text" id="retrieval-logs-conversation-id" data-i18n="retrievalLogs.optionalConversation" data-i18n-attr="placeholder" placeholder="可选：筛选特定对话" />
                                </label>
                                <label>
                                    <span data-i18n="retrievalLogs.messageId">消息ID</span>
                                    <input type="text" id="retrieval-logs-message-id" data-i18n="retrievalLogs.optionalMessage" data-i18n-attr="placeholder" placeholder="可选：筛选特定消息" />
                                </label>
                                <button class="btn-secondary" onclick="filterRetrievalLogs()" data-i18n="retrievalLogs.filter">筛选</button>
                            </div>
                        </div>
                        <div id="retrieval-logs-list" class="retrieval-logs-list">
                            <div class="loading-spinner" data-i18n="retrievalLogs.loading">加载中...</div>
                        </div>
                    </div>
                </div>

                <!-- 资产概览页面 -->
                <div id="page-asset-overview" class="page asset-page">
                    <div class="page-header">
                        <div><h2 data-i18n="assets.overviewTitle">资产概览</h2></div>
                        <div class="page-header-actions">
                            <button class="btn-secondary" type="button" onclick="loadAssetOverview()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-primary" type="button" onclick="switchPage('asset-library')" data-i18n="assets.viewLibrary">查看资产库</button>
                        </div>
                    </div>
                    <div class="page-content asset-content">
                        <div class="asset-overview-summary">
                            <section class="asset-total-card">
                                <div class="asset-total-card__layout">
                                    <div class="asset-inventory-summary">
                                        <div class="asset-total-card__heading">
                                            <div class="asset-overview-icon asset-overview-icon--blue" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="m12 2 8 4-8 4-8-4 8-4Z"/><path d="m4 10 8 4 8-4"/><path d="m4 14 8 4 8-4"/></svg></div>
                                            <div><span class="asset-eyebrow" data-i18n="assets.totalAssets">资产总数</span><p data-i18n="assets.totalAssetsHint">当前纳入持续监测的资产</p></div>
                                        </div>
                                        <strong id="asset-stat-total" class="asset-total-value">0</strong>
                                        <div class="asset-type-grid">
                                            <div class="asset-type-item asset-type-item--ip"><span class="asset-type-dot"></span><span data-i18n="assets.ipCount">IP 数量</span><strong id="asset-stat-ips">0</strong></div>
                                            <div class="asset-type-item asset-type-item--domain"><span class="asset-type-dot"></span><span data-i18n="assets.domainCount">域名数量</span><strong id="asset-stat-domains">0</strong></div>
                                            <div class="asset-type-item asset-type-item--port"><span class="asset-type-dot"></span><span data-i18n="assets.portCount">端口数量</span><strong id="asset-stat-ports">0</strong></div>
                                        </div>
                                    </div>
                                    <div class="asset-protocol-compact">
                                        <div class="asset-protocol-compact__header">
                                            <div><h3 data-i18n="assets.protocolDistribution">协议分布</h3><p data-i18n="assets.protocolDistributionHint">按已识别服务查看资产暴露构成</p></div>
                                            <span class="asset-panel-meta" id="asset-protocol-meta">—</span>
                                        </div>
                                        <div class="asset-protocol-columns"><span data-i18n="assets.protocolName">协议</span><span data-i18n="assets.assetRatio">资产占比</span><span data-i18n="assets.assetAmount">数量</span><span data-i18n="assets.ratio">占比</span></div>
                                        <div id="asset-protocol-chart" class="asset-bar-chart asset-bar-chart--compact" aria-live="polite"><div class="muted" data-i18n="common.noData">暂无数据</div></div>
                                    </div>
                                </div>
                            </section>
                            <section class="asset-recent-card">
                                <div class="asset-recent-card__top">
                                    <div class="asset-overview-icon asset-overview-icon--violet" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 10h18M12 14v4M10 16h4"/></svg></div>
                                    <span class="asset-recent-badge" data-i18n="assets.recentWindow">7 DAYS</span>
                                </div>
                                <div class="asset-recent-card__body"><span data-i18n="assets.recentCount">近 7 天发现</span><strong id="asset-stat-recent">0</strong></div>
                                <div class="asset-recent-progress"><i id="asset-recent-progress"></i></div>
                                <p id="asset-recent-rate" class="asset-recent-caption">—</p>
                            </section>
                        </div>
                        <div class="asset-insight-heading">
                            <div><h3 data-i18n="assets.postureChanges">态势变化</h3><p data-i18n="assets.postureChangesHint">观察资产与风险在选定周期内的变化</p></div>
                            <div class="asset-period-switch" role="group" data-i18n="assets.periodSelection" data-i18n-attr="aria-label" aria-label="周期选择">
                                <button type="button" data-days="7" aria-pressed="false" onclick="setAssetOverviewPeriod(7)" data-i18n="assets.days7">7 天</button>
                                <button type="button" class="active" data-days="30" aria-pressed="true" onclick="setAssetOverviewPeriod(30)" data-i18n="assets.days30">30 天</button>
                                <button type="button" data-days="90" aria-pressed="false" onclick="setAssetOverviewPeriod(90)" data-i18n="assets.days90">90 天</button>
                            </div>
                        </div>
                        <div class="asset-trend-grid">
                            <section class="asset-panel asset-trend-panel">
                                <div class="asset-panel-header asset-trend-header"><div class="asset-trend-heading"><h3 data-i18n="assets.assetTrend">资产增减趋势</h3><p data-i18n="assets.assetTrendHint">新增发现与当前已停用资产</p></div><div id="asset-growth-summary" class="asset-chart-summary"></div><div class="asset-chart-legend"><span class="asset-legend-added" data-i18n="assets.addedAssets">新增资产</span><span class="asset-legend-inactive" data-i18n="assets.inactiveAssets">停用资产</span></div></div>
                                <div id="asset-growth-chart" class="asset-line-chart"><div class="muted" data-i18n="common.loading">加载中...</div></div>
                            </section>
                            <section class="asset-panel asset-trend-panel">
                                <div class="asset-panel-header asset-trend-header"><div class="asset-trend-heading"><h3 data-i18n="assets.riskTrend">风险发现趋势</h3><p data-i18n="assets.riskTrendHint">新增漏洞及其中的高危与严重风险</p></div><div id="asset-risk-summary" class="asset-chart-summary"></div><div class="asset-chart-legend"><span class="asset-legend-risk" data-i18n="assets.discoveredRisks">新增漏洞</span><span class="asset-legend-high" data-i18n="assets.highRisks">高危及严重</span></div></div>
                                <div id="asset-risk-chart" class="asset-line-chart"><div class="muted" data-i18n="common.loading">加载中...</div></div>
                            </section>
                        </div>
                        <section class="asset-panel asset-coverage-panel">
                            <div class="asset-panel-header"><div><h3 data-i18n="assets.scanCoverage">扫描覆盖</h3><p data-i18n="assets.scanCoverageHint">识别未扫描与长期未复查的资产缺口</p></div><span id="asset-coverage-status" class="asset-panel-meta">—</span></div>
                            <div class="asset-coverage-layout">
                                <div class="asset-coverage-overview">
                                    <div class="asset-coverage-gauge" id="asset-coverage-gauge"><div><strong id="asset-coverage-rate">0%</strong><span data-i18n="assets.overallCoverage">总体覆盖率</span></div></div>
                                </div>
                                <div class="asset-coverage-metrics">
                                    <div class="asset-coverage-metric asset-coverage-metric--scanned"><span data-i18n="assets.scannedAssets">已扫描资产</span><strong id="asset-coverage-scanned">0</strong><small data-i18n="assets.scannedAssetsHint">至少完成过一次扫描</small></div>
                                    <div class="asset-coverage-metric asset-coverage-metric--recent"><span data-i18n="assets.recentlyScanned">近 30 天覆盖</span><strong id="asset-coverage-recent">0</strong><small id="asset-coverage-recent-rate">0%</small></div>
                                    <div class="asset-coverage-metric asset-coverage-metric--never"><span data-i18n="assets.neverScanned">从未扫描</span><strong id="asset-coverage-never">0</strong><small data-i18n="assets.neverScannedHint">建议优先纳入扫描</small></div>
                                    <div class="asset-coverage-metric asset-coverage-metric--stale"><span data-i18n="assets.staleScans">超过 30 天未扫描</span><strong id="asset-coverage-stale">0</strong><small data-i18n="assets.staleScansHint">扫描结果可能已过期</small></div>
                                </div>
                            </div>
                        </section>
                    </div>
                </div>

                <!-- 资产库页面 -->
                <div id="page-asset-library" class="page asset-page">
                    <div class="page-header">
                        <div><h2 data-i18n="assets.libraryTitle">资产库</h2></div>
                        <div class="page-header-actions">
                            <button class="btn-secondary" type="button" onclick="loadAssets()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-secondary" data-require-permission="asset:write" type="button" onclick="openAssetImport()" data-i18n="assets.bulkImport">批量导入</button>
                            <button class="btn-primary" data-require-permission="asset:write" type="button" onclick="openAssetEditor()" data-i18n="assets.addAsset">+ 新增资产</button>
                        </div>
                    </div>
                    <div class="page-content asset-content">
                        <div class="asset-toolbar">
                            <div class="asset-toolbar-main">
                                <input id="asset-search" type="search" data-i18n="assets.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索主机、IP、域名、标题、服务、责任人或标签" onkeydown="if(event.key==='Enter')loadAssets(1)">
                                <select id="asset-status-filter" onchange="loadAssets(1)"><option value="" data-i18n="assets.allStatuses">全部状态</option><option value="active" data-i18n="assets.statusActive">活跃</option><option value="inactive" data-i18n="assets.statusInactive">停用</option></select>
                                <select id="asset-project-filter" onchange="loadAssets(1)"><option value="" data-i18n="assets.allProjects">全部项目</option></select>
                                <button class="btn-secondary" type="button" onclick="toggleAssetAdvancedFilters()" aria-expanded="false" id="asset-advanced-toggle" data-i18n="assets.advancedFilters">高级筛选</button>
                                <button class="btn-primary" type="button" onclick="loadAssets(1)" data-i18n="common.search">搜索</button>
                                <button class="btn-link" type="button" onclick="resetAssetFilters()" data-i18n="assets.resetFilters">重置</button>
                                <span id="asset-list-meta" class="muted"></span>
                            </div>
                            <div id="asset-advanced-filters" class="asset-advanced-filters" hidden>
                                <label><span data-i18n="assets.riskLevel">风险等级</span><select id="asset-risk-filter"><option value="" data-i18n="assets.allRisks">全部风险</option><option value="critical" data-i18n="assets.riskCritical">严重</option><option value="high" data-i18n="assets.riskHigh">高危</option><option value="medium" data-i18n="assets.riskMedium">中危</option><option value="low" data-i18n="assets.riskLow">低危</option><option value="info" data-i18n="assets.riskInfo">信息</option><option value="normal" data-i18n="assets.riskNormal">正常</option><option value="unassessed" data-i18n="assets.riskUnassessed">未评估</option></select></label>
                                <label><span data-i18n="assets.minVulnerabilityCount">漏洞数量至少</span><input id="asset-vuln-min-filter" type="number" min="0" placeholder="0"></label>
                                <label><span data-i18n="assets.protocol">协议</span><input id="asset-protocol-filter" type="text" placeholder="https"></label>
                                <label><span>端口</span><input id="asset-port-filter" type="number" min="0" max="65535" placeholder="443"></label>
                                <label><span data-i18n="assets.source">来源</span><input id="asset-source-filter" type="text" placeholder="fofa / manual"></label>
                                <label><span data-i18n="assets.tagsLabel">标签</span><input id="asset-tag-filter" type="text" placeholder="公网"></label>
                                <label><span data-i18n="assets.scanState">扫描状态</span><select id="asset-scan-filter"><option value="" data-i18n="assets.allScanStates">全部</option><option value="never" data-i18n="assets.neverScannedFilter">从未扫描</option><option value="30" data-i18n="assets.overdue30">30 天未扫描</option><option value="60" data-i18n="assets.overdue60">60 天未扫描</option><option value="90" data-i18n="assets.overdue90">90 天未扫描</option><option value="scanned" data-i18n="assets.scannedFilter">已扫描</option></select></label>
                                <label><span data-i18n="assets.country">国家/地区</span><input id="asset-country-filter" type="text" placeholder="CN"></label>
                                <label><span data-i18n="assets.province">省份/州</span><input id="asset-province-filter" type="text"></label>
                                <label><span data-i18n="assets.city">城市</span><input id="asset-city-filter" type="text"></label>
                                <label><span data-i18n="assets.responsiblePerson">负责人</span><input id="asset-responsible-filter" type="text"></label>
                                <label><span data-i18n="assets.department">部门</span><input id="asset-department-filter" type="text"></label>
                                <label><span data-i18n="assets.businessSystem">业务系统</span><input id="asset-business-filter" type="text"></label>
                                <label><span data-i18n="assets.environment">环境</span><select id="asset-environment-filter"><option value="" data-i18n="assets.allEnvironments">全部环境</option><option value="production" data-i18n="assets.environmentProduction">生产</option><option value="staging" data-i18n="assets.environmentStaging">预发布</option><option value="testing" data-i18n="assets.environmentTesting">测试</option><option value="development" data-i18n="assets.environmentDevelopment">开发</option><option value="other" data-i18n="assets.environmentOther">其他</option></select></label>
                                <label><span data-i18n="assets.criticality">重要性</span><select id="asset-criticality-filter"><option value="" data-i18n="assets.allCriticalities">全部级别</option><option value="critical" data-i18n="assets.criticalityCritical">核心</option><option value="high" data-i18n="assets.criticalityHigh">重要</option><option value="medium" data-i18n="assets.criticalityMedium">一般</option><option value="low" data-i18n="assets.criticalityLow">低</option></select></label>
                                <label><span data-i18n="assets.firstSeenStart">首次发现开始</span><input id="asset-first-seen-after-filter" type="date"></label>
                                <label><span data-i18n="assets.firstSeenEnd">首次发现结束</span><input id="asset-first-seen-before-filter" type="date"></label>
                                <label><span data-i18n="assets.lastSeenStart">最近发现开始</span><input id="asset-last-seen-after-filter" type="date"></label>
                                <label><span data-i18n="assets.lastSeenEnd">最近发现结束</span><input id="asset-last-seen-before-filter" type="date"></label>
                                <label><span data-i18n="assets.sort">排序</span><select id="asset-sort-filter"><option value="last_seen_at:desc" data-i18n="assets.sortLastSeenDesc">最近发现（新到旧）</option><option value="last_scan_at:asc" data-i18n="assets.sortLastScanAsc">最久未扫描优先</option><option value="last_scan_at:desc" data-i18n="assets.sortLastScanDesc">最近扫描优先</option><option value="risk_level:desc" data-i18n="assets.sortRiskDesc">风险从高到低</option><option value="vulnerability_count:desc" data-i18n="assets.sortVulnerabilityDesc">漏洞数量从多到少</option><option value="first_seen_at:desc" data-i18n="assets.sortFirstSeenDesc">首次发现（新到旧）</option><option value="host:asc" data-i18n="assets.sortHostAsc">目标名称</option><option value="port:asc" data-i18n="assets.sortPortAsc">端口</option></select></label>
                            </div>
                            <div class="asset-saved-views">
                                <select id="asset-saved-view-select" onchange="applyAssetSavedView(this.value)"><option value="" data-i18n="assets.savedViews">保存的筛选视图</option></select>
                                <button class="btn-secondary" type="button" onclick="saveCurrentAssetView()" data-i18n="assets.saveCurrentView">保存当前视图</button>
                                <button class="btn-link" type="button" onclick="deleteCurrentAssetView()" data-i18n="assets.deleteView">删除视图</button>
                            </div>
                        </div>
                        <div id="asset-batch-actions" class="asset-batch-actions" hidden>
                            <div class="asset-batch-selection" aria-live="polite">
                                <span class="asset-batch-selection-mark" aria-hidden="true"></span>
                                <strong id="asset-selected-count"></strong>
                                <button class="asset-batch-text-action" type="button" onclick="clearAssetSelection()" data-i18n="assets.clearSelection">清除选择</button>
                                <button id="asset-select-all-results" class="asset-batch-text-action asset-batch-select-all" type="button" onclick="selectAllMatchingAssets()" hidden>选择全部结果</button>
                                <span id="asset-all-results-selected" class="asset-batch-all-selected" hidden></span>
                            </div>
                            <div class="asset-batch-primary-actions">
                                <button class="btn-secondary" data-require-permission="asset:write" type="button" onclick="openAssetProjectModal()" data-i18n="assets.bindProject">绑定项目</button>
                                <button class="btn-secondary" data-require-permission="asset:write" type="button" onclick="openAssetBulkEdit()" data-i18n="assets.bulkEdit">批量编辑</button>
                                <button class="btn-primary" type="button" onclick="openAssetScanModal('task')" data-i18n="assets.createScanTask">创建扫描任务</button>
                                <details id="asset-batch-more" class="asset-batch-more">
                                    <summary class="btn-secondary" data-i18n="assets.moreActions">更多</summary>
                                    <div class="asset-batch-menu" role="menu">
                                        <button type="button" role="menuitem" onclick="closeAssetBatchMenu();openAssetScanModal('chat')" data-i18n="assets.sendToChat">发送到对话</button>
                                        <div class="asset-batch-menu-separator" role="separator"></div>
                                        <div class="asset-batch-menu-label" data-i18n="assets.export">导出</div>
                                        <button type="button" role="menuitem" onclick="closeAssetBatchMenu();exportSelectedAssets('csv')" data-i18n="assets.exportCsv">导出 CSV</button>
                                        <button type="button" role="menuitem" onclick="closeAssetBatchMenu();exportSelectedAssets('xlsx')" data-i18n="assets.exportXlsx">导出 XLSX</button>
                                        <span class="asset-batch-permission-action" data-require-permission="asset:write"><button id="asset-merge-selected" type="button" role="menuitem" data-require-permission="asset:delete" onclick="closeAssetBatchMenu();mergeSelectedAssets()" data-i18n="assets.mergeDuplicates">合并重复资产</button></span>
                                        <div class="asset-batch-menu-separator" role="separator"></div>
                                        <button class="asset-batch-menu-danger" data-require-permission="asset:delete" type="button" role="menuitem" onclick="closeAssetBatchMenu();deleteSelectedAssets()" data-i18n="assets.batchDelete">批量删除…</button>
                                    </div>
                                </details>
                            </div>
                        </div>
                        <div class="asset-list-card">
                            <div class="asset-table-wrap">
                                <table class="asset-table">
                                    <thead><tr><th class="asset-check-cell"><input id="asset-select-page" class="theme-checkbox" type="checkbox" onchange="toggleAssetPageSelection(this.checked)" data-i18n="assets.selectPage" data-i18n-attr="aria-label" aria-label="选择本页"></th><th data-i18n="assets.target">目标</th><th data-i18n="assets.service">服务</th><th data-i18n="assets.project">所属项目</th><th data-i18n="assets.ownership">归属</th><th data-i18n="assets.lastScan">上次扫描</th><th data-i18n="assets.relatedVulnerabilities">相关漏洞</th><th data-i18n="assets.riskLevel">风险等级</th><th data-i18n="assets.status">状态</th><th data-i18n="infoCollect.actions">操作</th></tr></thead>
                                    <tbody id="asset-table-body"><tr><td colspan="10" class="muted" data-i18n="common.noData">暂无数据</td></tr></tbody>
                                </table>
                            </div>
                            <div id="asset-pagination" class="pagination-container pagination-fixed"></div>
                        </div>
                    </div>
                </div>

                <div id="asset-import-modal" class="modal asset-import-modal" style="display:none" role="dialog" aria-modal="true" aria-labelledby="asset-import-title" onclick="if(event.target===this)closeAssetImport()">
                    <div class="modal-content asset-import-content" onclick="event.stopPropagation()">
                        <div class="modal-header">
                            <div><h2 id="asset-import-title" data-i18n="assets.bulkImportTitle">批量导入资产</h2><p class="asset-page-subtitle" data-i18n="assets.bulkImportSubtitle">下载模板填写后上传，提交前会先校验并预览数据</p></div>
                            <button type="button" class="modal-close" onclick="closeAssetImport()" data-i18n="common.close" data-i18n-attr="aria-label" aria-label="关闭"></button>
                        </div>
                        <div class="modal-body asset-import-body">
                            <section class="asset-import-step">
                                <div class="asset-import-step-heading"><span>1</span><div><strong data-i18n="assets.downloadTemplate">下载模板</strong><small data-i18n="assets.downloadTemplateHint">推荐 XLSX；CSV 适合从其他系统快速导出</small></div></div>
                                <div class="asset-import-template-actions">
                                    <button class="btn-secondary" type="button" onclick="downloadAssetTemplate('xlsx')" data-i18n="assets.downloadXlsx">下载 XLSX 模板</button>
                                    <button class="btn-secondary" type="button" onclick="downloadAssetTemplate('csv')" data-i18n="assets.downloadCsv">下载 CSV 模板</button>
                                </div>
                            </section>
                            <section class="asset-import-step">
                                <div class="asset-import-step-heading"><span>2</span><div><strong data-i18n="assets.uploadFile">上传文件</strong><small data-i18n="assets.uploadFileHint">支持 .xlsx 和 .csv，最多 100000 行、100 MB</small></div></div>
                                <input id="asset-import-file" type="file" accept=".xlsx,.csv,text/csv,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" hidden onchange="handleAssetImportFile(this.files && this.files[0])">
                                <button id="asset-import-dropzone" class="asset-import-dropzone" type="button" onclick="document.getElementById('asset-import-file').click()">
                                    <span class="asset-import-dropzone-icon" aria-hidden="true">⇧</span>
                                    <strong id="asset-import-dropzone-title" data-i18n="assets.chooseOrDropFile">选择文件，或拖拽到此处</strong>
                                    <small id="asset-import-file-name" data-i18n="assets.fileNotSelected">尚未选择文件</small>
                                </button>
                            </section>
                            <section id="asset-import-preview-section" class="asset-import-step asset-import-preview-section" hidden>
                                <div class="asset-import-step-heading"><span>3</span><div><strong data-i18n="assets.dataPreview">数据预览</strong><small id="asset-import-summary"></small></div></div>
                                <div class="asset-import-preview-wrap">
                                    <table class="asset-import-preview-table">
                                        <thead><tr><th data-i18n="assets.rowNumber">行号</th><th data-i18n="assets.target">目标</th><th data-i18n="assets.project">所属项目</th><th data-i18n="assets.status">状态</th><th data-i18n="assets.validationResult">校验结果</th></tr></thead>
                                        <tbody id="asset-import-preview-body"></tbody>
                                    </table>
                                </div>
                                <p id="asset-import-preview-note" class="form-hint"></p>
                            </section>
                            <div id="asset-import-error" class="asset-form-error" role="alert" hidden></div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn-secondary" onclick="closeAssetImport()" data-i18n="common.cancel">取消</button>
                            <button id="asset-import-submit" type="button" class="btn-primary" data-require-permission="asset:write" onclick="submitAssetImport()" disabled data-i18n="assets.importValidRows">导入有效数据</button>
                        </div>
                    </div>
                </div>

                <div id="asset-project-modal" class="modal asset-project-modal" style="display:none" role="dialog" aria-modal="true" aria-labelledby="asset-project-title" onclick="if(event.target===this)closeAssetProjectModal()">
                    <form class="modal-content asset-project-content" onsubmit="event.preventDefault();submitAssetProjectBinding()" onclick="event.stopPropagation()">
                        <div class="modal-header"><div><h2 id="asset-project-title" data-i18n="assets.bindProjectTitle">绑定项目</h2><p id="asset-project-subtitle" class="asset-page-subtitle"></p></div><button type="button" class="modal-close" onclick="closeAssetProjectModal()" data-i18n="common.close" data-i18n-attr="aria-label" aria-label="关闭"></button></div>
                        <div class="modal-body">
                            <label class="asset-editor-field" for="asset-batch-project"><span data-i18n="assets.project">所属项目</span><select id="asset-batch-project"><option value="" disabled hidden data-i18n="assets.chooseProject">请选择项目</option></select></label>
                            <p class="form-hint" data-i18n="assets.bindProjectHint">所选资产将统一绑定到该项目。</p>
                        </div>
                        <div class="modal-footer"><button type="button" class="btn-secondary" onclick="closeAssetProjectModal()" data-i18n="common.cancel">取消</button><button id="asset-project-submit" type="submit" class="btn-primary" data-require-permission="asset:write" data-i18n="assets.confirmBinding">确认绑定</button></div>
                    </form>
                </div>

                <div id="asset-bulk-edit-modal" class="modal asset-project-modal" style="display:none" role="dialog" aria-modal="true" aria-labelledby="asset-bulk-edit-title" onclick="if(event.target===this)closeAssetBulkEdit()">
                    <form class="modal-content asset-bulk-edit-content" onsubmit="event.preventDefault();submitAssetBulkEdit()" onclick="event.stopPropagation()">
                        <div class="modal-header"><div><h2 id="asset-bulk-edit-title">批量编辑资产</h2><p id="asset-bulk-edit-subtitle" class="asset-page-subtitle"></p></div><button type="button" class="modal-close" onclick="closeAssetBulkEdit()" aria-label="关闭"></button></div>
                        <div class="modal-body asset-editor-grid">
                            <label class="asset-editor-field"><span>状态（留空不修改）</span><select id="asset-bulk-status"><option value="">不修改</option><option value="active">活跃</option><option value="inactive">停用</option></select></label>
                            <label class="asset-editor-field"><span>负责人</span><input id="asset-bulk-responsible" type="text" placeholder="留空不修改"></label>
                            <label class="asset-editor-field"><span>部门</span><input id="asset-bulk-department" type="text" placeholder="留空不修改"></label>
                            <label class="asset-editor-field"><span>业务系统</span><input id="asset-bulk-business" type="text" placeholder="留空不修改"></label>
                            <label class="asset-editor-field"><span>环境（留空不修改）</span><select id="asset-bulk-environment"><option value="">不修改</option><option value="production">生产</option><option value="staging">预发布</option><option value="testing">测试</option><option value="development">开发</option><option value="other">其他</option></select></label>
                            <label class="asset-editor-field"><span>重要性（留空不修改）</span><select id="asset-bulk-criticality"><option value="">不修改</option><option value="critical">核心</option><option value="high">重要</option><option value="medium">一般</option><option value="low">低</option></select></label>
                            <label class="asset-editor-field"><span>增加标签</span><input id="asset-bulk-add-tags" type="text" placeholder="逗号分隔"></label>
                            <label class="asset-editor-field"><span>移除标签</span><input id="asset-bulk-remove-tags" type="text" placeholder="逗号分隔"></label>
                        </div>
                        <div class="modal-footer"><button type="button" class="btn-secondary" onclick="closeAssetBulkEdit()">取消</button><button id="asset-bulk-edit-submit" type="submit" class="btn-primary" data-require-permission="asset:write">应用修改</button></div>
                    </form>
                </div>

                <div id="asset-scan-modal" class="modal asset-scan-modal" style="display:none" role="dialog" aria-modal="true" onclick="if(event.target===this)closeAssetScanModal()">
                    <div class="modal-content asset-scan-content" onclick="event.stopPropagation()">
                        <div class="modal-header"><div><h2 id="asset-scan-title" data-i18n="assets.scanTitle">扫描资产</h2><p id="asset-scan-subtitle" class="asset-page-subtitle"></p></div><span class="modal-close" onclick="closeAssetScanModal()">&times;</span></div>
                        <div class="modal-body">
                            <div id="asset-scan-targets" class="asset-scan-targets"></div>
                            <label class="asset-scan-prompt-label" for="asset-scan-prompt" data-i18n="assets.userPrompt">用户提示词</label>
                            <textarea id="asset-scan-prompt" class="asset-scan-prompt" rows="7"></textarea>
                            <p id="asset-scan-hint" class="form-hint" data-i18n="assets.promptHint">可使用 &#123;&#123;asset_id&#125;&#125;、&#123;&#123;target&#125;&#125;、&#123;&#123;host&#125;&#125;、&#123;&#123;ip&#125;&#125;、&#123;&#123;domain&#125;&#125;、&#123;&#123;port&#125;&#125; 占位符；创建任务时会为每个资产生成一条任务。</p>
                            <label id="asset-scan-execute-wrap" class="checkbox-label"><input id="asset-scan-execute-now" type="checkbox" checked><span data-i18n="assets.executeNow">创建后立即执行</span></label>
                        </div>
                        <div class="modal-footer"><button class="btn-secondary" onclick="closeAssetScanModal()" data-i18n="common.cancel">取消</button><button id="asset-scan-submit" class="btn-primary" onclick="submitAssetScan()" data-i18n="assets.confirmSend">确认发送</button></div>
                    </div>
                </div>

                <div id="asset-editor-modal" class="modal asset-editor-modal" style="display:none" role="dialog" aria-modal="true" aria-labelledby="asset-editor-title" onclick="if(event.target===this)closeAssetEditor()">
                    <form id="asset-editor-form" class="modal-content asset-editor-content" novalidate onsubmit="event.preventDefault();saveAsset()" onclick="event.stopPropagation()">
                        <div class="modal-header"><div><h2 id="asset-editor-title" data-i18n="assets.addAssetTitle">新增资产</h2><p class="asset-editor-subtitle" data-i18n="assets.editorSubtitle">输入一个目标即可，其余信息可自动解析或稍后补充</p></div><button type="button" class="modal-close" onclick="closeAssetEditor()" data-i18n="common.close" data-i18n-attr="aria-label" aria-label="关闭"></button></div>
                        <div class="modal-body asset-editor-body">
                            <input type="hidden" id="asset-edit-id">
                            <div class="asset-editor-primary">
                                <label class="asset-editor-field asset-editor-target-field" for="asset-edit-target">
                                    <span><span data-i18n="assets.assetAddress">资产地址</span><b aria-hidden="true">*</b></span>
                                    <input id="asset-edit-target" type="text" autocomplete="off" spellcheck="false" placeholder="https://example.com:443、example.com 或 1.1.1.1:443" aria-describedby="asset-edit-target-hint asset-edit-target-error" aria-required="true">
                                    <small id="asset-edit-target-hint" class="asset-field-hint" data-i18n="assets.assetAddressHint">仅需填写非空目标；可识别的 URL、域名、IP 和端口会自动解析</small>
                                    <small id="asset-edit-target-error" class="asset-field-error" role="alert" hidden></small>
                                </label>
                                <div class="asset-editor-grid asset-editor-primary-grid">
                                    <label class="asset-editor-field"><span data-i18n="assets.project">所属项目</span><select id="asset-edit-project"><option value="" data-i18n="assets.unboundProject">暂不绑定</option></select></label>
                                    <label class="asset-editor-field"><span data-i18n="assets.tagsLabel">标签</span><div id="asset-tag-editor" class="asset-tag-editor"><div id="asset-tag-chips" class="asset-tag-chips"></div><input id="asset-edit-tags" type="text" autocomplete="off" data-i18n="assets.tagsPlaceholder" data-i18n-attr="placeholder" placeholder="输入后按回车或逗号"></div><small class="asset-field-hint" data-i18n="assets.tagsHint">用于环境、业务或责任范围分类</small></label>
                                </div>
                            </div>
                            <section id="asset-editor-details" class="asset-editor-details" aria-labelledby="asset-editor-details-title">
                                <div class="asset-editor-section-group">
                                    <div class="asset-editor-group-heading"><h3 id="asset-editor-details-title" data-i18n="assets.connectionInfo">连接信息</h3><p data-i18n="assets.connectionInfoHint">由资产地址自动解析，可按需修正</p></div>
                                    <div class="asset-editor-grid">
                                        <label class="asset-editor-field asset-editor-wide"><span data-i18n="assets.hostUrl">完整 URL / Host</span><input id="asset-edit-host" type="text" spellcheck="false" placeholder="https://example.com:443"><small id="asset-edit-host-error" class="asset-field-error" role="alert" hidden></small></label>
                                        <label class="asset-editor-field"><span>IP</span><input id="asset-edit-ip" type="text" spellcheck="false" placeholder="1.1.1.1"><small id="asset-edit-ip-error" class="asset-field-error" role="alert" hidden></small></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.domain">域名</span><input id="asset-edit-domain" type="text" spellcheck="false" placeholder="example.com"><small id="asset-edit-domain-error" class="asset-field-error" role="alert" hidden></small></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.port">端口</span><input id="asset-edit-port" type="number" inputmode="numeric" min="1" max="65535" placeholder="443"><small id="asset-edit-port-error" class="asset-field-error" role="alert" hidden></small></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.protocol">协议</span><input id="asset-edit-protocol" type="text" list="asset-protocol-options" spellcheck="false" placeholder="https"><datalist id="asset-protocol-options"><option value="http"><option value="https"><option value="ssh"><option value="ftp"><option value="smtp"><option value="rdp"><option value="mysql"><option value="postgresql"><option value="redis"><option value="mongodb"></datalist><small id="asset-edit-protocol-error" class="asset-field-error" role="alert" hidden></small></label>
                                    </div>
                                </div>
                                <div class="asset-editor-section-group">
                                    <div class="asset-editor-group-heading"><h3 data-i18n="assets.fingerprintInfo">识别信息</h3><p data-i18n="assets.fingerprintInfoHint">补充页面与服务指纹，便于检索和识别</p></div>
                                    <div class="asset-editor-grid">
                                        <label class="asset-editor-field"><span data-i18n="assets.pageTitle">页面标题</span><input id="asset-edit-title-value" type="text" maxlength="500"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.serverProduct">服务 / 产品</span><input id="asset-edit-server" type="text" maxlength="255" placeholder="nginx"></label>
                                    </div>
                                </div>
                                <div class="asset-editor-section-group">
                                    <div class="asset-editor-group-heading"><h3 data-i18n="assets.locationAndStatus">地理与状态</h3><p data-i18n="assets.locationAndStatusHint">记录资产归属地区和当前启用状态</p></div>
                                    <div class="asset-editor-grid">
                                        <label class="asset-editor-field"><span data-i18n="assets.country">国家/地区</span><input id="asset-edit-country" type="text" maxlength="100" placeholder="CN"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.province">省份/州</span><input id="asset-edit-province" type="text" maxlength="100" placeholder="Beijing"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.city">城市</span><input id="asset-edit-city" type="text" maxlength="100" placeholder="Beijing"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.status">状态</span><select id="asset-edit-status"><option value="active" data-i18n="assets.statusActive">活跃</option><option value="inactive" data-i18n="assets.statusInactive">停用</option></select></label>
                                    </div>
                                </div>
                                <div class="asset-editor-section-group">
                                    <div class="asset-editor-group-heading"><h3 data-i18n="assets.responsibilityBusiness">责任与业务属性</h3><p data-i18n="assets.responsibilityBusinessHint">用于资产归属、运营分级与风险排序</p></div>
                                    <div class="asset-editor-grid">
                                        <label class="asset-editor-field"><span data-i18n="assets.responsiblePerson">负责人</span><input id="asset-edit-responsible" type="text" maxlength="255"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.department">部门</span><input id="asset-edit-department" type="text" maxlength="255"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.businessSystem">业务系统</span><input id="asset-edit-business" type="text" maxlength="255"></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.environment">环境</span><select id="asset-edit-environment"><option value="">未设置</option><option value="production" data-i18n="assets.environmentProduction">生产</option><option value="staging" data-i18n="assets.environmentStaging">预发布</option><option value="testing" data-i18n="assets.environmentTesting">测试</option><option value="development" data-i18n="assets.environmentDevelopment">开发</option><option value="other" data-i18n="assets.environmentOther">其他</option></select></label>
                                        <label class="asset-editor-field"><span data-i18n="assets.criticality">重要性</span><select id="asset-edit-criticality"><option value="">未设置</option><option value="critical" data-i18n="assets.criticalityCritical">核心</option><option value="high" data-i18n="assets.criticalityHigh">重要</option><option value="medium" data-i18n="assets.criticalityMedium">一般</option><option value="low" data-i18n="assets.criticalityLow">低</option></select></label>
                                    </div>
                                </div>
                            </section>
                            <div id="asset-editor-form-error" class="asset-form-error" role="alert" hidden></div>
                        </div>
                        <div class="modal-footer"><button type="button" class="btn-secondary" onclick="closeAssetEditor()" data-i18n="common.cancel">取消</button><button id="asset-editor-submit" type="submit" class="btn-primary" data-require-permission="asset:write" data-i18n="assets.addAssetAction">添加资产</button></div>
                    </form>
                </div>

                <div id="asset-detail-modal" class="modal asset-detail-modal" style="display:none" role="dialog" aria-modal="true" onclick="if(event.target===this)closeAssetDetail()">
                    <div class="modal-content asset-detail-content" onclick="event.stopPropagation()">
                        <div class="modal-header"><div><h2 data-i18n="assets.detailTitle">资产详情</h2><p id="asset-detail-subtitle" class="asset-page-subtitle"></p></div><span class="modal-close" onclick="closeAssetDetail()">&times;</span></div>
                        <div class="modal-body">
                            <div id="asset-detail-grid" class="asset-detail-grid"></div>
                        </div>
                        <div class="modal-footer"><button class="btn-secondary" onclick="closeAssetDetail()" data-i18n="common.close">关闭</button><button id="asset-detail-edit" class="btn-primary" data-require-permission="asset:write" onclick="editAssetFromDetail()" data-i18n="common.edit">编辑</button></div>
                    </div>
                </div>

                <!-- 信息收集页面 -->
                <div id="page-info-collect" class="page">
                    <div class="page-header">
                        <h2 data-i18n="infoCollectPage.title">信息收集</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="resetFofaForm()" data-i18n="infoCollectPage.reset">重置</button>
                            <button class="btn-primary" data-require-permission="fofa:execute" onclick="submitFofaSearch()" data-i18n="infoCollectPage.confirm">确定</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="info-collect-panel">
                            <div class="info-collect-form">
                                <div class="info-collect-form-top">
                                    <div class="info-collect-provider-card form-group">
                                        <div class="info-collect-step-title">
                                            <span>01</span>
                                            <label for="fofa-provider">数据源</label>
                                        </div>
                                        <select id="fofa-provider" onchange="handleInfoCollectProviderChange()">
                                            <option value="fofa">FOFA</option>
                                            <option value="zoomeye">ZoomEye</option>
                                            <option value="quake">Quake</option>
                                            <option value="shodan">Shodan</option>
                                        </select>
                                        <small class="form-hint">支持 FOFA、ZoomEye、Quake、Shodan；API Key 可在系统设置或环境变量中配置。</small>
                                    </div>
                                    <div class="info-collect-query-card form-group">
                                        <div class="info-collect-step-title">
                                            <span>02</span>
                                            <div>查询方式</div>
                                        </div>
                                        <div id="info-collect-natural-panel" class="info-collect-query-mode-panel info-collect-natural-panel">
                                            <label for="fofa-nl" id="info-collect-nl-label" class="info-collect-inner-label">自然语言（可选，AI 解析为查询语法）</label>
                                            <div class="info-collect-nl-row">
                                                <textarea id="fofa-nl" class="info-collect-query-input" rows="1" placeholder="例如：找中国的 Apache 站点"></textarea>
                                                <button id="fofa-nl-parse-btn" class="btn-secondary" type="button" onclick="parseFofaNaturalLanguage()" data-i18n="infoCollectPage.parseBtn" data-i18n-attr="title" data-i18n-title="infoCollectPage.parseBtnTitle" title="将自然语言解析为 FOFA 查询语法">AI 解析</button>
                                            </div>
                                            <div id="fofa-nl-status" class="fofa-nl-status muted" style="display: none;" aria-live="polite"></div>
                                            <small class="form-hint" id="info-collect-parse-hint">解析后会弹窗展示对应数据源语法（可编辑），确认无误后再填入查询框并执行查询。</small>
                                        </div>
                                        <div id="info-collect-syntax-panel" class="info-collect-query-mode-panel is-active">
                                            <label for="fofa-query" id="info-collect-query-label" class="info-collect-inner-label">查询语法（可编辑，可直接查询）</label>
                                            <div class="info-collect-query-row">
                                                <textarea id="fofa-query" class="info-collect-query-input" rows="1" placeholder='例如：app="Apache" && country="CN"'></textarea>
                                                <button id="fofa-query-submit-btn" class="btn-primary" data-require-permission="fofa:execute" type="button" onclick="submitFofaSearch()">查询</button>
                                            </div>
                                            <small class="form-hint" id="info-collect-query-hint">选择数据源后会显示对应查询语法提示。</small>
                                            <div class="info-collect-presets" id="info-collect-query-presets" aria-label="查询示例"></div>
                                            <div class="info-collect-syntax-guide" id="info-collect-syntax-guide" hidden></div>
                                        </div>
                                    </div>
                                </div>
                                <div class="info-collect-options-card">
                                    <div class="info-collect-step-title">
                                        <span>03</span>
                                        <div>返回配置</div>
                                    </div>
                                    <div class="info-collect-form-row">
                                        <div class="form-group">
                                            <label for="fofa-size" data-i18n="infoCollectPage.returnCount">返回数量</label>
                                            <input type="number" id="fofa-size" min="1" max="10000" value="100" />
                                        </div>
                                        <div class="form-group">
                                            <label for="fofa-page" data-i18n="infoCollectPage.pageNum">页码</label>
                                            <input type="number" id="fofa-page" min="1" value="1" />
                                        </div>
                                        <div class="form-group" id="info-collect-full-option">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="fofa-full" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="infoCollectPage.fullLabel">full</span>
                                            </label>
                                        </div>
                                        <small class="form-hint info-collect-row-hint" id="info-collect-size-hint">不同数据源的单次返回上限可能不同。</small>
                                    </div>
                                </div>
                                <div class="info-collect-fields-card form-group">
                                    <div class="info-collect-step-title">
                                        <span>04</span>
                                        <label for="fofa-fields" data-i18n="infoCollectPage.returnFields">返回字段名（逗号分隔）</label>
                                    </div>
                                    <input type="text" id="fofa-fields" value="host,ip,port,domain,title,protocol,country,province,city,server" />
                                    <div class="info-collect-presets" id="info-collect-fields-presets" aria-label="字段模板"></div>
                                </div>
                            </div>
                        </div>

                        <div class="info-collect-results">
                            <div class="info-collect-results-header">
                                <div class="info-collect-results-header-left">
                                    <div class="info-collect-results-title" data-i18n="infoCollectPage.queryResults">查询结果</div>
                                    <div class="info-collect-results-meta" id="fofa-results-meta">-</div>
                                </div>
                                <div class="info-collect-results-toolbar" aria-label="结果工具条" data-i18n="infoCollectPage.resultsToolbarAria" data-i18n-attr="aria-label" data-i18n-skip-text="true">
                                    <div class="info-collect-selected" id="fofa-selected-meta" data-i18n="infoCollectPage.selectedRowsZero">已选择 0 条</div>
                                    <button class="btn-secondary btn-small" type="button" onclick="toggleFofaColumnsPanel()" data-i18n="infoCollectPage.showHideColumns" data-i18n-attr="title" title="显示/隐藏字段"><span data-i18n="infoCollectPage.columns">列</span></button>
                                    <button class="btn-secondary btn-small" type="button" data-require-permission="fofa:execute" onclick="exportFofaResults('csv')" data-i18n="infoCollectPage.exportCsvTitle" data-i18n-attr="title" title="导出当前结果为 CSV（UTF-8，兼容中文）"><span data-i18n="infoCollectPage.exportCsv">导出 CSV</span></button>
                                    <button class="btn-secondary btn-small" type="button" data-require-permission="fofa:execute" onclick="exportFofaResults('json')" data-i18n="infoCollectPage.exportJsonTitle" data-i18n-attr="title" title="导出当前结果为 JSON"><span data-i18n="infoCollectPage.exportJson">导出 JSON</span></button>
                                    <button class="btn-secondary btn-small" type="button" data-require-permission="fofa:execute" onclick="exportFofaResults('xlsx')" data-i18n="infoCollectPage.exportXlsxTitle" data-i18n-attr="title" title="导出当前结果为 Excel"><span data-i18n="infoCollectPage.exportXlsx">导出 XLSX</span></button>
                                    <button class="btn-secondary btn-small" data-require-permission="asset:write" type="button" onclick="importSelectedFofaAssets()" data-i18n="assets.importSelected">入库所选</button>
                                    <button class="btn-primary btn-small" data-require-permission="fofa:execute" type="button" onclick="batchScanSelectedFofaRows()" data-i18n="infoCollectPage.batchScanTitle" data-i18n-attr="title" title="将所选行创建为批量任务队列"><span data-i18n="infoCollectPage.batchScan">批量扫描</span></button>
                                </div>
                            </div>
                            <div class="info-collect-results-table-wrap">
                                <!-- 字段显示/隐藏面板 -->
                                <div id="fofa-columns-panel" class="info-collect-columns-panel" style="display: none;">
                                    <div class="info-collect-columns-panel-header">
                                        <div class="info-collect-columns-title" data-i18n="infoCollectPage.showColumns">显示字段</div>
                                        <div class="info-collect-columns-actions">
                                            <button class="btn-secondary btn-small" type="button" onclick="showAllFofaColumns()" data-i18n="infoCollectPage.columnsPanelAll">全选</button>
                                            <button class="btn-secondary btn-small" type="button" onclick="hideAllFofaColumns()" data-i18n="infoCollectPage.columnsPanelNone">全不选</button>
                                            <button class="btn-secondary btn-small" type="button" onclick="closeFofaColumnsPanel()" data-i18n="infoCollectPage.columnsPanelClose">关闭</button>
                                        </div>
                                    </div>
                                    <div id="fofa-columns-list" class="info-collect-columns-list"></div>
                                </div>
                                <table class="info-collect-table">
                                    <thead id="fofa-results-thead"></thead>
                                    <tbody id="fofa-results-tbody">
                                        <tr><td class="muted" style="padding: 16px;" data-i18n="common.noData">暂无数据</td></tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 项目管理页面 -->
                <div id="page-projects" class="page projects-page">
                    <div class="page-header">
                        <h2 data-i18n="projects.title">项目管理</h2>
                        <div class="page-header-actions">
                            <label class="projects-show-archived-label"><input type="checkbox" id="projects-show-archived" onchange="loadProjectsList()"> <span data-i18n="projects.showArchived">显示已归档</span></label>
                            <button class="btn-secondary" type="button" onclick="loadProjectsList()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-primary" type="button" data-require-permission="project:write" onclick="showNewProjectModal()" data-i18n="projects.newProjectCta">+ 新建项目</button>
                        </div>
                    </div>
                    <div class="page-content projects-page-layout">
                        <aside class="projects-sidebar-card">
                            <div class="projects-sidebar-head">
                                <span class="projects-sidebar-title" data-i18n="projects.projectList">项目列表</span>
                                <span class="projects-sidebar-count" id="projects-list-count">0</span>
                            </div>
                            <div class="projects-sidebar-search">
                                <input type="search" id="projects-list-search" class="form-input" placeholder="搜索项目…" oninput="filterProjectsList()" autocomplete="off" data-i18n="projects.searchProjectsPlaceholder" data-i18n-attr="placeholder">
                            </div>
                            <div id="projects-list" class="projects-list"></div>
                            <div id="projects-pagination" class="sidebar-list-pagination projects-sidebar-pagination"></div>
                        </aside>
                        <main class="projects-detail" id="projects-detail-main">
                            <div class="projects-detail-placeholder" id="projects-detail-placeholder">
                                <div class="projects-placeholder-icon" aria-hidden="true">
                                    <svg width="56" height="56" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <rect x="3" y="4" width="18" height="16" rx="3" stroke="currentColor" stroke-width="1.5"/>
                                        <path d="M3 9h18M8 4V9M16 4V9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                                        <path d="M8 14h8M8 17h5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
                                    </svg>
                                </div>
                                <h3 data-i18n="projects.selectOrCreateTitle">选择或创建项目</h3>
                                <p data-i18n="projects.selectOrCreateHint">项目用于跨对话共享「事实黑板」：目标、环境、认证等信息会在绑定项目的对话中自动注入。</p>
                                <button class="btn-primary" type="button" data-require-permission="project:write" onclick="showNewProjectModal()" data-i18n="projects.createFirstProject">创建第一个项目</button>
                            </div>
                            <div class="projects-detail-inner" id="projects-detail-inner" hidden>
                                <header class="projects-detail-header">
                                    <div class="projects-detail-header-main">
                                        <div class="projects-detail-headline">
                                            <div class="projects-detail-title-group">
                                                <h3 id="projects-detail-title" class="projects-detail-title" data-i18n="projects.defaultProjectName">项目</h3>
                                                <span id="projects-detail-status" class="projects-status-pill projects-status-pill--active" data-i18n="projects.statusActive">进行中</span>
                                            </div>
                                            <div class="projects-detail-stats" id="projects-detail-stats">
                                                <span class="projects-stat-chip projects-stat-chip--facts" id="project-stat-facts">0 条事实</span>
                                                <span class="projects-stat-chip projects-stat-chip--vulns" id="project-stat-vulns">0 个漏洞</span>
                                                <span class="projects-stat-chip projects-stat-chip--conversations" id="project-stat-conversations">0 个对话</span>
                                                <span class="projects-stat-chip projects-stat-chip--warn" id="project-stat-sparse" hidden>0 待补全</span>
                                            </div>
                                        </div>
                                        <p id="projects-detail-desc" class="projects-detail-desc" hidden></p>
                                    </div>
                                    <div class="projects-detail-header-actions">
                                        <span id="projects-detail-meta" class="projects-detail-meta" aria-live="polite">
                                            <svg class="projects-detail-meta-icon" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
                                            <span id="projects-detail-meta-time" class="projects-detail-meta-time"></span>
                                        </span>
                                        <button type="button" class="btn-secondary btn-small" onclick="openVulnerabilitiesForProject()" data-i18n="projects.vulnerabilityManagement">漏洞管理</button>
                                        <button type="button" class="btn-primary btn-small" data-require-permission="project:write" onclick="showAddFactModal()" data-i18n="projects.addFactCta">+ 添加事实</button>
                                    </div>
                                </header>
                                <nav class="projects-tabs" role="tablist">
                                    <button type="button" id="project-tab-facts" class="projects-tab is-active" role="tab" onclick="switchProjectTab('facts')" data-i18n="projects.tabFacts">事实黑板</button>
                                    <button type="button" id="project-tab-graph" class="projects-tab" role="tab" onclick="switchProjectTab('graph')" data-i18n="projects.tabGraph">攻击路径</button>
                                    <button type="button" id="project-tab-assets" class="projects-tab" role="tab" data-require-permission="asset:read" onclick="switchProjectTab('assets')" data-i18n="projects.tabAssets">资产库</button>
                                    <button type="button" id="project-tab-conversations" class="projects-tab" role="tab" onclick="switchProjectTab('conversations')" data-i18n="projects.tabConversations">关联对话</button>
                                    <button type="button" id="project-tab-vulns" class="projects-tab" role="tab" onclick="switchProjectTab('vulns')" data-i18n="projects.tabVulns">关联漏洞</button>
                                    <button type="button" id="project-tab-settings" class="projects-tab" role="tab" onclick="switchProjectTab('settings')" data-i18n="projects.tabSettings">设置</button>
                                </nav>
                                <div id="project-panel-facts" class="projects-panel" role="tabpanel">
                                    <div class="projects-fact-toolbar">
                                        <div class="projects-fact-toolbar-filters" role="search">
                                            <label class="projects-fact-filter-field projects-fact-filter-field--search">
                                                <span class="projects-fact-filter-label" data-i18n="common.search">搜索</span>
                                                <svg class="projects-fact-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                                    <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
                                                    <path d="M20 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                </svg>
                                                <input type="search" id="project-facts-search" placeholder="搜索 key、摘要、body…" oninput="debouncedLoadProjectFacts()" autocomplete="off" data-i18n="projects.searchFactsPlaceholder" data-i18n-attr="placeholder">
                                            </label>
                                            <label class="projects-fact-filter-field">
                                                <span class="projects-fact-filter-label" data-i18n="projects.category">分类</span>
                                                <select id="project-facts-filter-category" class="projects-filter-select-native">
                                                    <option value="" data-i18n="projects.all">全部</option>
                                                    <option value="target">target</option>
                                                    <option value="auth">auth</option>
                                                    <option value="infra">infra</option>
                                                    <option value="business">business</option>
                                                    <option value="finding">finding</option>
                                                    <option value="chain">chain</option>
                                                    <option value="exploit">exploit</option>
                                                    <option value="poc">poc</option>
                                                    <option value="note">note</option>
                                                </select>
                                            </label>
                                            <label class="projects-fact-filter-field">
                                                <span class="projects-fact-filter-label" data-i18n="projects.confidence">置信度</span>
                                                <select id="project-facts-filter-confidence" class="projects-filter-select-native">
                                                    <option value="" data-i18n="projects.all">全部</option>
                                                    <option value="confirmed" data-i18n="projects.confidenceConfirmed">已确认</option>
                                                    <option value="tentative" data-i18n="projects.confidenceTentative">待确认</option>
                                                    <option value="deprecated" data-i18n="projects.confidenceDeprecated">已废弃</option>
                                                </select>
                                            </label>
                                            <div class="projects-fact-filter-toggles" role="group" aria-label="显示选项" data-i18n="projects.displayOptions" data-i18n-attr="aria-label">
                                                <label class="projects-fact-toggle">
                                                    <input type="checkbox" id="project-facts-filter-sparse" onchange="loadProjectFacts()">
                                                    <span data-i18n="projects.sparseOnly">仅待补全</span>
                                                </label>
                                                <label class="projects-fact-toggle">
                                                    <input type="checkbox" id="project-facts-filter-hide-deprecated" checked onchange="loadProjectFacts()">
                                                    <span data-i18n="projects.hideDeprecated">隐藏废弃</span>
                                                </label>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="projects-table-wrap">
                                        <table class="data-table data-table--projects">
                                            <thead><tr><th>Key</th><th data-i18n="projects.category">分类</th><th data-i18n="projects.summary">摘要</th><th data-i18n="projects.linksColumn">关系</th><th>Body</th><th data-i18n="projects.confidence">置信度</th><th data-i18n="projects.updated">更新</th><th class="col-actions" data-i18n="common.actions">操作</th></tr></thead>
                                            <tbody id="project-facts-tbody"></tbody>
                                        </table>
                                    </div>
                                </div>
                                <div id="project-panel-graph" class="projects-panel projects-panel--graph" role="tabpanel" hidden>
                                    <div class="projects-fact-toolbar projects-graph-toolbar">
                                        <div class="projects-fact-toolbar-filters projects-graph-toolbar-row">
                                            <label class="projects-fact-filter-field">
                                                <span class="projects-fact-filter-label" data-i18n="projects.graphView">视图</span>
                                                <select id="project-graph-view" class="projects-filter-select-native">
                                                    <option value="path" data-i18n="projects.graphViewPath">攻击路径</option>
                                                    <option value="full" data-i18n="projects.graphViewFull">完整关系</option>
                                                </select>
                                            </label>
                                            <label class="projects-fact-filter-field projects-fact-filter-field--search projects-graph-search-field">
                                                <span class="projects-fact-filter-label" data-i18n="common.search">搜索</span>
                                                <svg class="projects-fact-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                                    <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
                                                    <path d="M20 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                </svg>
                                                <input type="search" id="project-graph-search" placeholder="搜索节点…" oninput="filterProjectFactGraph()" autocomplete="off" data-i18n="projects.graphSearchPlaceholder" data-i18n-attr="placeholder">
                                            </label>
                                            <div class="projects-graph-actions" role="group" aria-label="Graph actions">
                                                <button type="button" class="projects-graph-action-btn" onclick="loadProjectFactGraph()" title="刷新" data-i18n="projects.graphRefresh" data-i18n-attr="title">
                                                    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M21 12a9 9 0 1 1-2.64-6.36" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M21 3v6h-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
                                                    <span data-i18n="projects.graphRefresh">刷新</span>
                                                </button>
                                                <button type="button" class="projects-graph-action-btn" onclick="centerProjectFactGraph()" title="居中" data-i18n="projects.graphCenter" data-i18n-attr="title">
                                                    <svg width="15" height="15" viewBox="0 0 24 24" fill="none" aria-hidden="true"><circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="2"/><path d="M12 2v4M12 18v4M2 12h4M18 12h4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                                                    <span data-i18n="projects.graphCenter">居中</span>
                                                </button>
                                                <button type="button" class="projects-graph-action-btn projects-graph-action-btn--connect" data-require-permission="project:write" id="project-graph-connect-btn" onclick="toggleProjectFactGraphConnectMode()" data-i18n="projects.graphConnect">连边</button>
                                            </div>
                                        </div>
                                    </div>
                                    <div class="project-fact-graph-layout">
                                        <div id="project-fact-graph-container" class="project-fact-graph-container"></div>
                                        <aside id="project-fact-graph-sidebar" class="project-fact-graph-sidebar" hidden>
                                            <div class="project-fact-graph-sidebar-header">
                                                <div class="project-fact-graph-sidebar-title-wrap">
                                                    <span id="project-fact-graph-node-category" class="project-fact-graph-node-category"></span>
                                                    <h4 id="project-fact-graph-node-title">—</h4>
                                                </div>
                                                <button type="button" class="project-fact-graph-sidebar-close" onclick="closeProjectFactGraphSidebar()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label">
                                                    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                                                </button>
                                            </div>
                                            <p id="project-fact-graph-node-meta" class="project-fact-graph-node-meta"></p>
                                            <div id="project-fact-graph-edges-wrap" class="project-fact-graph-edges-wrap" hidden>
                                                <h5 class="project-fact-graph-edges-title" data-i18n="projects.graphEdgesTitle">关系边</h5>
                                                <p class="project-fact-graph-edges-hint" data-i18n="projects.graphEdgesHint">箭头方向与数据库/编辑弹窗一致（source → target）；点击连线可定位。</p>
                                                <div id="project-fact-graph-edges-list" class="project-fact-graph-edges-list"></div>
                                            </div>
                                            <div class="project-fact-graph-sidebar-actions">
                                                <button type="button" class="btn-primary btn-small" id="project-fact-graph-detail-btn" onclick="openSelectedGraphFactDetail()" data-i18n="projects.details">详情</button>
                                                <button type="button" class="btn-secondary btn-small" data-require-permission="project:write" id="project-fact-graph-edit-btn" onclick="editSelectedGraphFact()" data-i18n="common.edit">编辑</button>
                                            </div>
                                        </aside>
                                    </div>
                                    <div class="project-fact-graph-footer">
                                        <div id="project-fact-graph-stats" class="project-fact-graph-stats"></div>
                                        <div class="projects-graph-legend" role="group" aria-label="Graph legend">
                                            <div class="projects-graph-legend-group">
                                                <span class="projects-graph-legend-heading" data-i18n="projects.graphLegendNodes">节点</span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node"><i style="--legend-color:#4F46E5;--legend-bg:#F5F3FF"></i><span data-i18n="projects.graphLegendNodeTarget">TARGET · 目标</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node"><i style="--legend-color:#64748B;--legend-bg:#F8FAFC"></i><span data-i18n="projects.graphLegendNodeInfra">INFRA · 基础设施</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node"><i style="--legend-color:#E11D48;--legend-bg:#FFF1F2"></i><span data-i18n="projects.graphLegendNodeFinding">FINDING · 发现</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node"><i style="--legend-color:#9333EA;--legend-bg:#F5F3FF"></i><span data-i18n="projects.graphLegendNodeVuln">VULN · 漏洞</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node"><i style="--legend-color:#B45309;--legend-bg:#FFFBEB"></i><span data-i18n="projects.graphLegendNodeExploit">EXPLOIT · 利用</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--node projects-graph-legend-item--node-dashed"><i style="--legend-color:#CBD5E1;--legend-bg:#F1F5F9"></i><span data-i18n="projects.graphLegendNodeMissing">MISSING · 缺失</span></span>
                                            </div>
                                            <span class="projects-graph-legend-divider" aria-hidden="true"></span>
                                            <div class="projects-graph-legend-group">
                                                <span class="projects-graph-legend-heading" data-i18n="projects.graphLegendEdges">连线</span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--edge"><i style="--legend-color:#4F46E5"></i><span data-i18n="projects.graphLegendDiscovered">discovered_on</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--edge"><i style="--legend-color:#64748B"></i><span data-i18n="projects.graphLegendLeads">leads_to</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--edge"><i style="--legend-color:#DC2626"></i><span data-i18n="projects.graphLegendExploits">exploits</span></span>
                                                <span class="projects-graph-legend-item projects-graph-legend-item--edge projects-graph-legend-item--dashed"><i style="--legend-color:#94A3B8"></i><span data-i18n="projects.graphLegendTentative">待确认（虚线）</span></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                                <div id="project-panel-assets" class="projects-panel" role="tabpanel" hidden>
                                    <div class="projects-table-wrap projects-table-wrap--with-pagination">
                                        <table class="data-table data-table--projects">
                                            <thead><tr><th data-i18n="assets.target">目标</th><th data-i18n="assets.service">服务</th><th data-i18n="assets.title">标题/指纹</th><th data-i18n="assets.source">来源</th><th data-i18n="assets.lastSeen">最近发现</th><th data-i18n="assets.status">状态</th><th class="col-actions" data-i18n="common.actions">操作</th></tr></thead>
                                            <tbody id="project-assets-tbody"></tbody>
                                        </table>
                                    </div>
                                    <div id="project-assets-pagination" class="pagination-container pagination-fixed projects-panel-pagination"></div>
                                </div>
                                <div id="project-panel-conversations" class="projects-panel" role="tabpanel" hidden>
                                    <div class="projects-table-wrap">
                                        <table class="data-table data-table--projects">
                                            <thead><tr><th data-i18n="projects.titleLabel">标题</th><th data-i18n="projects.updated">更新</th><th class="col-actions" data-i18n="common.actions">操作</th></tr></thead>
                                            <tbody id="project-conversations-tbody"></tbody>
                                        </table>
                                    </div>
                                </div>
                                <div id="project-panel-vulns" class="projects-panel" role="tabpanel" hidden>
                                    <div class="projects-fact-toolbar">
                                        <div class="projects-fact-toolbar-filters projects-vuln-toolbar-filters" role="search">
                                            <label class="projects-fact-filter-field projects-fact-filter-field--search">
                                                <span class="projects-fact-filter-label" data-i18n="common.search">搜索</span>
                                                <svg class="projects-fact-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                                    <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
                                                    <path d="M20 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                                </svg>
                                                <input type="search" id="project-vulns-search" placeholder="搜索标题、描述、类型、目标…" oninput="debouncedLoadProjectVulnerabilities()" autocomplete="off" data-i18n="projects.searchVulnsPlaceholder" data-i18n-attr="placeholder">
                                            </label>
                                            <label class="projects-fact-filter-field">
                                                <span class="projects-fact-filter-label" data-i18n="projects.severity">严重度</span>
                                                <select id="project-vulns-filter-severity" class="projects-filter-select-native">
                                                    <option value="" data-i18n="projects.all">全部</option>
                                                    <option value="critical">critical</option>
                                                    <option value="high">high</option>
                                                    <option value="medium">medium</option>
                                                    <option value="low">low</option>
                                                    <option value="info">info</option>
                                                </select>
                                            </label>
                                            <label class="projects-fact-filter-field">
                                                <span class="projects-fact-filter-label" data-i18n="projects.status">状态</span>
                                                <select id="project-vulns-filter-status" class="projects-filter-select-native">
                                                    <option value="" data-i18n="projects.all">全部</option>
                                                    <option value="open" data-i18n="vulnerabilityPage.statusOpen">待处理</option>
                                                    <option value="confirmed" data-i18n="vulnerabilityPage.statusConfirmed">已确认</option>
                                                    <option value="fixed" data-i18n="vulnerabilityPage.statusFixed">已修复</option>
                                                    <option value="ignored" data-i18n="vulnerabilityPage.statusIgnored">已忽略</option>
                                                    <option value="false_positive" data-i18n="vulnerabilityPage.statusFalsePositive">误报</option>
                                                </select>
                                            </label>
                                            <button type="button" class="btn-secondary btn-small projects-vuln-toolbar-action" onclick="openVulnerabilitiesForProject()" data-i18n="projects.viewInVulnerabilityManagement">在漏洞管理中查看</button>
                                        </div>
                                    </div>
                                    <div class="projects-table-wrap">
                                        <table class="data-table data-table--projects">
                                            <thead><tr><th data-i18n="projects.titleLabel">标题</th><th data-i18n="projects.severity">严重度</th><th data-i18n="projects.status">状态</th><th class="col-actions" data-i18n="common.actions">操作</th></tr></thead>
                                            <tbody id="project-vulns-tbody"></tbody>
                                        </table>
                                    </div>
                                </div>
                                <div id="project-panel-settings" class="projects-panel projects-panel--settings" role="tabpanel" hidden>
                                    <div class="projects-settings-layout">
                                        <header class="projects-settings-intro">
                                            <div class="projects-settings-intro-text">
                                                <h4 class="projects-settings-intro-title" data-i18n="projects.settingsIntroTitle">项目设置</h4>
                                                <p class="projects-settings-intro-hint" data-i18n="projects.settingsIntroHint">配置项目元数据与 Agent 授权边界，保存后即时生效于绑定对话。</p>
                                            </div>
                                        </header>
                                        <div class="projects-settings-grid">
                                            <section class="projects-settings-card projects-settings-card--basic">
                                                <div class="projects-settings-card-head">
                                                    <div class="projects-settings-card-head-left">
                                                        <span class="projects-settings-icon projects-settings-icon--blue" aria-hidden="true">
                                                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/></svg>
                                                        </span>
                                                        <div>
                                                            <h4 class="projects-settings-card-title" data-i18n="projects.basicInfoTitle">基本信息</h4>
                                                            <p class="projects-settings-card-hint" data-i18n="projects.basicInfoHint">名称与描述会显示在项目详情中</p>
                                                        </div>
                                                    </div>
                                                </div>
                                                <div class="projects-settings-card-body">
                                                    <div class="projects-form-row projects-form-row--2">
                                                        <div class="projects-form-field">
                                                            <label for="project-edit-name" data-i18n="projects.projectName">项目名称</label>
                                                            <input type="text" id="project-edit-name" class="form-input" placeholder="例如：某客户 Web 渗透" data-i18n="projects.projectNamePlaceholder" data-i18n-attr="placeholder">
                                                        </div>
                                                        <div class="projects-form-field">
                                                            <label for="project-edit-status" data-i18n="projects.status">状态</label>
                                                            <div class="projects-status-select-wrap">
                                                                <select id="project-edit-status" class="form-input projects-status-select projects-filter-select-native">
                                                                    <option value="active" data-i18n="projects.statusActive">进行中</option>
                                                                    <option value="archived" data-i18n="projects.statusArchived">已归档</option>
                                                                </select>
                                                            </div>
                                                        </div>
                                                    </div>
                                                    <div class="projects-form-field">
                                                        <label class="projects-filter-check projects-pin-toggle">
                                                            <input type="checkbox" id="project-edit-pinned"> <span data-i18n="projects.pinProject">置顶项目（列表优先显示）</span>
                                                        </label>
                                                    </div>
                                                    <div class="projects-form-field">
                                                        <label for="project-edit-description" data-i18n="projects.projectDescription">描述</label>
                                                        <textarea id="project-edit-description" class="form-input projects-description-textarea" rows="3" maxlength="4000" placeholder="客户/任务备注、协作说明、联系人…" data-i18n="projects.editDescriptionPlaceholder" data-i18n-attr="placeholder"></textarea>
                                                        <small class="form-hint" data-i18n="projects.descriptionLengthHint">仅供团队成员查阅，Agent 不会读取；简要说明即可（最多 4000 字）。需让 Agent 知晓的内容请写入事实黑板</small>
                                                    </div>
                                                </div>
                                            </section>
                                            <section class="projects-settings-card projects-settings-card--scope">
                                                <div class="projects-settings-card-head">
                                                    <div class="projects-settings-card-head-left">
                                                        <span class="projects-settings-icon projects-settings-icon--violet" aria-hidden="true">
                                                            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
                                                        </span>
                                                        <div>
                                                            <h4 class="projects-settings-card-title" data-i18n="projects.scopeTitle">测试范围</h4>
                                                            <p class="projects-settings-card-hint" data-i18n="projects.scopeHint">JSON 格式，供 Agent 理解授权边界与目标资产</p>
                                                        </div>
                                                    </div>
                                                    <div class="projects-scope-toolbar">
                                                        <button type="button" class="btn-ghost btn-small" onclick="formatProjectScopeJson()" title="格式化 JSON" data-i18n="projects.formatJson" data-i18n-attr="title">格式化</button>
                                                        <button type="button" class="btn-ghost btn-small" onclick="insertProjectScopeExample()" title="插入示例" data-i18n="projects.example" data-i18n-attr="title">示例</button>
                                                    </div>
                                                </div>
                                                <div class="projects-settings-card-body projects-settings-card-body--fill">
                                                    <div class="projects-scope-editor">
                                                        <label for="project-edit-scope" class="sr-only" data-i18n="projects.scopeJsonLabel">范围 JSON</label>
                                                        <textarea id="project-edit-scope" class="form-input form-input--mono projects-scope-textarea" spellcheck="false" placeholder='{"targets":["https://example.com"],"exclude":["*.cdn.example.com"]}'></textarea>
                                                    </div>
                                                    <p class="projects-scope-footnote" data-i18n="projects.scopeFootnote">支持 targets、exclude、notes 等字段，留空表示不限制范围。</p>
                                                </div>
                                            </section>
                                        </div>
                                        <section class="projects-settings-card projects-settings-card--danger">
                                            <div class="projects-settings-danger-main">
                                                <span class="projects-settings-icon projects-settings-icon--red" aria-hidden="true">
                                                    <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
                                                </span>
                                                <div>
                                                    <h4 class="projects-settings-card-title" data-i18n="projects.dangerZoneTitle">危险操作</h4>
                                                    <p class="projects-settings-card-hint" data-i18n="projects.dangerZoneHint">归档后需在列表勾选「显示已归档」才能查看；删除将清除全部事实且不可恢复。</p>
                                                </div>
                                            </div>
                                            <div class="projects-settings-danger-actions">
                                                <button class="btn-secondary btn-small" data-require-permission="project:write" type="button" onclick="archiveCurrentProject()" data-i18n="projects.archiveRestore">归档 / 恢复</button>
                                                <button class="btn-secondary btn-small btn-danger-outline" data-require-permission="project:delete" type="button" onclick="deleteCurrentProject()" data-i18n="projects.deleteProject">删除项目</button>
                                            </div>
                                        </section>
                                    </div>
                                    <footer class="projects-settings-footer">
                                        <span class="projects-settings-footer-hint" data-i18n="projects.saveChangesHint">修改后请点击保存以同步到服务器</span>
                                        <button class="btn-primary" data-require-permission="project:write" type="button" onclick="saveProjectSettings()">
                                            <span data-i18n="projects.saveSettings">保存更改</span>
                                        </button>
                                    </footer>
                                </div>
                            </div>
                        </main>
                    </div>
                </div>
                <!-- 漏洞管理页面 -->
                <div id="page-vulnerabilities" class="page">
                    <div class="page-header">
                        <h2 data-i18n="vulnerability.title">漏洞管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" data-require-permission="vulnerability:read" onclick="exportVulnerabilityReports()" data-i18n="vulnerabilityPage.batchExport">批量导出</button>
                            <button class="btn-secondary btn-delete" data-require-permission="vulnerability:delete" onclick="batchDeleteVulnerabilityReports()" data-i18n="vulnerabilityPage.batchDelete">批量删除</button>
                            <button class="btn-secondary" onclick="refreshVulnerabilities()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-primary" data-require-permission="vulnerability:write" onclick="showAddVulnerabilityModal()" data-i18n="vulnerability.addVuln">添加漏洞</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <!-- 统计看板：点击卡片筛选严重度，与下方下拉/地址栏 hash 同步 -->
                        <div class="vulnerability-dashboard" id="vulnerability-dashboard">
                            <div class="dashboard-stats" id="vulnerability-stat-cards" role="group" aria-label="漏洞严重度统计">
                                <div class="stat-card stat-card-total is-clickable is-active" data-severity="" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickAll" data-i18n-attr="title" title="查看全部（清除严重度筛选）">
                                    <div class="stat-label" data-i18n="vulnerabilityPage.statTotal">总漏洞数</div>
                                    <div class="stat-value" id="stat-total">-</div>
                                    <div class="stat-stacked-bar" id="stat-stacked-bar" aria-hidden="true">
                                        <span class="stat-stacked-seg critical" data-sev="critical"></span>
                                        <span class="stat-stacked-seg high" data-sev="high"></span>
                                        <span class="stat-stacked-seg medium" data-sev="medium"></span>
                                        <span class="stat-stacked-seg low" data-sev="low"></span>
                                        <span class="stat-stacked-seg info" data-sev="info"></span>
                                    </div>
                                </div>
                                <div class="stat-card stat-critical is-clickable" data-severity="critical" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickFilter" data-i18n-attr="title" title="点击按此严重度筛选；再次点击清除">
                                    <div class="stat-label" data-i18n="dashboard.severityCritical">严重</div>
                                    <div class="stat-value" id="stat-critical">-</div>
                                    <div class="stat-pct" id="stat-critical-pct" aria-hidden="true">—</div>
                                </div>
                                <div class="stat-card stat-high is-clickable" data-severity="high" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickFilter" data-i18n-attr="title" title="点击按此严重度筛选；再次点击清除">
                                    <div class="stat-label" data-i18n="dashboard.severityHigh">高危</div>
                                    <div class="stat-value" id="stat-high">-</div>
                                    <div class="stat-pct" id="stat-high-pct" aria-hidden="true">—</div>
                                </div>
                                <div class="stat-card stat-medium is-clickable" data-severity="medium" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickFilter" data-i18n-attr="title" title="点击按此严重度筛选；再次点击清除">
                                    <div class="stat-label" data-i18n="dashboard.severityMedium">中危</div>
                                    <div class="stat-value" id="stat-medium">-</div>
                                    <div class="stat-pct" id="stat-medium-pct" aria-hidden="true">—</div>
                                </div>
                                <div class="stat-card stat-low is-clickable" data-severity="low" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickFilter" data-i18n-attr="title" title="点击按此严重度筛选；再次点击清除">
                                    <div class="stat-label" data-i18n="dashboard.severityLow">低危</div>
                                    <div class="stat-value" id="stat-low">-</div>
                                    <div class="stat-pct" id="stat-low-pct" aria-hidden="true">—</div>
                                </div>
                                <div class="stat-card stat-info is-clickable" data-severity="info" role="button" tabindex="0"
                                     data-i18n="vulnerabilityPage.statClickFilter" data-i18n-attr="title" title="点击按此严重度筛选；再次点击清除">
                                    <div class="stat-label" data-i18n="dashboard.severityInfo">信息</div>
                                    <div class="stat-value" id="stat-info">-</div>
                                    <div class="stat-pct" id="stat-info-pct" aria-hidden="true">—</div>
                                </div>
                            </div>
                        </div>

                        <!-- 筛选 -->
                        <div class="vulnerability-controls" id="vulnerability-filter-panel">
                            <div class="vulnerability-filter-toolbar">
                                <div class="vulnerability-filter-primary">
                                    <label class="vulnerability-filter-field vulnerability-filter-field--grow vulnerability-search-wrap">
                                        <span class="sr-only" data-i18n="vulnerabilityPage.searchKeyword">关键词搜索</span>
                                        <svg class="vulnerability-search-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
                                            <circle cx="11" cy="11" r="7" stroke="currentColor" stroke-width="2"/>
                                            <path d="M20 20L16 16" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                        </svg>
                                        <input type="search" id="vulnerability-search-filter" autocomplete="off"
                                            data-i18n="vulnerabilityPage.searchKeyword" data-i18n-attr="placeholder" placeholder="搜索标题、描述、类型、目标…" />
                                    </label>
                                    <label class="vulnerability-filter-field vulnerability-filter-field--project">
                                        <span class="sr-only" data-i18n="vulnerabilityPage.detailProject">项目</span>
                                        <select id="vulnerability-project-filter" data-i18n="vulnerabilityPage.filterByProject" data-i18n-attr="title" title="按项目筛选" onchange="scheduleVulnerabilityFilterApply(true)">
                                            <option value="" data-i18n="vulnerabilityPage.allProjects">全部项目</option>
                                        </select>
                                    </label>
                                    <label class="vulnerability-filter-field vulnerability-filter-field--status">
                                        <span class="sr-only" data-i18n="vulnerabilityPage.status">状态</span>
                                        <select id="vulnerability-status-filter" data-i18n="vulnerabilityPage.status" data-i18n-attr="title" title="状态">
                                            <option value="" data-i18n="knowledgePage.all">全部状态</option>
                                            <option value="open" data-i18n="vulnerabilityPage.statusOpen">待处理</option>
                                            <option value="confirmed" data-i18n="vulnerabilityPage.statusConfirmed">已确认</option>
                                            <option value="fixed" data-i18n="vulnerabilityPage.statusFixed">已修复</option>
                                            <option value="ignored" data-i18n="vulnerabilityPage.statusIgnored">已忽略</option>
                                            <option value="false_positive" data-i18n="vulnerabilityPage.statusFalsePositive">误报</option>
                                        </select>
                                    </label>
                                    <div class="vulnerability-filter-actions">
                                        <div class="vulnerability-more-filters-anchor">
                                            <button type="button" class="btn-secondary vulnerability-more-filters-btn" id="vulnerability-more-filters-btn"
                                                aria-expanded="false" aria-haspopup="dialog" aria-controls="vulnerability-more-filters-popover">
                                                <span data-i18n="vulnerabilityPage.moreFilters">更多筛选</span>
                                                <span class="vulnerability-filter-advanced-badge" id="vulnerability-advanced-badge" hidden></span>
                                            </button>
                                            <div class="vulnerability-more-filters-popover" id="vulnerability-more-filters-popover" hidden role="dialog"
                                                aria-labelledby="vulnerability-more-filters-title">
                                                <p class="vulnerability-more-filters-popover-title" id="vulnerability-more-filters-title" data-i18n="vulnerabilityPage.moreFilters">更多筛选</p>
                                                <div class="vulnerability-more-filters-popover-body">
                                                    <label class="vulnerability-filter-field vulnerability-filter-field--full">
                                                        <span data-i18n="vulnerabilityPage.vulnId">漏洞 ID</span>
                                                        <input type="text" id="vulnerability-exact-id-filter"
                                                            data-i18n="vulnerabilityPage.filterExactId" data-i18n-attr="placeholder" placeholder="精确匹配漏洞 ID" />
                                                    </label>
                                                    <label class="vulnerability-filter-field">
                                                        <span data-i18n="vulnerabilityPage.conversationId">会话 ID</span>
                                                        <input type="text" id="vulnerability-conversation-filter" list="vulnerability-conversation-suggestions"
                                                            data-i18n="vulnerabilityPage.filterConversation" data-i18n-attr="placeholder" placeholder="筛选特定会话" />
                                                    </label>
                                                    <label class="vulnerability-filter-field">
                                                        <span data-i18n="vulnerabilityPage.taskOrQueueId">任务 / 队列 ID</span>
                                                        <input type="text" id="vulnerability-task-filter" list="vulnerability-task-suggestions"
                                                            data-i18n="vulnerabilityPage.filterTaskOrQueue" data-i18n-attr="placeholder" placeholder="筛选任务或队列 ID" />
                                                    </label>
                                                    <label class="vulnerability-filter-field">
                                                        <span data-i18n="vulnerabilityPage.conversationTag">对话标签</span>
                                                        <input type="text" id="vulnerability-conversation-tag-filter" list="vulnerability-conversation-tag-suggestions"
                                                            data-i18n="vulnerabilityPage.filterConversationTag" data-i18n-attr="placeholder" placeholder="筛选对话标签" />
                                                    </label>
                                                    <label class="vulnerability-filter-field">
                                                        <span data-i18n="vulnerabilityPage.taskTag">任务标签</span>
                                                        <input type="text" id="vulnerability-task-tag-filter" list="vulnerability-task-tag-suggestions"
                                                            data-i18n="vulnerabilityPage.filterTaskTag" data-i18n-attr="placeholder" placeholder="筛选任务标签" />
                                                    </label>
                                                </div>
                                                <div class="vulnerability-more-filters-popover-footer">
                                                    <button type="button" class="btn-secondary" id="vulnerability-more-filters-reset" data-i18n="vulnerabilityPage.clearAdvanced">清空</button>
                                                    <button type="button" class="btn-primary" id="vulnerability-more-filters-apply" data-i18n="vulnerabilityPage.applyFilters">应用</button>
                                                </div>
                                            </div>
                                        </div>
                                        <button type="button" class="vulnerability-filter-clear-btn" id="vulnerability-filter-clear-btn"
                                            onclick="clearVulnerabilityFilters()" hidden data-i18n="vulnerabilityPage.clearAll">重置全部</button>
                                    </div>
                                </div>
                                <select id="vulnerability-severity-filter" class="vulnerability-severity-sync" hidden aria-hidden="true" tabindex="-1">
                                    <option value=""></option>
                                    <option value="critical">critical</option>
                                    <option value="high">high</option>
                                    <option value="medium">medium</option>
                                    <option value="low">low</option>
                                    <option value="info">info</option>
                                </select>
                            </div>
                            <div class="vulnerability-filter-chips" id="vulnerability-filter-chips" hidden>
                                <span class="vulnerability-filter-chips-label" data-i18n="vulnerabilityPage.activeFilters">已选条件</span>
                                <div class="vulnerability-filter-chips-list" id="vulnerability-filter-chips-list" role="list"></div>
                            </div>
                            <datalist id="vulnerability-conversation-suggestions"></datalist>
                            <datalist id="vulnerability-task-suggestions"></datalist>
                            <datalist id="vulnerability-conversation-tag-suggestions"></datalist>
                            <datalist id="vulnerability-task-tag-suggestions"></datalist>
                        </div>

                        <!-- 漏洞列表 -->
                        <div id="vulnerabilities-list" class="vulnerabilities-list">
                            <div class="loading-spinner" data-i18n="vulnerabilityPage.loading">加载中...</div>
                        </div>
                        
                        <!-- 分页控件 -->
                        <div id="vulnerability-pagination" class="pagination-container pagination-fixed"></div>
                    </div>
                </div>

                <!-- WebShell 管理页面 -->
                <div id="page-webshell" class="page">
                    <div class="page-header">
                        <h2 data-i18n="webshell.title">WebShell 管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-primary" data-require-permission="webshell:write" onclick="showAddWebshellModal()" data-i18n="webshell.addConnection">添加连接</button>
                        </div>
                    </div>
                    <div class="page-content webshell-page-content">
                        <div class="webshell-layout">
                            <div id="webshell-sidebar" class="webshell-sidebar">
                                <div class="webshell-sidebar-header" data-i18n="webshell.connections">连接列表</div>
                                <div class="webshell-conn-search">
                                    <input type="text"
                                           id="webshell-conn-search"
                                           class="form-control webshell-conn-search-input"
                                           data-i18n="webshell.searchPlaceholder"
                                           data-i18n-attr="placeholder"
                                           placeholder="搜索连接..." />
                                </div>
                                <div class="webshell-sidebar-tools">
                                    <button type="button" class="btn-ghost btn-sm" id="webshell-batch-probe-btn" data-i18n="webshell.batchProbe">一键批量探活</button>
                                </div>
                                <div id="webshell-list" class="webshell-list">
                                    <div class="webshell-empty" data-i18n="webshell.noConnections">暂无连接，请点击「添加连接」</div>
                                </div>
                            </div>
                            <div id="webshell-resize-handle" class="webshell-resize-handle" title="拖拽调整宽度"></div>
                            <div class="webshell-main">
                                <div id="webshell-workspace" class="webshell-workspace">
                                    <div class="webshell-workspace-placeholder" data-i18n="webshell.selectOrAdd">请从左侧选择连接，或添加新的 WebShell 连接</div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 对话附件 / 文件管理 -->
                <div id="page-chat-files" class="page">
                    <div class="page-header">
                        <h2 data-i18n="chatFilesPage.title">文件管理</h2>
                        <div class="page-header-actions">
                            <button type="button" class="btn-secondary" id="chat-files-export-btn" data-require-permission="files:read" onclick="exportChatFiles()" data-i18n="chatFilesPage.export">导出当前结果</button>
                            <button type="button" class="btn-primary" id="chat-files-header-upload-btn" data-require-permission="files:write" onclick="chatFilesOpenUploadPicker()" data-i18n="chatFilesPage.upload">上传文件</button>
                            <input type="file" id="chat-files-upload-input" style="display:none" multiple onchange="onChatFilesUploadPick(event)" />
                            <button type="button" class="btn-secondary" id="chat-files-refresh-btn" onclick="loadChatFilesPage()" data-i18n="common.refresh">刷新</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <p class="chat-files-intro" data-i18n="chatFilesPage.intro">管理在对话中上传的文件。可将文件拖拽到下方列表区域，或点击「上传文件」选择文件（支持多选）。需要让 AI 引用某文件时，在列表中点击「复制路径」，到对话里粘贴即可。</p>
                        <div class="tasks-filters chat-files-filters">
                            <label>
                                <span data-i18n="chatFilesPage.conversationFilter">会话 ID</span>
                                <input type="text" id="chat-files-filter-conv" class="form-control" data-i18n="chatFilesPage.conversationPlaceholder" data-i18n-attr="placeholder" placeholder="留空表示全部" onkeydown="if(event.key==='Enter') chatFilesResetToFirstPageAndLoad()" />
                            </label>
                            <label>
                                <span data-i18n="chatFilesPage.projectFilter">项目 ID</span>
                                <input type="text" id="chat-files-filter-project" class="form-control" data-i18n="chatFilesPage.projectPlaceholder" data-i18n-attr="placeholder" placeholder="留空表示全部" onkeydown="if(event.key==='Enter') chatFilesResetToFirstPageAndLoad()" />
                            </label>
                            <label style="flex:1;min-width:180px;max-width:360px;">
                                <span data-i18n="chatFilesPage.searchName">文件名</span>
                                <input type="text" id="chat-files-filter-name" class="form-control" data-i18n="chatFilesPage.searchNamePlaceholder" data-i18n-attr="placeholder" placeholder="筛选文件名" oninput="chatFilesFilterNameOnInput()" onkeydown="if(event.key==='Enter') chatFilesResetToFirstPageAndLoad()" />
                            </label>
                            <label>
                                <span data-i18n="chatFilesPage.sourceFilter">来源</span>
                                <select id="chat-files-filter-source" class="form-control" onchange="chatFilesResetToFirstPageAndLoad()">
                                    <option value="all" data-i18n="chatFilesPage.sourceAll">全部</option>
                                    <option value="upload" data-i18n="chatFilesPage.sourceUpload">对话附件</option>
                                    <option value="reduction" data-i18n="chatFilesPage.sourceReduction">工具输出</option>
                                    <option value="workspace" data-i18n="chatFilesPage.sourceWorkspace">工作目录</option>
                                    <option value="conversation_artifact" data-i18n="chatFilesPage.sourceConversationArtifact">会话产物</option>
                                </select>
                            </label>
                            <label>
                                <span data-i18n="chatFilesPage.groupBy">分组</span>
                                <select id="chat-files-group-by" class="form-control chat-files-filter-select-native">
                                    <option value="none" data-i18n="chatFilesPage.groupNone">不分组</option>
                                    <option value="date" data-i18n="chatFilesPage.groupByDate">按日期</option>
                                    <option value="conversation" data-i18n="chatFilesPage.groupByConversation">按会话</option>
                                    <option value="project" data-i18n="chatFilesPage.groupByProject">按项目</option>
                                    <option value="folder" data-i18n="chatFilesPage.groupByFolder">按文件夹</option>
                                </select>
                            </label>
                            <button class="btn-secondary" type="button" onclick="chatFilesResetToFirstPageAndLoad()" data-i18n="common.search">搜索</button>
                        </div>
                        <div id="chat-files-upload-progress" class="chat-upload-progress-row chat-upload-progress-row--files" hidden role="status" aria-live="polite">
                            <div class="chat-upload-progress-track" aria-hidden="true"><div class="chat-upload-progress-fill" id="chat-files-upload-progress-fill"></div></div>
                            <span class="chat-upload-progress-label" id="chat-files-upload-progress-label"></span>
                        </div>
                        <div id="chat-files-list-wrap" class="chat-files-table-wrap">
                            <div class="loading-spinner" data-i18n="common.loading">加载中…</div>
                        </div>
                        <div id="chat-files-pagination" class="chat-files-pagination pagination" hidden></div>
                    </div>
                </div>

                <!-- 任务管理页面 -->
                <div id="page-tasks" class="page">
                    <div class="page-header">
                        <h2 data-i18n="tasks.title">任务管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-primary" data-require-permission="tasks:write" onclick="showBatchImportModal()" data-i18n="tasks.newTask">新建任务</button>
                            <label class="auto-refresh-toggle">
                                <input type="checkbox" id="tasks-auto-refresh" checked onchange="toggleTasksAutoRefresh(this.checked)">
                                <span data-i18n="tasks.autoRefresh">自动刷新</span>
                            </label>
                            <button class="btn-secondary" onclick="refreshBatchQueues()" data-i18n="common.refresh">刷新</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <!-- 批量任务队列列表 -->
                        <div class="batch-queues-section" id="batch-queues-section" style="display: none;">
                            <!-- 筛选控件 -->
                            <div class="batch-queues-filters tasks-filters batch-queues-filters--compact">
                                <label>
                                    <span data-i18n="tasksPage.statusFilter">状态筛选</span>
                                    <select id="batch-queues-status-filter" class="tasks-filter-select">
                                        <option value="all" data-i18n="knowledgePage.all">全部</option>
                                        <option value="pending" data-i18n="tasksPage.statusPending">待执行</option>
                                        <option value="running" data-i18n="dashboard.executing">执行中</option>
                                        <option value="paused" data-i18n="tasksPage.statusPaused">已暂停</option>
                                        <option value="completed" data-i18n="dashboard.completed">已完成</option>
                                        <option value="cancelled" data-i18n="tasksPage.statusCancelled">已取消</option>
                                    </select>
                                </label>
                                <label class="batch-queues-filters__search">
                                    <span data-i18n="tasksPage.searchQueuePlaceholder">搜索队列ID、标题或创建时间</span>
                                    <input type="text" id="batch-queues-search" data-i18n="tasksPage.searchKeywordPlaceholder" data-i18n-attr="placeholder" placeholder="输入关键字搜索..." 
                                           oninput="filterBatchQueues()">
                                </label>
                            </div>
                            <div class="batch-queues-board">
                                <div id="batch-queues-list" class="batch-queues-list"></div>
                                <div id="batch-queues-pagination" class="pagination-container"></div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- C2 监听器管理页面 -->
                <div id="page-c2-listeners" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.listeners.title">监听器管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-primary" data-require-permission="c2:write" onclick="C2.showCreateListenerModal()" data-i18n="c2.listeners.headerCreateBtn">+ 创建监听器</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div id="c2-listener-grid" class="c2-listener-grid"></div>
                    </div>
                </div>

                <!-- C2 会话管理页面 -->
                <div id="page-c2-sessions" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.sessions.title">会话管理</h2>
                        <div class="page-header-actions c2-sessions-page-actions">
                            <button type="button" class="btn-secondary" id="c2-sessions-batch-delete" data-require-permission="c2:delete" disabled onclick="C2.deleteSelectedSessions()"><span data-i18n="c2.sessions.batchDelete">批量删除</span></button>
                            <button type="button" class="btn-secondary" id="c2-sessions-delete-filtered" data-require-permission="c2:delete" disabled onclick="C2.deleteFilteredSessions()"><span data-i18n="c2.sessions.deleteFiltered">删除筛选结果</span></button>
                            <button class="btn-secondary" onclick="C2.loadSessions()"><span data-i18n="common.refresh">刷新</span></button>
                        </div>
                    </div>
                    <div class="page-content" style="padding:0;">
                        <div class="c2-session-layout">
                            <div class="c2-session-sidebar-wrap">
                                <div id="c2-session-toolbar" class="c2-sessions-toolbar"></div>
                                <div id="c2-session-list" class="c2-session-sidebar"></div>
                            </div>
                            <div id="c2-session-main" class="c2-session-main"></div>
                        </div>
                    </div>
                </div>

                <!-- C2 任务管理页面 -->
                <div id="page-c2-tasks" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.tasks.title">任务管理</h2>
                        <div class="page-header-actions">
                            <button type="button" class="btn-danger" id="c2-tasks-batch-delete" data-require-permission="c2:delete" disabled onclick="C2.deleteSelectedTasks()"><span data-i18n="c2.tasks.batchDelete">批量删除</span></button>
                            <button type="button" class="btn-secondary" onclick="C2.loadTasks()"><span data-i18n="common.refresh">刷新</span></button>
                        </div>
                    </div>
                    <div class="page-content c2-tasks-page-wrap">
                        <div class="c2-tasks-summary" id="c2-tasks-summary" hidden>
                            <span class="c2-tasks-stat">
                                <span class="c2-tasks-stat-label" data-i18n="c2.tasks.statTotal">当前筛选</span>
                                <strong id="c2-tasks-stat-total">0</strong>
                            </span>
                            <span class="c2-tasks-stat c2-tasks-stat--success">
                                <span class="c2-tasks-stat-label" data-i18n="c2.tasks.success">成功</span>
                                <strong id="c2-tasks-stat-success">0</strong>
                            </span>
                            <span class="c2-tasks-stat c2-tasks-stat--failed">
                                <span class="c2-tasks-stat-label" data-i18n="c2.tasks.failed">失败</span>
                                <strong id="c2-tasks-stat-failed">0</strong>
                            </span>
                            <span class="c2-tasks-stat c2-tasks-stat--pending">
                                <span class="c2-tasks-stat-label" data-i18n="c2.tasks.pending">待处理</span>
                                <strong id="c2-tasks-stat-pending">0</strong>
                            </span>
                        </div>
                        <div class="c2-tasks-filter-card">
                            <div class="c2-tasks-time-presets" id="c2-tasks-time-presets">
                                <span class="c2-tasks-time-presets-label" data-i18n="c2.tasks.timePresets">快捷</span>
                                <button type="button" class="c2-tasks-time-preset-btn" data-preset="15m" data-i18n="c2.tasks.preset15m">最近15分钟</button>
                                <button type="button" class="c2-tasks-time-preset-btn" data-preset="1h" data-i18n="c2.tasks.preset1h">最近1小时</button>
                                <button type="button" class="c2-tasks-time-preset-btn" data-preset="24h" data-i18n="c2.tasks.preset24h">最近24小时</button>
                                <button type="button" class="c2-tasks-time-preset-btn" data-preset="7d" data-i18n="c2.tasks.preset7d">最近7天</button>
                                <button type="button" class="c2-tasks-time-preset-btn" data-preset="all" data-i18n="c2.tasks.presetAll">全部</button>
                            </div>
                            <div class="c2-tasks-filter-fields">
                                <label class="c2-tasks-field">
                                    <span data-i18n="c2.tasks.colStatus">状态</span>
                                    <select id="c2-tasks-filter-status" class="form-control">
                                        <option value="" data-i18n="c2.tasks.filterAllStatuses">全部状态</option>
                                        <option value="queued" data-i18n="c2.tasks.queued">队列中</option>
                                        <option value="sent" data-i18n="c2.tasks.sent">已发送</option>
                                        <option value="running" data-i18n="c2.tasks.running">执行中</option>
                                        <option value="success" data-i18n="c2.tasks.success">成功</option>
                                        <option value="failed" data-i18n="c2.tasks.failed">失败</option>
                                        <option value="cancelled" data-i18n="c2.tasks.cancelled">已取消</option>
                                    </select>
                                </label>
                                <label class="c2-tasks-field">
                                    <span data-i18n="c2.tasks.colType">类型</span>
                                    <select id="c2-tasks-filter-type" class="form-control">
                                        <option value="" data-i18n="c2.tasks.filterAllTypes">全部类型</option>
                                        <option value="shell">shell</option>
                                        <option value="exec">exec</option>
                                        <option value="ls">ls</option>
                                        <option value="pwd">pwd</option>
                                        <option value="cd">cd</option>
                                        <option value="download">download</option>
                                        <option value="upload">upload</option>
                                        <option value="ps">ps</option>
                                        <option value="sleep">sleep</option>
                                        <option value="screenshot">screenshot</option>
                                    </select>
                                </label>
                                <label class="c2-tasks-field c2-tasks-field--session">
                                    <span data-i18n="c2.tasks.filterSession">会话 ID</span>
                                    <input type="text" id="c2-tasks-filter-session" class="form-control" data-i18n="c2.tasks.filterSessionPlaceholder" data-i18n-attr="placeholder" placeholder="s_xxxxxxxx" autocomplete="off" spellcheck="false" />
                                </label>
                                <div class="c2-tasks-filter-actions">
                                    <button type="button" class="btn-primary btn-small" onclick="C2.applyTasksFilters()" data-i18n="c2.tasks.applyFilters">应用筛选</button>
                                    <button type="button" class="btn-secondary btn-small" onclick="C2.resetTasksFilters()" data-i18n="c2.tasks.resetFilters">重置</button>
                                </div>
                            </div>
                        </div>
                        <div class="c2-tasks-panel">
                            <div id="c2-task-list" class="c2-tasks-list-container"></div>
                            <div id="c2-tasks-pagination" class="pagination-container c2-tasks-pagination"></div>
                        </div>
                    </div>
                </div>

                <!-- C2 Payload 生成页面 -->
                <div id="page-c2-payloads" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.payloads.title">Payload 生成</h2>
                    </div>
                    <div class="page-content">
                        <div class="c2-payload-grid">
                            <div class="c2-payload-card">
                                <h3>
                                    <span class="c2-payload-icon" style="background:rgba(59,130,246,0.08);color:#3b82f6;">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
                                    </span>
                                    <span data-i18n="c2.payloads.oneliner">单行 Payload</span>
                                </h3>
                                <p class="c2-payload-desc" data-i18n="c2.payloads.onelinerDesc">快速生成可在目标机直接执行的反弹命令，支持 Bash / Python / PowerShell / Curl</p>
                                <div class="c2-form-group">
                                    <label data-i18n="c2.payloads.listener">监听器</label>
                                    <select id="c2-payload-listener" class="form-control c2-form-select-native"></select>
                                </div>
                                <div class="c2-form-group">
                                    <label data-i18n="c2.payloads.kind">类型</label>
                                    <select id="c2-payload-kind" class="form-control c2-form-select-native"></select>
                                </div>
                                <div class="c2-form-group">
                                    <label data-i18n="c2.payloads.hostOptional">回连地址 (可选)</label>
                                    <input type="text" id="c2-payload-host" class="form-control" data-i18n="c2.payloads.placeholderListenerHost" data-i18n-attr="placeholder" placeholder="留空则使用监听器地址">
                                </div>
                                <button type="button" id="c2-generate-oneliner-btn" class="btn-primary" data-require-permission="c2:write" onclick="C2.generateOneliner()" style="width:100%;" data-i18n="c2.payloads.generateOnelinerBtn">生成 Oneliner</button>
                                <pre id="c2-oneliner-output" class="c2-oneliner-output" style="display:none;" onclick="C2.copyOneliner()" data-i18n="c2.payloads.clickToCopyTitle" data-i18n-attr="title" data-i18n-skip-text="true" title="点击复制"></pre>
                            </div>
                            <div class="c2-payload-card">
                                <h3>
                                    <span class="c2-payload-icon" style="background:rgba(16,185,129,0.08);color:#10b981;">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="4" y="4" width="16" height="16" rx="2" ry="2"></rect><rect x="9" y="9" width="6" height="6"></rect><line x1="9" y1="1" x2="9" y2="4"></line><line x1="15" y1="1" x2="15" y2="4"></line><line x1="9" y1="20" x2="9" y2="23"></line><line x1="15" y1="20" x2="15" y2="23"></line><line x1="20" y1="9" x2="23" y2="9"></line><line x1="20" y1="14" x2="23" y2="14"></line><line x1="1" y1="9" x2="4" y2="9"></line><line x1="1" y1="14" x2="4" y2="14"></line></svg>
                                    </span>
                                    <span data-i18n="c2.payloads.build">编译 Beacon 二进制</span>
                                </h3>
                                <p class="c2-payload-desc" data-i18n="c2.payloads.buildDesc">交叉编译支持多平台的完整 Beacon 可执行文件，支持 Linux / Windows / macOS</p>
                                <div class="c2-form-group">
                                    <label data-i18n="c2.payloads.listener">监听器</label>
                                    <select id="c2-build-listener" class="form-control c2-form-select-native"></select>
                                    <p id="c2-build-loopback-hint" class="form-hint" style="display:none;margin-top:8px;color:#b45309;"></p>
                                </div>
                                <div class="c2-form-group">
                                    <label data-i18n="c2.payloads.hostOptional">回连地址（可选）</label>
                                    <input type="text" id="c2-build-host" class="form-control" data-i18n="c2.payloads.placeholderListenerHost" data-i18n-attr="placeholder" placeholder="留空则使用监听器地址">
                                </div>
                                <div class="c2-form-row">
                                    <div class="c2-form-group">
                                        <label data-i18n="c2.payloads.os">目标系统</label>
                                        <select id="c2-build-os" class="form-control c2-form-select-native">
                                            <option value="linux" data-i18n="c2.payloads.linux">Linux</option>
                                            <option value="windows" data-i18n="c2.payloads.windows">Windows</option>
                                            <option value="darwin" data-i18n="c2.payloads.darwin">macOS</option>
                                        </select>
                                    </div>
                                    <div class="c2-form-group">
                                        <label data-i18n="c2.payloads.arch">目标架构</label>
                                        <select id="c2-build-arch" class="form-control c2-form-select-native">
                                            <option value="amd64" data-i18n="c2.payloads.amd64">AMD64</option>
                                            <option value="arm64" data-i18n="c2.payloads.arm64">ARM64</option>
                                            <option value="386" data-i18n="c2.payloads.386">386</option>
                                        </select>
                                    </div>
                                </div>
                                <button id="c2-build-btn" type="button" class="btn-primary" data-require-permission="c2:write" onclick="C2.buildBeacon()" style="width:100%;" data-i18n="c2.payloads.buildBeaconBtn">构建 Beacon</button>
                                <div id="c2-build-result"></div>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- C2 事件审计页面 -->
                <div id="page-c2-events" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.events.title">事件审计</h2>
                        <div class="page-header-actions">
                            <button type="button" class="btn-danger" id="c2-events-batch-delete" data-require-permission="c2:delete" disabled onclick="C2.deleteSelectedEvents()"><span data-i18n="c2.events.batchDelete">批量删除</span></button>
                            <button type="button" class="btn-secondary" onclick="C2.loadEvents()"><span data-i18n="common.refresh">刷新</span></button>
                        </div>
                    </div>
                    <div class="page-content c2-events-page-wrap">
                        <div class="c2-events-summary" id="c2-events-summary" hidden>
                            <span class="c2-events-stat">
                                <span class="c2-events-stat-label" data-i18n="c2.events.statTotal">当前筛选</span>
                                <strong id="c2-events-stat-total">0</strong>
                            </span>
                            <span class="c2-events-stat c2-events-stat--info">
                                <span class="c2-events-stat-label" data-i18n="c2.events.info">信息</span>
                                <strong id="c2-events-stat-info">0</strong>
                            </span>
                            <span class="c2-events-stat c2-events-stat--warn">
                                <span class="c2-events-stat-label" data-i18n="c2.events.warn">警告</span>
                                <strong id="c2-events-stat-warn">0</strong>
                            </span>
                            <span class="c2-events-stat c2-events-stat--critical">
                                <span class="c2-events-stat-label" data-i18n="c2.events.critical">严重</span>
                                <strong id="c2-events-stat-critical">0</strong>
                            </span>
                        </div>
                        <div class="c2-events-filter-card">
                            <div class="c2-events-time-presets" id="c2-events-time-presets">
                                <span class="c2-events-time-presets-label" data-i18n="c2.events.timePresets">快捷</span>
                                <button type="button" class="c2-events-time-preset-btn" data-preset="15m" data-i18n="c2.events.preset15m">最近15分钟</button>
                                <button type="button" class="c2-events-time-preset-btn" data-preset="1h" data-i18n="c2.events.preset1h">最近1小时</button>
                                <button type="button" class="c2-events-time-preset-btn" data-preset="24h" data-i18n="c2.events.preset24h">最近24小时</button>
                                <button type="button" class="c2-events-time-preset-btn" data-preset="7d" data-i18n="c2.events.preset7d">最近7天</button>
                                <button type="button" class="c2-events-time-preset-btn" data-preset="all" data-i18n="c2.events.presetAll">全部</button>
                            </div>
                            <div class="c2-events-filter-fields">
                                <label class="c2-events-field">
                                    <span data-i18n="c2.events.level">级别</span>
                                    <select id="c2-events-filter-level" class="form-control">
                                        <option value="" data-i18n="c2.events.filterAllLevels">全部级别</option>
                                        <option value="info" data-i18n="c2.events.info">信息</option>
                                        <option value="warn" data-i18n="c2.events.warn">警告</option>
                                        <option value="critical" data-i18n="c2.events.critical">严重</option>
                                    </select>
                                </label>
                                <label class="c2-events-field">
                                    <span data-i18n="c2.events.category">类别</span>
                                    <select id="c2-events-filter-category" class="form-control">
                                        <option value="" data-i18n="c2.events.filterAllCategories">全部类别</option>
                                        <option value="listener" data-i18n="c2.events.listener">监听器</option>
                                        <option value="session" data-i18n="c2.events.session">会话</option>
                                        <option value="task" data-i18n="c2.events.task">任务</option>
                                        <option value="payload" data-i18n="c2.events.payload">Payload</option>
                                        <option value="opsec" data-i18n="c2.events.opsec">OPSEC</option>
                                    </select>
                                </label>
                                <label class="c2-events-field c2-events-field--session">
                                    <span data-i18n="c2.events.filterSession">会话 ID</span>
                                    <input type="text" id="c2-events-filter-session" class="form-control" data-i18n="c2.events.filterSessionPlaceholder" data-i18n-attr="placeholder" placeholder="s_xxxxxxxx" autocomplete="off" spellcheck="false" />
                                </label>
                                <div class="c2-events-filter-actions">
                                    <button type="button" class="btn-primary btn-small" onclick="C2.applyEventsFilters()" data-i18n="c2.events.applyFilters">应用筛选</button>
                                    <button type="button" class="btn-secondary btn-small" onclick="C2.resetEventsFilters()" data-i18n="c2.events.resetFilters">重置</button>
                                </div>
                            </div>
                        </div>
                        <div class="c2-events-panel">
                            <div id="c2-event-list" class="c2-events-list-container"></div>
                            <div id="c2-events-pagination" class="pagination-container c2-events-pagination"></div>
                        </div>
                    </div>
                </div>

                <!-- C2 Profile 管理页面 -->
                <div id="page-c2-profiles" class="page">
                    <div class="page-header">
                        <h2 data-i18n="c2.profiles.title">流量伪装</h2>
                        <div class="page-header-actions">
                            <button class="btn-primary" data-require-permission="c2:write" onclick="C2.showCreateProfileModal()" data-i18n="c2.profiles.createBtn">+ 创建 Profile</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div id="c2-profile-list" class="c2-profile-list"></div>
                    </div>
                </div>

                <!-- C2 模态框 -->
                <div id="c2-modal" class="c2-modal-overlay" style="display:none;" onclick="if(event.target===this)C2.closeModal()">
                    <div class="c2-modal" onclick="event.stopPropagation()">
                        <div id="c2-modal-content"></div>
                    </div>
                </div>

                <!-- 工作流页面 -->
                <div id="page-workflows" class="page">
                    <div class="page-header">
                        <h2 data-i18n="workflows.title">工作流</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="refreshWorkflows()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-secondary" data-require-permission="workflow:write" type="button" onclick="openWorkflowPackageImportModal()" data-i18n="workflows.package.importLocal">导入本地包</button>
                            <button class="btn-secondary" data-require-permission="workflow:write" type="button" onclick="openWorkflowAiModal()" data-i18n="workflows.ai.open">用自然语言创建</button>
                            <button class="btn-primary" onclick="newWorkflowDraft()" data-i18n="workflows.newGraph">新建工作流</button>
                        </div>
                    </div>
                    <div class="page-content workflow-page-content">
                        <aside class="workflow-sidebar">
                            <div class="workflow-panel">
                                <div class="workflow-panel-header">
                                    <h3 data-i18n="workflows.processLibrary">工作流列表</h3>
                                </div>
                                <div id="workflow-list" class="workflow-list">
                                    <div class="loading-spinner" data-i18n="common.loading">加载中...</div>
                                </div>
                            </div>
                            <div class="workflow-panel">
                                <div class="workflow-panel-header">
                                    <h3 data-i18n="workflows.nodeLibrary">节点库</h3>
                                </div>
                                <div class="workflow-node-palette">
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="start" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('start')" data-i18n="workflows.nodes.start">开始</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="tool" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('tool')" data-i18n="workflows.nodes.tool">工具</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="agent" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('agent')" data-i18n="workflows.nodes.agent">Agent</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="condition" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('condition')" data-i18n="workflows.nodes.condition">条件</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="hitl" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('hitl')" data-i18n="workflows.nodes.hitl">审批</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="output" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('output')" data-i18n="workflows.nodes.output">输出</button>
                                    <button type="button" draggable="true" data-require-permission="workflow:write" data-node-type="end" ondragstart="workflowPaletteDragStart(event)" onclick="addWorkflowNodeFromPalette('end')" data-i18n="workflows.nodes.end">结束</button>
                                </div>
                            </div>
                        </aside>
                        <main class="workflow-main">
                            <section class="workflow-meta-bar">
                                <div class="workflow-canvas-header">
                                    <div class="workflow-canvas-heading">
                                        <h3 id="workflow-canvas-title" class="workflow-canvas-title" data-i18n="workflows.untitled">未命名工作流</h3>
                                        <span id="workflow-canvas-subtitle" class="workflow-canvas-subtitle" hidden></span>
                                    </div>
                                </div>
                                <div class="workflow-toolbar" role="toolbar" aria-label="工作流编辑工具" data-i18n="workflows.toolbarLabel" data-i18n-attr="aria-label" data-i18n-skip-text="true">
                                    <div class="workflow-toolbar-group" role="group" aria-label="画布工具" data-i18n="workflows.canvasTools" data-i18n-attr="aria-label" data-i18n-skip-text="true">
                                        <button class="btn-secondary btn-small workflow-toolbar-button" data-require-permission="workflow:write" type="button" onclick="toggleWorkflowConnectMode()" id="workflow-connect-btn" aria-pressed="false">
                                            <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="2.5"/><circle cx="18" cy="18" r="2.5"/><path d="M8 8l8 8"/></svg>
                                            <span class="workflow-toolbar-label" data-i18n="workflows.connect">连线</span>
                                        </button>
                                        <button class="btn-secondary btn-small workflow-toolbar-button" type="button" onclick="layoutWorkflowGraph()">
                                            <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="3" width="6" height="5" rx="1"/><rect x="14" y="16" width="6" height="5" rx="1"/><path d="M7 8v4h10v4"/></svg>
                                            <span class="workflow-toolbar-label" data-i18n="workflows.autoLayout">自动布局</span>
                                        </button>
                                    </div>
                                    <button class="btn-secondary btn-small workflow-toolbar-button workflow-run-button" data-require-permission="workflow:execute" type="button" onclick="dryRunWorkflowDraft()">
                                        <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5.4v13.2a1 1 0 0 0 1.55.84l9.2-6.6a1 1 0 0 0 0-1.68l-9.2-6.6A1 1 0 0 0 8 5.4Z"/></svg>
                                        <span class="workflow-toolbar-label" data-i18n="workflows.dryRun">试运行</span>
                                    </button>
                                    <button class="btn-secondary btn-small workflow-toolbar-button workflow-ai-button" data-require-permission="workflow:write" type="button" onclick="openWorkflowAiModal()">
                                        <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3Z"/><path d="M19 14l.8 2.2L22 17l-2.2.8L19 20l-.8-2.2L16 17l2.2-.8L19 14Z"/></svg>
                                        <span class="workflow-toolbar-label" data-i18n="workflows.ai.generate">生成草稿</span>
                                    </button>
                                    <details class="workflow-more-actions" id="workflow-more-actions" data-require-permission-any="workflow:read workflow:delete">
                                        <summary class="btn-secondary btn-small workflow-more-actions-trigger" aria-haspopup="menu">
                                            <svg aria-hidden="true" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><circle cx="5" cy="12" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="19" cy="12" r="1.8"/></svg>
                                            <span class="workflow-toolbar-label" data-i18n="workflows.moreActions">更多</span>
                                        </summary>
                                        <div class="workflow-more-actions-menu" role="menu">
                                            <button data-require-permission="workflow:read" type="button" id="workflow-package-export-btn" role="menuitem" onclick="closeWorkflowMoreActions(); exportCurrentWorkflowPackage()">
                                                <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12m0 0 4-4m-4 4-4-4"/><path d="M5 19h14"/></svg>
                                                <span data-i18n="workflows.package.export">导出</span>
                                            </button>
                                            <div class="workflow-more-actions-divider" role="separator"></div>
                                            <button class="workflow-more-actions-danger" data-require-permission="workflow:delete" type="button" role="menuitem" onclick="closeWorkflowMoreActions(); deleteCurrentWorkflow()">
                                                <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h16M9 7V4h6v3m3 0-1 13H7L6 7"/><path d="M10 11v5m4-5v5"/></svg>
                                                <span data-i18n="workflows.deleteWorkflow">删除工作流</span>
                                            </button>
                                        </div>
                                    </details>
                                    <button class="btn-primary btn-small workflow-save-button" data-require-permission="workflow:write" type="button" onclick="saveWorkflowDraft()">
                                        <svg aria-hidden="true" width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 4h12l2 2v14H5z"/><path d="M8 4v6h8V4M8 20v-6h8v6"/></svg>
                                        <span data-i18n="common.save">保存</span>
                                    </button>
                                </div>
                            </section>
                            <section class="workflow-canvas-wrap" ondragover="workflowCanvasDragOver(event)" ondrop="workflowCanvasDrop(event)">
                                <div id="workflow-canvas"></div>
                                <div id="workflow-canvas-empty" class="workflow-canvas-empty" data-i18n="workflows.canvasEmpty">从左侧拖拽节点到画布，或用自然语言生成工作流</div>
                                <div id="workflow-ai-canvas-status" class="workflow-ai-canvas-status" hidden data-i18n="workflows.ai.canvasRendering">AI 正在编排画布…</div>
                            </section>
                        </main>
                        <aside class="workflow-properties">
                            <div class="workflow-panel-header">
                                <h3 id="workflow-property-title" data-i18n="workflows.properties">属性</h3>
                                <button type="button" id="workflow-property-delete-btn" class="btn-secondary btn-small" data-require-permission="workflow:delete" onclick="deleteWorkflowSelection()" hidden data-i18n="common.delete">删除</button>
                            </div>
                            <div id="workflow-property-empty" class="workflow-property-empty" data-i18n="workflows.propertyEmpty">选择一个节点或连线后编辑属性</div>
                            <div id="workflow-property-form" class="workflow-property-form" hidden>
                                <div class="form-group">
                                    <label for="workflow-prop-label" data-i18n="workflows.propLabel">名称</label>
                                    <input type="text" id="workflow-prop-label" class="form-input" oninput="updateWorkflowSelectedProperty()">
                                </div>
                                <div class="form-group" id="workflow-prop-type-wrap">
                                    <label for="workflow-prop-type" data-i18n="workflows.propType">类型</label>
                                    <select id="workflow-prop-type" class="workflow-form-select-native" onchange="updateWorkflowSelectedProperty()">
                                        <option value="start" data-i18n="workflows.nodes.start">开始</option>
                                        <option value="tool" data-i18n="workflows.nodes.tool">工具</option>
                                        <option value="agent" data-i18n="workflows.nodes.agent">Agent</option>
                                        <option value="condition" data-i18n="workflows.nodes.condition">条件</option>
                                        <option value="hitl" data-i18n="workflows.nodes.hitl">审批</option>
                                        <option value="output" data-i18n="workflows.nodes.output">输出</option>
                                        <option value="end" data-i18n="workflows.nodes.end">结束</option>
                                    </select>
                                </div>
                                <div id="workflow-typed-config" class="workflow-typed-config"></div>
                                <div class="workflow-custom-fields-head">
                                    <span data-i18n="workflows.customFields">自定义字段</span>
                                    <button type="button" class="btn-secondary btn-small" data-require-permission="workflow:write" onclick="addWorkflowCustomField()" data-i18n="workflows.addField">添加字段</button>
                                </div>
                                <div id="workflow-custom-fields" class="workflow-custom-fields"></div>
                            </div>
                            <div id="workflow-dry-run-panel" class="workflow-property-form workflow-dry-run-panel" hidden>
                                <div class="workflow-custom-fields-head workflow-dry-run-head">
                                    <span data-i18n="workflows.dryRunTrace">试运行轨迹</span>
                                    <button type="button" class="role-selection-panel-close workflow-dry-run-close" onclick="closeWorkflowDryRunPanel()" data-i18n="common.close" data-i18n-attr="title,aria-label" title="关闭" aria-label="关闭">
                                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
                                            <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                        </svg>
                                    </button>
                                </div>
                                <div id="workflow-dry-run-output" class="workflow-property-empty workflow-property-empty--compact"></div>
                            </div>
                        </aside>
                    </div>
                </div>

                <!-- 角色管理页面 -->
                <div id="page-roles-management" class="page">
                    <div class="page-header">
                        <h2 data-i18n="roles.title">角色管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="refreshRoles()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-primary" data-require-permission="roles:write" onclick="showAddRoleModal()" data-i18n="roles.createRole">创建角色</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="roles-controls">
                            <div class="roles-search-box">
                                <input type="text" id="roles-search" data-i18n="roles.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索角色..." oninput="handleRolesSearchInput()" onkeydown="if(event.key==='Enter') searchRoles()" />
                                <button class="roles-search-clear" id="roles-search-clear" onclick="clearRolesSearch()" style="display: none;" data-i18n="common.clearSearch" data-i18n-attr="title" title="清除搜索">
                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
                                        <path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                    </svg>
                                </button>
                            </div>
                        </div>
                        <div id="roles-list" class="roles-grid">
                            <div class="loading-spinner" data-i18n="knowledgePage.loading">加载中...</div>
                        </div>
                    </div>
                </div>

                <!-- Skills状态监控页面 -->
                <div id="page-skills-monitor" class="page skills-monitor-page">
                    <div class="page-header">
                        <h2 data-i18n="skills.monitorTitle">Skills状态监控</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="refreshSkillsMonitor()" data-i18n="common.refresh">刷新</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <div class="monitor-sections">
                            <section class="monitor-section monitor-overview">
                                <div class="section-header">
                                    <h3 data-i18n="skills.callStats">调用统计</h3>
                                </div>
                                <div id="skills-stats" class="monitor-stats-grid">
                                    <div class="monitor-empty" data-i18n="skillsPage.loading">加载中...</div>
                                </div>
                            </section>
                            <section class="monitor-section monitor-executions">
                                <div class="section-header">
                                    <h3 data-i18n="skillsPage.skillsCallStats">Skills调用统计</h3>
                                    <div class="section-actions">
                                        <button class="btn-secondary btn-small" onclick="clearSkillsStats()" data-i18n="skillsPage.clearStatsTitle" data-i18n-attr="title" data-i18n-skip-text="true" title="清空所有统计数据"><span data-i18n="skillsPage.clearStats">清空统计</span></button>
                                    </div>
                                </div>
                                <div id="skills-monitor-list" class="monitor-table-container">
                                    <div class="monitor-empty" data-i18n="skillsPage.loading">加载中...</div>
                                </div>
                            </section>
                        </div>
                    </div>
                </div>

                <!-- Skills管理页面 -->
                <div id="page-skills-management" class="page skills-management-page">
                    <div class="page-header">
                        <h2 data-i18n="skills.title">Skills管理</h2>
                        <div class="page-header-actions">
                            <button class="btn-secondary" onclick="refreshSkills()" data-i18n="common.refresh">刷新</button>
                            <button class="btn-primary" data-require-permission="skills:write" onclick="showAddSkillModal()" data-i18n="skills.createSkill">创建Skill</button>
                        </div>
                    </div>
                    <div class="page-content page-content-with-pagination">
                        <div class="skills-overview" id="skills-management-stats">
                            <div class="skills-overview-card skills-overview-card-primary">
                                <span class="skills-overview-label" data-i18n="skillsPage.overviewTotal">Skills</span>
                                <strong class="skill-stat-value">0</strong>
                            </div>
                            <div class="skills-overview-card">
                                <span class="skills-overview-label" data-i18n="skillsPage.overviewCurrent">当前页</span>
                                <strong id="skills-current-count">0</strong>
                            </div>
                            <div class="skills-overview-card">
                                <span class="skills-overview-label" data-i18n="skillsPage.overviewFiles">文件</span>
                                <strong id="skills-file-count">0</strong>
                            </div>
                            <div class="skills-overview-card">
                                <span class="skills-overview-label" data-i18n="skillsPage.overviewScripts">脚本</span>
                                <strong id="skills-script-count">0</strong>
                            </div>
                        </div>
                        <div class="skills-controls">
                            <div class="skills-search-box">
                                <input type="text" id="skills-search" data-i18n="skillsPage.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索Skills..." oninput="handleSkillsSearchInput()" onkeydown="if(event.key==='Enter') searchSkills()" />
                                <button class="skills-search-clear" id="skills-search-clear" onclick="clearSkillsSearch()" style="display: none;" data-i18n="common.clearSearch" data-i18n-attr="title" title="清除搜索">
                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
                                        <path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                    </svg>
                                </button>
                            </div>
                        </div>
                        <div id="skills-list" class="skills-grid">
                            <div class="loading-spinner" data-i18n="skillsPage.loading">加载中...</div>
                        </div>
                        <div id="skills-pagination" class="pagination-container pagination-fixed"></div>
                    </div>
                </div>

                <!-- 多代理子 Agent（Markdown）管理 -->
                <div id="page-agents-management" class="page">
                    <div class="page-header">
                        <h2 data-i18n="agentsPage.title">Agent 管理</h2>
                        <div class="page-header-actions">
                            <button type="button" class="btn-secondary" onclick="loadMarkdownAgents()" data-i18n="common.refresh">刷新</button>
                            <button type="button" class="btn-primary" data-require-permission="agents:write" onclick="showAddMarkdownAgentModal()" data-i18n="agentsPage.create">新建 Agent</button>
                        </div>
                    </div>
                    <div class="page-content">
                        <p class="agents-page-hint" data-i18n="agentsPage.hint">子 Agent 仅在 agents 目录下 .md 维护。</p>
                        <div id="agents-md-dir" class="agents-dir-label"></div>
                        <div id="agents-md-list" class="skills-grid">
                            <div class="loading-spinner" data-i18n="agentsPage.loading">加载中...</div>
                        </div>
                    </div>
                </div>

                <!-- Agent Markdown 编辑弹窗 -->
                <div id="agent-md-modal" class="modal" style="display: none;">
                    <div class="modal-content" style="max-width: 720px; max-height: 92vh;">
                        <div class="modal-header">
                            <h2 id="agent-md-modal-title" data-i18n="agentsPage.editTitle">编辑 Agent</h2>
                            <span class="modal-close" onclick="closeMarkdownAgentModal()">&times;</span>
                        </div>
                        <div class="modal-body" style="overflow-y: auto; max-height: calc(92vh - 130px);">
                            <input type="hidden" id="agent-md-filename-current" value="">
                            <div class="form-group" id="agent-md-filename-row">
                                <label data-i18n="agentsPage.filename">文件名（.md）</label>
                                <input type="text" id="agent-md-filename" data-i18n="agentsPage.filenamePlaceholder" data-i18n-attr="placeholder" placeholder="例如 code-reviewer.md" autocomplete="off" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldRole">类型</label>
                                <select id="agent-md-role" class="form-select">
                                    <option value="sub" data-i18n="agentsPage.roleSub">子代理</option>
                                    <option value="orchestrator" data-i18n="agentsPage.roleOrchestrator">主代理（Deep 协调者）</option>
                                </select>
                                <p class="form-hint muted" data-i18n="agentsPage.roleHint">主代理也可使用固定文件名 orchestrator.md；全目录仅允许一个主代理。</p>
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldId">Agent ID（留空则从名称生成）</label>
                                <input type="text" id="agent-md-id" placeholder="code-reviewer" autocomplete="off" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldName">显示名称</label>
                                <input type="text" id="agent-md-name" data-i18n="agentsPage.namePlaceholder" data-i18n-attr="placeholder" placeholder="Code Reviewer" autocomplete="off" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldDesc">描述</label>
                                <textarea id="agent-md-description" rows="2" data-i18n="agentsPage.descPlaceholder" data-i18n-attr="placeholder" placeholder="何时调用该子代理"></textarea>
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldTools">可用工具（逗号分隔，与角色工具 key 一致）</label>
                                <input type="text" id="agent-md-tools" placeholder="tool_a, tool_b" autocomplete="off" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldBindRole">绑定角色（可选）</label>
                                <input type="text" id="agent-md-bind-role" placeholder="" autocomplete="off" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldMaxIter">最大迭代（0=沿用设置页 agent.max_iterations）</label>
                                <input type="number" id="agent-md-max-iter" min="0" value="0" />
                            </div>
                            <div class="form-group">
                                <label data-i18n="agentsPage.fieldInstruction">系统提示词（Markdown 正文）</label>
                                <textarea id="agent-md-instruction" rows="14" data-i18n="agentsPage.instructionPlaceholder" data-i18n-attr="placeholder" placeholder="You are a specialist agent..."></textarea>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <button type="button" class="btn-secondary" onclick="closeMarkdownAgentModal()" data-i18n="common.cancel">取消</button>
                            <button type="button" class="btn-primary" data-require-permission="agents:write" onclick="saveMarkdownAgent()" data-i18n="common.save">保存</button>
                        </div>
                    </div>
                </div>

                <!-- 系统设置页面 -->
                <div id="page-settings" class="page">
                    <div class="page-header">
                        <h2 data-i18n="settings.title">系统设置</h2>
                    </div>
                    <div class="page-content settings-layout">
                        <!-- 左侧导航栏 -->
                        <aside class="settings-sidebar">
                            <nav class="settings-nav">
                                <div class="settings-nav-item active" data-section="basic" onclick="switchSettingsSection('basic')">
                                    <span data-i18n="settings.nav.basic">基本设置</span>
                                </div>
                                <div class="settings-nav-item" data-section="hitl" onclick="switchSettingsSection('hitl')">
                                    <span data-i18n="settings.nav.hitl">人机协同</span>
                                </div>
                                <div class="settings-nav-item" data-section="infocollect" onclick="switchSettingsSection('infocollect')">
                                    <span data-i18n="settings.nav.infocollect">资产管理</span>
                                </div>
                                <div class="settings-nav-item" data-section="knowledge" onclick="switchSettingsSection('knowledge')">
                                    <span data-i18n="settings.nav.knowledge">知识库</span>
                                </div>
                                <div class="settings-nav-item" data-section="c2" onclick="switchSettingsSection('c2')">
                                    <span data-i18n="settings.nav.c2">C2</span>
                                </div>
                                <div class="settings-nav-item" data-section="robots" onclick="switchSettingsSection('robots')">
                                    <span data-i18n="settings.nav.robots">机器人设置</span>
                                </div>
                                <div class="settings-nav-item" data-section="terminal" onclick="switchSettingsSection('terminal')">
                                    <span data-i18n="settings.nav.terminal">终端</span>
                                </div>
                                <div class="settings-nav-item" data-section="security" onclick="switchSettingsSection('security')">
                                    <span data-i18n="settings.nav.security">安全设置</span>
                                </div>
                                <div class="settings-nav-item" data-section="audit" onclick="switchSettingsSection('audit')">
                                    <span data-i18n="settings.nav.audit">日志审计</span>
                                </div>
                            </nav>
                        </aside>
                        
                        <!-- 右侧内容区域 -->
                        <div class="settings-content">
                            <!-- 基本设置 -->
                            <div id="settings-section-basic" class="settings-section-content active">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settingsBasic.basicTitle">基本设置</h3>
                                </div>
                                
                                <!-- AI 通道配置 -->
                                <div class="settings-subsection">
                                    <div class="ai-channel-manager">
                                        <div class="ai-channel-manager-header">
                                            <div>
                                                <h4 data-i18n="settingsBasic.openaiConfig">AI 通道配置</h4>
                                                <p id="ai-channel-save-hint" class="ai-channel-manager-hint" data-i18n="settingsBasic.aiChannelHint">通过下拉切换已保存通道；保存后写入 ai.channels，默认通道用于新对话和未指定通道的任务。</p>
                                            </div>
                                            <div class="ai-channel-header-actions">
                                                <button type="button" class="btn-secondary" onclick="createAIChannelFromForm()" data-i18n="settingsBasic.aiChannelNew">新增</button>
                                                <button type="button" class="btn-primary ai-channel-save-btn" onclick="saveSelectedAIChannel()" data-i18n="settingsBasic.aiChannelSave">保存更改</button>
                                            </div>
                                        </div>
                                        <div class="ai-channel-manager-body">
                                            <div class="ai-channel-switcher" aria-label="AI 通道选择" data-i18n="settingsBasic.aiChannelListAria" data-i18n-attr="aria-label">
                                                <div class="ai-channel-switcher-field">
                                                    <label for="ai-channel-select" data-i18n="settingsBasic.aiChannelCurrent">当前通道</label>
                                                    <select id="ai-channel-select" class="ai-channel-switch-select" onchange="selectAIChannelForEditing(this.value)"></select>
                                                </div>
                                                <div class="ai-channel-switcher-actions">
                                                    <button type="button" class="btn-secondary" onclick="probeSelectedAIChannels()" data-i18n="settingsBasic.aiChannelBulkProbe" data-i18n-title="settingsBasic.aiChannelBulkProbeTitle" data-i18n-attr="title">批量探活</button>
                                                    <button type="button" class="btn-secondary" onclick="copyAIChannelFromForm()" data-i18n="settingsBasic.aiChannelCopy">复制</button>
                                                    <button type="button" class="btn-secondary" onclick="setSelectedAIChannelDefault()" data-i18n="settingsBasic.aiChannelSetDefault">设为默认</button>
                                                    <button type="button" class="btn-secondary danger" onclick="deleteSelectedAIChannel()" data-i18n="settingsBasic.aiChannelDelete">删除</button>
                                                </div>
                                                <div id="ai-channel-list" class="ai-channel-list" aria-live="polite"></div>
                                            </div>
                                            <div class="ai-channel-editor">
                                                <div class="ai-channel-editor-head">
                                                    <div>
                                                        <span class="ai-channel-editor-kicker" data-i18n="settingsBasic.aiChannelFormContext">编辑当前选择的通道</span>
                                                        <p id="ai-channel-editor-title" class="ai-channel-editor-title">-</p>
                                                    </div>
                                                    <div id="ai-channel-editor-meta" class="ai-channel-editor-meta" aria-live="polite"></div>
                                                </div>
                                                <div class="settings-form ai-channel-editor-form">
                                                    <section class="ai-channel-form-section">
                                                        <div class="ai-channel-form-section-head">
                                                            <div>
                                                                <h6 data-i18n="settingsBasic.aiChannelConnectionSection">连接信息</h6>
                                                                <p data-i18n="settingsBasic.aiChannelConnectionHint">先确认服务商、地址、密钥和模型，测试连接会使用这些信息。</p>
                                                            </div>
                                                            <div class="ai-channel-section-actions">
                                                                <button type="button" id="test-openai-btn" class="btn-secondary" onclick="testOpenAIConnection()" data-i18n="settingsBasic.testConnection">测试连接</button>
                                                                <span id="test-openai-result" class="form-inline-result connection-test-result"></span>
                                                            </div>
                                                        </div>
                                                        <div class="ai-channel-form-grid">
                                                            <div class="form-group">
                                                                <label for="ai-channel-name" data-i18n="settingsBasic.aiChannelName">通道名称</label>
                                                                <input type="text" id="ai-channel-name" placeholder="Qwen Max" maxlength="24" />
                                                            </div>
                                                            <div class="form-group">
                                                                <label for="openai-provider" data-i18n="settingsBasic.apiProvider">API 提供商</label>
                                                                <select id="openai-provider">
                                                                    <option value="openai_compatible" data-i18n="settingsBasic.providerOpenAI">OpenAI / 兼容 OpenAI 协议</option>
                                                                    <option value="claude" data-i18n="settingsBasic.providerClaude">Claude (Anthropic Messages API)</option>
                                                                </select>
                                                            </div>
                                                            <div class="form-group span-2">
                                                                <label for="openai-base-url">Base URL <span class="required-mark">*</span></label>
                                                                <input type="text" id="openai-base-url" data-i18n="settingsBasic.openaiBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="https://api.openai.com/v1" required />
                                                            </div>
                                                            <div class="form-group span-2">
                                                                <label for="openai-api-key">API Key <span class="required-mark">*</span></label>
                                                                <input type="password" id="openai-api-key" data-i18n="settingsBasic.openaiApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="输入OpenAI API Key" required />
                                                            </div>
                                                            <div class="form-group span-2">
                                                                <label for="openai-model"><span data-i18n="settingsBasic.model">模型</span> <span class="required-mark">*</span></label>
                                                                <div class="model-pick-row">
                                                                    <input type="text" id="openai-model" class="model-pick-input" data-i18n="settingsBasic.modelPlaceholder" data-i18n-attr="placeholder" placeholder="gpt-4" required />
                                                                    <select id="openai-model-select" class="model-pick-native" style="display: none;" title="" aria-hidden="true" tabindex="-1">
                                                                        <option value="" disabled data-i18n="settingsBasic.modelsListSelectPlaceholder">请选择模型</option>
                                                                    </select>
                                                                    <a href="javascript:void(0)" id="fetch-openai-models-btn" class="model-pick-fetch-link" onclick="fetchModelList('openai')" data-i18n="settingsBasic.fetchModels">获取列表</a>
                                                                </div>
                                                                <small id="fetch-openai-models-hint" class="form-hint" style="display: none;"></small>
                                                                <span id="fetch-openai-models-result" class="form-inline-result"></span>
                                                            </div>
                                                        </div>
                                                    </section>

                                                    <section class="ai-channel-form-section">
                                                        <div class="ai-channel-form-section-head">
                                                            <div>
                                                                <h6 data-i18n="settingsBasic.aiChannelLimitsSection">额度设置</h6>
                                                                <p data-i18n="settingsBasic.aiChannelLimitsHint">Token 上限控制上下文窗口和单次输出。</p>
                                                            </div>
                                                        </div>
                                                        <div class="ai-channel-form-grid">
                                                            <div class="form-group">
                                                                <label for="openai-max-total-tokens"><span data-i18n="settingsBasic.maxTotalTokens">最大上下文 Token 数</span></label>
                                                                <input type="number" id="openai-max-total-tokens" data-i18n="settingsBasic.maxTotalTokensPlaceholder" data-i18n-attr="placeholder" placeholder="120000" min="1000" step="1000" />
                                                                <small class="form-hint" data-i18n="settingsBasic.maxTotalTokensHint">内存压缩和攻击链构建共用此配置，默认 120000</small>
                                                            </div>
                                                            <div class="form-group">
                                                                <label for="openai-max-completion-tokens"><span data-i18n="settingsBasic.maxCompletionTokens">最大输出 Token 数</span></label>
                                                                <input type="number" id="openai-max-completion-tokens" data-i18n="settingsBasic.maxCompletionTokensPlaceholder" data-i18n-attr="placeholder" placeholder="16384" min="1" step="256" />
                                                                <small class="form-hint" data-i18n="settingsBasic.maxCompletionTokensHint">单次模型回复的输出上限，默认 16384</small>
                                                            </div>
                                                        </div>
                                                    </section>

                                                    <details class="ai-channel-form-section ai-channel-advanced-section">
                                                        <summary>
                                                            <span>
                                                                <strong data-i18n="settingsBasic.openaiReasoningTitle">推理设置</strong>
                                                                <small data-i18n="settingsBasic.openaiReasoningHint">作为该 AI 通道的默认推理设置；对话页「会话设置」可覆盖。</small>
                                                            </span>
                                                        </summary>
                                                        <div class="ai-channel-reasoning-grid">
                                                            <div class="form-group">
                                                                <label for="openai-reasoning-mode" data-i18n="chat.reasoningModeLabel">模式</label>
                                                                <select id="openai-reasoning-mode">
                                                                    <option value="auto" data-i18n="chat.reasoningModeAuto">自动</option>
                                                                    <option value="on" data-i18n="chat.reasoningModeOn">开启</option>
                                                                    <option value="off" data-i18n="chat.reasoningModeOff">关闭</option>
                                                                </select>
                                                            </div>
                                                            <div class="form-group">
                                                                <label for="openai-reasoning-effort" data-i18n="chat.reasoningEffortLabel">强度</label>
                                                                <select id="openai-reasoning-effort">
                                                                    <option value="" data-i18n="chat.reasoningEffortUnset">不指定</option>
                                                                    <option value="low">low</option>
                                                                    <option value="medium">medium</option>
                                                                    <option value="high">high</option>
                                                                    <option value="xhigh">xhigh</option>
                                                                    <option value="max">max</option>
                                                                </select>
                                                            </div>
                                                            <div class="form-group">
                                                                <label for="openai-reasoning-profile" data-i18n="settingsBasic.openaiReasoningProfile">线路</label>
                                                                <select id="openai-reasoning-profile">
                                                                    <option value="auto">auto</option>
                                                                    <option value="deepseek">deepseek</option>
                                                                    <option value="deepseek_compat">deepseek_compat</option>
                                                                    <option value="openai_compat">openai_compat</option>
                                                                    <option value="output_config_effort">output_config_effort</option>
                                                                </select>
                                                            </div>
                                                        </div>
                                                        <label class="checkbox-label ai-channel-reasoning-toggle">
                                                            <input type="checkbox" id="openai-reasoning-allow-client" class="modern-checkbox" checked />
                                                            <span class="checkbox-custom"></span>
                                                            <span class="checkbox-text" data-i18n="settingsBasic.openaiReasoningAllowClient">允许对话页覆盖推理选项</span>
                                                        </label>
                                                    </details>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <!-- Vision 视觉分析 -->
                                <div class="settings-subsection">
                                    <h4 data-i18n="settingsBasic.visionConfig">视觉分析（analyze_image）</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="vision-enabled" class="modern-checkbox" onchange="syncVisionFormEnabled()" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settingsBasic.visionEnabled">启用视觉分析工具 analyze_image</span>
                                            </label>
                                            <small class="form-hint" data-i18n="settingsBasic.visionEnabledHint">启用后注册 MCP 工具；图片仅在单次 VL 调用中出现，Agent 上下文只保留文字摘要。</small>
                                        </div>
                                        <div id="vision-fields-panel">
                                            <div class="form-group">
                                                <label for="vision-provider" data-i18n="settingsBasic.provider">提供商</label>
                                                <select id="vision-provider" style="width: 100%; padding: 0.5rem 0.75rem; border: 1px solid var(--border-color, #e2e8f0); border-radius: 6px; background: var(--card-bg, #fff); color: var(--text-color, #2d3748); font-size: 0.875rem;">
                                                    <option value="" data-i18n="settingsBasic.visionProviderReuseOpenAI">默认 AI 通道（留空复用）</option>
                                                    <option value="openai" data-i18n="settingsBasic.providerOpenAI">OpenAI / 兼容 OpenAI 协议</option>
                                                    <option value="claude" data-i18n="settingsBasic.providerClaude">Claude (Anthropic Messages API)</option>
                                                </select>
                                            </div>
                                            <div class="form-group">
                                                <label for="vision-base-url" data-i18n="settingsBasic.baseUrl">Base URL</label>
                                                <input type="text" id="vision-base-url" data-i18n="settingsBasic.visionBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用 OpenAI Base URL" />
                                            </div>
                                            <div class="form-group">
                                                <label for="vision-api-key" data-i18n="settingsBasic.apiKey">API Key</label>
                                                <input type="password" id="vision-api-key" data-i18n="settingsBasic.visionApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用 OpenAI API Key" />
                                            </div>
                                            <div class="form-group">
                                                <label for="vision-model"><span data-i18n="settingsBasic.visionModel">视觉模型</span> <span style="color: red;">*</span></label>
                                                <div class="model-pick-row">
                                                    <input type="text" id="vision-model" class="model-pick-input" data-i18n="settingsBasic.visionModelPlaceholder" data-i18n-attr="placeholder" placeholder="qwen-vl-max" />
                                                    <select id="vision-model-select" class="model-pick-native" style="display: none;" aria-hidden="true" tabindex="-1">
                                                        <option value="" disabled data-i18n="settingsBasic.modelsListSelectPlaceholder">请选择模型</option>
                                                    </select>
                                                    <a href="javascript:void(0)" id="fetch-vision-models-btn" class="model-pick-fetch-link" onclick="fetchModelList('vision')" data-i18n="settingsBasic.fetchModels">获取列表</a>
                                                </div>
                                                <small id="fetch-vision-models-hint" class="form-hint" style="display: none; font-size: 0.75rem; margin-top: 4px;"></small>
                                                <span id="fetch-vision-models-result" style="font-size: 0.75rem; margin-top: 2px; display: block;"></span>
                                            </div>
                                            <details style="margin-top: 8px;">
                                                <summary style="cursor: pointer; font-size: 0.875rem; color: var(--accent-color, #3182ce);" data-i18n="settingsBasic.visionAdvanced">高级：预处理与限制</summary>
                                                <div style="margin-top: 12px;">
                                                    <div class="form-group">
                                                        <label for="vision-max-image-bytes" data-i18n="settingsBasic.visionMaxImageBytes">原始文件上限（字节）</label>
                                                        <input type="number" id="vision-max-image-bytes" min="0" step="1024" placeholder="5242880" />
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-max-dimension" data-i18n="settingsBasic.visionMaxDimension">长边缩放像素</label>
                                                        <input type="number" id="vision-max-dimension" min="256" step="1" placeholder="2048" />
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-jpeg-quality" data-i18n="settingsBasic.visionJpegQuality">JPEG 质量</label>
                                                        <input type="number" id="vision-jpeg-quality" min="60" max="100" step="1" placeholder="82" />
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-max-payload-bytes" data-i18n="settingsBasic.visionMaxPayloadBytes">送 API 体积上限（字节）</label>
                                                        <input type="number" id="vision-max-payload-bytes" min="0" step="1024" placeholder="524288" />
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-skip-preprocess-bytes" data-i18n="settingsBasic.visionSkipPreprocessBytes">低于该字节可原图直传</label>
                                                        <input type="number" id="vision-skip-preprocess-bytes" min="0" step="1024" placeholder="2097152" />
                                                        <small class="form-hint" data-i18n="settingsBasic.visionSkipPreprocessHint">0 表示始终 JPEG 压缩；需同时满足长边与 payload 限制。</small>
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-detail" data-i18n="settingsBasic.visionDetail">Image detail</label>
                                                        <select id="vision-detail" style="width: 100%; padding: 0.5rem 0.75rem; border: 1px solid var(--border-color, #e2e8f0); border-radius: 6px;">
                                                            <option value="low">low</option>
                                                            <option value="auto">auto</option>
                                                            <option value="high">high</option>
                                                        </select>
                                                    </div>
                                                    <div class="form-group">
                                                        <label for="vision-timeout-seconds" data-i18n="settingsBasic.visionTimeout">超时（秒）</label>
                                                        <input type="number" id="vision-timeout-seconds" min="5" step="1" placeholder="60" />
                                                    </div>
                                                </div>
                                            </details>
                                            <div style="display: flex; align-items: center; gap: 8px; margin-top: 8px;">
                                                <a href="javascript:void(0)" id="test-vision-btn" onclick="testVisionConnection()" style="font-size: 0.8125rem; color: var(--accent-color, #3182ce); text-decoration: none; cursor: pointer;" data-i18n="settingsBasic.testConnection">测试连接</a>
                                                <span id="test-vision-result" style="font-size: 0.8125rem;"></span>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <!-- Agent配置 -->
                                <div class="settings-subsection">
                                    <h4 data-i18n="settingsBasic.agentConfig">Agent 配置</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="agent-max-iterations" data-i18n="settingsBasic.maxIterations">最大迭代次数</label>
                                            <input type="number" id="agent-max-iterations" min="1" data-i18n="settingsBasic.iterationsPlaceholder" data-i18n-attr="placeholder" placeholder="30" />
                                        </div>
                                        <div class="form-group">
                                            <label for="agent-tool-wait-timeout-seconds" data-i18n="settingsBasic.toolWaitTimeoutSeconds">外部 MCP 单轮等待秒数</label>
                                            <input type="number" id="agent-tool-wait-timeout-seconds" min="0" step="1" placeholder="60" />
                                            <small class="form-hint" data-i18n="settingsBasic.toolWaitTimeoutSecondsHint">Agent 等待工具的单轮上限；到时返回 execution_id，worker 继续后台执行，可用 wait_tool_execution 继续等待。0 表示等到完成。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="agent-external-mcp-concurrency-server" data-i18n="settingsBasic.externalMcpConcurrencyServer">单 MCP 并发上限</label>
                                            <input type="number" id="agent-external-mcp-concurrency-server" min="-1" step="1" placeholder="2" />
                                            <small class="form-hint" data-i18n="settingsBasic.externalMcpConcurrencyServerHint">每个外部 MCP server 同时运行的工具数；0 使用默认 2，-1 不限制。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="agent-external-mcp-concurrency-total" data-i18n="settingsBasic.externalMcpConcurrencyTotal">外部 MCP 全局并发上限</label>
                                            <input type="number" id="agent-external-mcp-concurrency-total" min="-1" step="1" placeholder="16" />
                                            <small class="form-hint" data-i18n="settingsBasic.externalMcpConcurrencyTotalHint">所有外部 MCP 工具的总并发；0 使用默认 16，-1 不限制。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="agent-external-mcp-circuit-threshold" data-i18n="settingsBasic.externalMcpCircuitThreshold">MCP 熔断失败阈值</label>
                                            <input type="number" id="agent-external-mcp-circuit-threshold" min="-1" step="1" placeholder="3" />
                                            <small class="form-hint" data-i18n="settingsBasic.externalMcpCircuitThresholdHint">同一 MCP server 连续失败达到阈值后临时熔断；0 使用默认 3，-1 关闭熔断。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="agent-external-mcp-circuit-cooldown" data-i18n="settingsBasic.externalMcpCircuitCooldown">MCP 熔断冷却秒数</label>
                                            <input type="number" id="agent-external-mcp-circuit-cooldown" min="0" step="1" placeholder="60" />
                                            <small class="form-hint" data-i18n="settingsBasic.externalMcpCircuitCooldownHint">server 熔断后的等待时间；0 使用默认 60 秒。</small>
                                        </div>
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="multi-agent-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settingsBasic.enableMultiAgent">启用 Eino 多代理</span>
                                            </label>
                                            <small class="form-hint" data-i18n="settingsBasic.enableMultiAgentHint">开启后对话页可选「多代理」模式；子代理在 config.yaml 的 multi_agent.sub_agents 或 agents 目录中配置。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="multi-agent-pe-loop" data-i18n="settingsBasic.multiAgentPeLoop">plan_execute 外层循环上限</label>
                                            <input type="number" id="multi-agent-pe-loop" min="0" step="1" value="0" data-i18n="settingsBasic.multiAgentPeLoopPlaceholder" data-i18n-attr="placeholder" placeholder="0 表示 Eino 默认 10" />
                                            <small class="form-hint" data-i18n="settingsBasic.multiAgentPeLoopHint">仅 orchestration=plan_execute 时有效；execute 与 replan 之间的最大轮次。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="multi-agent-robot-mode" data-i18n="settingsBasic.multiAgentRobotMode">机器人默认对话模式</label>
                                            <select id="multi-agent-robot-mode" class="form-select">
                                                <option value="eino_single" data-i18n="chat.agentModeEinoSingle">Eino 单代理（ADK）</option>
                                                <option value="deep" data-i18n="chat.agentModeDeep">Deep（DeepAgent）</option>
                                                <option value="plan_execute" data-i18n="chat.agentModePlanExecuteLabel">Plan-Execute</option>
                                                <option value="supervisor" data-i18n="chat.agentModeSupervisorLabel">Supervisor</option>
                                            </select>
                                            <small class="form-hint" data-i18n="settingsBasic.multiAgentRobotModeHint">企业微信 / 钉钉 / 飞书机器人每条消息使用的执行模式；Deep / Plan-Execute / Supervisor 需启用多代理。</small>
                                        </div>
                                        <details class="settings-advanced-block">
                                            <summary data-i18n="settingsBasic.agentAdvanced">高级设置</summary>
                                            <div class="settings-form" style="margin-top: 0.75rem;">
                                                <div class="form-group">
                                                    <label for="eino-model-retry-max-retries" data-i18n="settingsBasic.einoModelRetryMaxRetries">Eino 原生模型最大重试次数</label>
                                                    <input type="number" id="eino-model-retry-max-retries" min="0" step="1" placeholder="0" />
                                                    <small class="form-hint" data-i18n="settingsBasic.einoModelRetryMaxRetriesHint">ChatModelAgent 原生 ModelRetry 次数；0 使用后端默认 4。用于 429/5xx/网络抖动和空模型输出。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="eino-model-retry-max-backoff-sec" data-i18n="settingsBasic.einoModelRetryMaxBackoffSec">Eino 原生模型最大退避秒数</label>
                                                    <input type="number" id="eino-model-retry-max-backoff-sec" min="0" step="1" placeholder="0" />
                                                    <small class="form-hint" data-i18n="settingsBasic.einoModelRetryMaxBackoffSecHint">模型原生重试的指数退避上限；0 使用后端默认 30 秒。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="eino-model-failover-channels" data-i18n="settingsBasic.einoModelFailoverChannels">Eino 模型 Failover 备用通道</label>
                                                    <textarea id="eino-model-failover-channels" rows="3" placeholder="backup-openai&#10;backup-claude" data-i18n="settingsBasic.einoModelFailoverChannelsPlaceholder" data-i18n-attr="placeholder"></textarea>
                                                    <small class="form-hint" data-i18n="settingsBasic.einoModelFailoverChannelsHint">主通道原生重试耗尽后按顺序切换 ai.channels 中的通道 ID；每行一个，也支持逗号分隔。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="eino-model-failover-max-retries" data-i18n="settingsBasic.einoModelFailoverMaxRetries">Eino 模型 Failover 最大切换次数</label>
                                                    <input type="number" id="eino-model-failover-max-retries" min="0" step="1" placeholder="0" />
                                                    <small class="form-hint" data-i18n="settingsBasic.einoModelFailoverMaxRetriesHint">0 表示尝试全部已配置备用通道；大于 0 时限制最多切换几个通道。</small>
                                                </div>
	                                                <div class="form-group">
	                                                    <label for="summarization-user-ledger-max-runes" data-i18n="settingsBasic.userLedgerMaxRunes">用户原文账本总字符上限</label>
	                                                    <input type="number" id="summarization-user-ledger-max-runes" min="0" step="1000" placeholder="96000" />
	                                                    <small class="form-hint" data-i18n="settingsBasic.userLedgerMaxRunesHint">压缩后注入模型上下文的原始用户输入账本总上限；0 使用后端默认值。DB 原始消息不裁剪。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="summarization-user-ledger-entry-max-runes" data-i18n="settingsBasic.userLedgerEntryMaxRunes">单条用户原文字符上限</label>
                                                    <input type="number" id="summarization-user-ledger-entry-max-runes" min="0" step="1000" placeholder="16000" />
                                                    <small class="form-hint" data-i18n="settingsBasic.userLedgerEntryMaxRunesHint">账本中单条用户消息的模型可见上限；0 使用后端默认值，不影响 DB 原文。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="latest-user-message-max-runes" data-i18n="settingsBasic.latestUserMaxRunes">最新用户输入字符上限</label>
                                                    <input type="number" id="latest-user-message-max-runes" min="0" step="1000" placeholder="48000" />
                                                    <small class="form-hint" data-i18n="settingsBasic.latestUserMaxRunesHint">本轮最新 user 进入模型上下文的上限；超出时全文落盘，只注入预览。0 使用后端默认值。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="latest-user-message-head-runes" data-i18n="settingsBasic.latestUserHeadRunes">最新用户输入头部预览</label>
                                                    <input type="number" id="latest-user-message-head-runes" min="0" step="1000" placeholder="24000" />
                                                    <small class="form-hint" data-i18n="settingsBasic.latestUserHeadRunesHint">超长最新 user 保留给模型看的头部字符数。</small>
                                                </div>
                                                <div class="form-group">
                                                    <label for="latest-user-message-tail-runes" data-i18n="settingsBasic.latestUserTailRunes">最新用户输入尾部预览</label>
                                                    <input type="number" id="latest-user-message-tail-runes" min="0" step="1000" placeholder="24000" />
                                                    <small class="form-hint" data-i18n="settingsBasic.latestUserTailRunesHint">超长最新 user 保留给模型看的尾部字符数。</small>
                                                </div>
                                            </div>
                                        </details>
                                    </div>
                                </div>
                                <div class="settings-actions">
                                    <button class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- 人机协同 -->
                            <div id="settings-section-hitl" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.hitl.title">人机协同</h3>
                                </div>

                                <div class="settings-subsection">
                                    <h4 data-i18n="settings.hitl.approvalTitle">审批配置</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="hitl-default-reviewer" data-i18n="settings.hitl.defaultReviewer">全局默认审批方</label>
                                            <select id="hitl-default-reviewer" class="form-select">
                                                <option value="human" data-i18n="chat.hitlReviewerHuman">人工审批</option>
                                                <option value="audit_agent" data-i18n="chat.hitlReviewerAgent">审计 Agent</option>
                                            </select>
                                            <small class="form-hint" data-i18n="settings.hitl.defaultReviewerHint">未选会话和新建会话默认使用该审批方；会话侧栏仍可临时覆盖。</small>
                                        </div>
                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settings.hitl.auditModelTitle">审计 Agent 模型</h5>
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-audit-model-provider" data-i18n="settingsBasic.apiProvider">API 提供商</label>
                                            <select id="hitl-audit-model-provider" class="form-select">
                                                <option value="" data-i18n="settings.hitl.auditModelReuseMain">跟随主模型配置</option>
                                                <option value="openai" data-i18n="settingsBasic.providerOpenAI">OpenAI / 兼容 OpenAI 协议</option>
                                                <option value="claude" data-i18n="settingsBasic.providerClaude">Claude (Anthropic Messages API)</option>
                                            </select>
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-audit-model-base-url">Base URL</label>
                                            <input type="text" id="hitl-audit-model-base-url" data-i18n="settings.hitl.auditModelBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用主模型 Base URL" />
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-audit-model-api-key">API Key</label>
                                            <input type="password" id="hitl-audit-model-api-key" data-i18n="settings.hitl.auditModelApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用主模型 API Key" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-audit-model-name" data-i18n="settings.hitl.auditModelName">审批模型</label>
                                            <div class="model-pick-row">
                                                <input type="text" id="hitl-audit-model-name" class="model-pick-input" data-i18n="settings.hitl.auditModelNamePlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用主模型；建议填写小模型" />
                                                <select id="hitl-audit-model-select" class="model-pick-native" style="display: none;" aria-hidden="true" tabindex="-1">
                                                    <option value="" disabled data-i18n="settingsBasic.modelsListSelectPlaceholder">请选择模型</option>
                                                </select>
                                                <a href="javascript:void(0)" id="fetch-hitl-audit-models-btn" class="model-pick-fetch-link" onclick="fetchModelList('hitlAudit')" data-i18n="settingsBasic.fetchModels">获取列表</a>
                                            </div>
                                            <small id="fetch-hitl-audit-models-hint" class="form-hint" style="display: none; font-size: 0.75rem; margin-top: 4px;"></small>
                                            <span id="fetch-hitl-audit-models-result" style="font-size: 0.75rem; margin-top: 2px; display: block;"></span>
                                            <small class="form-hint" data-i18n="settings.hitl.auditModelHint">仅审计 Agent 审批时使用；人工审批不消耗模型。</small>
                                        </div>
                                        <div style="display: flex; align-items: center; gap: 8px; margin-top: 2px;">
                                            <a href="javascript:void(0)" id="test-hitl-audit-model-btn" onclick="testHitlAuditModelConnection()" style="font-size: 0.8125rem; color: var(--accent-color, #3182ce); text-decoration: none; cursor: pointer; user-select: none;" data-i18n="settings.hitl.testAuditModel">测试审计模型</a>
                                            <span id="test-hitl-audit-model-result" style="font-size: 0.8125rem;"></span>
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-retention-days" data-i18n="settings.hitl.retentionDays">已决策审计日志保留天数</label>
                                            <input type="number" id="hitl-retention-days" min="0" step="1" placeholder="90" />
                                            <small class="form-hint" data-i18n="settings.hitl.retentionDaysHint">0 表示不自动清理；留空使用默认 90 天。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-tool-whitelist" data-i18n="settings.hitl.toolWhitelist">免审批工具白名单</label>
                                            <textarea id="hitl-tool-whitelist" rows="4" spellcheck="false" autocomplete="off" data-i18n="settings.hitl.toolWhitelistPlaceholder" data-i18n-attr="placeholder" placeholder="read_file, list_dir, glob"></textarea>
                                            <small class="form-hint" data-i18n="settings.hitl.toolWhitelistHint">每行一个或逗号分隔；白名单工具不会触发人机协同审批。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-subsection">
                                    <h4 data-i18n="settings.hitl.auditAgentTitle">审计 Agent 策略</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="hitl-audit-agent-prompt-settings" data-i18n="settings.hitl.auditPromptApproval">审批模式提示词</label>
                                            <textarea id="hitl-audit-agent-prompt-settings" rows="10" spellcheck="false" autocomplete="off"></textarea>
                                            <small class="form-hint" data-i18n="settings.hitl.auditPromptHint">留空时使用后端内置默认策略。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="hitl-audit-agent-prompt-review-edit-settings" data-i18n="settings.hitl.auditPromptReviewEdit">审查编辑模式提示词</label>
                                            <textarea id="hitl-audit-agent-prompt-review-edit-settings" rows="10" spellcheck="false" autocomplete="off"></textarea>
                                            <small class="form-hint" data-i18n="settings.hitl.auditPromptReviewEditHint">审查编辑模式可通过 editedArguments 收窄参数后放行。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-actions">
                                    <button type="button" class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- 资产管理设置 -->
                            <div id="settings-section-infocollect" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.infocollect.title">资产管理</h3>
                                </div>

                                <!-- FOFA配置 -->
                                <div class="settings-subsection">
                                    <h4 data-i18n="settingsBasic.fofaConfig">FOFA 配置</h4>
                                    <p class="form-hint" data-i18n="settingsBasic.fofaConfigHint">用于资产发现与导入，仅需配置 API Key。</p>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="fofa-base-url">Base URL</label>
                                            <input type="text" id="fofa-base-url" data-i18n="settingsBasic.fofaBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="https://fofa.info/api/v1/search/all（可选）" />
                                            <small class="form-hint" data-i18n="settingsBasic.fofaBaseUrlHint">留空则使用默认地址。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="fofa-api-key">API Key</label>
                                            <input type="password" id="fofa-api-key" data-i18n="settingsBasic.fofaApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="输入 FOFA API Key" autocomplete="off" />
                                            <small class="form-hint" data-i18n="settingsBasic.fofaApiKeyHint">仅保存在服务器配置中（`config.yaml`）。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-subsection">
                                    <h4>ZoomEye 配置</h4>
                                    <p class="form-hint">用于信息收集页调用 ZoomEye API；也可设置环境变量 ZOOMEYE_API_KEY。</p>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="zoomeye-base-url">Base URL</label>
                                            <input type="text" id="zoomeye-base-url" placeholder="https://api.zoomeye.ai/v2/search（可选）" />
                                            <small class="form-hint">留空则使用默认地址。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="zoomeye-api-key">API Key</label>
                                            <input type="password" id="zoomeye-api-key" placeholder="输入 ZoomEye API Key" autocomplete="off" />
                                            <small class="form-hint">仅保存在服务器配置中（config.yaml）。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-subsection">
                                    <h4>Quake 配置</h4>
                                    <p class="form-hint">用于信息收集页调用 360 Quake API；也可设置环境变量 QUAKE_API_KEY。</p>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="quake-base-url">Base URL</label>
                                            <input type="text" id="quake-base-url" placeholder="https://quake.360.net/api/v3/search/quake_service（可选）" />
                                            <small class="form-hint">留空则使用默认地址。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="quake-api-key">API Token</label>
                                            <input type="password" id="quake-api-key" placeholder="输入 Quake API Token" autocomplete="off" />
                                            <small class="form-hint">仅保存在服务器配置中（config.yaml）。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-subsection">
                                    <h4>Shodan 配置</h4>
                                    <p class="form-hint">用于信息收集页调用 Shodan API；也可设置环境变量 SHODAN_API_KEY。</p>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="shodan-base-url">Base URL</label>
                                            <input type="text" id="shodan-base-url" placeholder="https://api.shodan.io（可选）" />
                                            <small class="form-hint">留空则使用默认地址。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="shodan-api-key">API Key</label>
                                            <input type="password" id="shodan-api-key" placeholder="输入 Shodan API Key" autocomplete="off" />
                                            <small class="form-hint">仅保存在服务器配置中（config.yaml）。</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-actions">
                                    <button type="button" class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- 知识库设置 -->
                            <div id="settings-section-knowledge" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.knowledge.title">知识库设置</h3>
                                </div>

                                <div class="settings-subsection">
                                    <h4 data-i18n="settingsBasic.knowledgeConfig">知识库配置</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="knowledge-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settingsBasic.enableKnowledge">启用知识检索功能</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-base-path" data-i18n="settingsBasic.knowledgeBasePath">知识库路径</label>
                                            <input type="text" id="knowledge-base-path" data-i18n="settingsBasic.knowledgeBasePathPlaceholder" data-i18n-attr="placeholder" placeholder="knowledge_base" />
                                            <small class="form-hint" data-i18n="settingsBasic.knowledgeBasePathHint">相对于配置文件所在目录的路径</small>
                                        </div>

                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settingsBasic.embeddingConfig">嵌入模型配置</h5>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-embedding-provider" data-i18n="settingsBasic.provider">提供商</label>
                                            <select id="knowledge-embedding-provider">
                                                <option value="openai">OpenAI</option>
                                            </select>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-embedding-base-url">Base URL</label>
                                            <input type="text" id="knowledge-embedding-base-url" data-i18n="settingsBasic.embeddingBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="留空则使用OpenAI配置的base_url" />
                                            <small class="form-hint" data-i18n="settingsBasic.embeddingBaseUrlPlaceholder">留空则使用OpenAI配置的base_url</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-embedding-api-key">API Key</label>
                                            <input type="password" id="knowledge-embedding-api-key" data-i18n="settingsBasic.embeddingApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="留空则使用OpenAI配置的api_key" />
                                            <small class="form-hint" data-i18n="settingsBasic.embeddingApiKeyPlaceholder">留空则使用OpenAI配置的api_key</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-embedding-model" data-i18n="settingsBasic.modelName">模型名称</label>
                                            <div class="model-pick-row">
                                                <input type="text" id="knowledge-embedding-model" class="model-pick-input" data-i18n="settingsBasic.embeddingModelPlaceholder" data-i18n-attr="placeholder" placeholder="text-embedding-v4" />
                                                <select id="knowledge-embedding-model-select" class="model-pick-native" style="display: none;" aria-hidden="true" tabindex="-1">
                                                    <option value="" disabled data-i18n="settingsBasic.modelsListSelectPlaceholder">请选择模型</option>
                                                </select>
                                                <a href="javascript:void(0)" id="fetch-knowledge-embedding-models-btn" class="model-pick-fetch-link" onclick="fetchModelList('knowledgeEmbedding')" data-i18n="settingsBasic.fetchModels">获取列表</a>
                                            </div>
                                            <small id="fetch-knowledge-embedding-models-hint" class="form-hint" style="display: none; font-size: 0.75rem; margin-top: 4px;"></small>
                                            <span id="fetch-knowledge-embedding-models-result" style="font-size: 0.75rem; margin-top: 2px; display: block;"></span>
                                        </div>

                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settingsBasic.retrievalConfig">检索配置</h5>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-retrieval-top-k" data-i18n="settingsBasic.topK">Top-K 结果数量</label>
                                            <input type="number" id="knowledge-retrieval-top-k" min="1" max="20" data-i18n="settingsBasic.topKPlaceholder" data-i18n-attr="placeholder" placeholder="5" />
                                            <small class="form-hint" data-i18n="settingsBasic.topKHint">检索返回的Top-K结果数量</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-retrieval-similarity-threshold" data-i18n="settingsBasic.similarityThreshold">相似度阈值</label>
                                            <input type="number" id="knowledge-retrieval-similarity-threshold" min="0" max="1" step="0.1" data-i18n="settingsBasic.similarityPlaceholder" data-i18n-attr="placeholder" placeholder="0.7" />
                                            <small class="form-hint" data-i18n="settingsBasic.similarityHint">相似度阈值（0-1），低于此值的结果将被过滤</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-retrieval-sub-index-filter" data-i18n="settingsBasic.subIndexFilter">子索引过滤（可选）</label>
                                            <input type="text" id="knowledge-retrieval-sub-index-filter" data-i18n="settingsBasic.subIndexFilterPlaceholder" data-i18n-attr="placeholder" placeholder="与索引 sub_indexes 标签一致，如 prod" />
                                            <small class="form-hint" data-i18n="settingsBasic.subIndexFilterHint">留空表示不过滤；非空时仅检索 sub_indexes 含该标签的向量行（未打标旧数据仍会命中）。</small>
                                        </div>

                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settingsBasic.ragPipelineHeader">RAG 管线（MultiQuery + Rerank）</h5>
                                        </div>
                                        <p class="form-hint" style="margin: 0 0 12px 0;" data-i18n="settingsBasic.ragPipelineHint">MultiQuery 与精排始终启用：LLM 改写多路检索 → 向量预取与融合 → HTTP 精排 → 去重与预算截断。</p>
                                        <div class="form-group">
                                            <label for="knowledge-multi-query-max-queries" data-i18n="settingsBasic.multiQueryMaxQueries">MultiQuery 改写变体上限</label>
                                            <input type="number" id="knowledge-multi-query-max-queries" min="1" max="8" data-i18n="settingsBasic.multiQueryMaxQueriesPlaceholder" data-i18n-attr="placeholder" placeholder="4" />
                                            <small class="form-hint" data-i18n="settingsBasic.multiQueryMaxQueriesHint">LLM 生成的检索变体数量上限（含原问语义覆盖）；建议 3~4，最大 8。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-rerank-provider" data-i18n="settingsBasic.rerankProvider">精排提供商</label>
                                            <select id="knowledge-rerank-provider">
                                                <option value="" data-i18n="settingsBasic.rerankProviderAuto">自动（按 Base URL 推断）</option>
                                                <option value="dashscope">DashScope</option>
                                                <option value="cohere" data-i18n="settingsBasic.rerankProviderCohere">Cohere 兼容 API</option>
                                            </select>
                                            <small class="form-hint" data-i18n="settingsBasic.rerankProviderHint">DashScope 使用 gte-rerank；其他兼容端点走 /v1/rerank。留空时按下方 Base URL 自动推断。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-rerank-model" data-i18n="settingsBasic.rerankModel">精排模型（可选）</label>
                                            <input type="text" id="knowledge-rerank-model" data-i18n="settingsBasic.rerankModelPlaceholder" data-i18n-attr="placeholder" placeholder="留空：DashScope→gte-rerank，Cohere→rerank-multilingual-v3.0" />
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-rerank-base-url" data-i18n="settingsBasic.rerankBaseUrl">精排 Base URL（可选）</label>
                                            <input type="text" id="knowledge-rerank-base-url" data-i18n="settingsBasic.rerankBaseUrlPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用嵌入 / OpenAI 的 base_url" />
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-rerank-api-key" data-i18n="settingsBasic.rerankApiKey">精排 API Key（可选）</label>
                                            <input type="password" id="knowledge-rerank-api-key" data-i18n="settingsBasic.rerankApiKeyPlaceholder" data-i18n-attr="placeholder" placeholder="留空则复用嵌入 / OpenAI 的 api_key" />
                                            <small class="form-hint" data-i18n="settingsBasic.rerankApiKeyHint">精排失败时自动降级为融合排序，检索仍可用。</small>
                                        </div>

                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settingsBasic.postRetrieveHeader">检索后处理（去重 / 预算）</h5>
                                        </div>
                                        <p class="form-hint" style="margin: 0 0 12px 0;" data-i18n="settingsBasic.postRetrieveDedupeAuto">检索结果会自动按正文规范化去重（合并仅空白不同的重复片段），无需配置。</p>
                                        <div class="form-group">
                                            <label for="knowledge-post-retrieve-prefetch-top-k" data-i18n="settingsBasic.prefetchTopK">预取候选数（向量阶段）</label>
                                            <input type="number" id="knowledge-post-retrieve-prefetch-top-k" min="0" max="200" data-i18n="settingsBasic.prefetchTopKPlaceholder" data-i18n-attr="placeholder" placeholder="20" />
                                            <small class="form-hint" data-i18n="settingsBasic.prefetchTopKHint">每条 MultiQuery 变体的向量候选数；0 表示内置 max(top_k×4, 20)（上限 200）。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-post-retrieve-max-chars" data-i18n="settingsBasic.maxContextChars">返回内容最大字符数（Unicode）</label>
                                            <input type="number" id="knowledge-post-retrieve-max-chars" min="0" max="1000000" data-i18n="settingsBasic.maxContextCharsPlaceholder" data-i18n-attr="placeholder" placeholder="0" />
                                            <small class="form-hint" data-i18n="settingsBasic.maxContextCharsHint">0 表示不限制；按检索顺序整段保留 chunk，超出则丢弃后续。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-post-retrieve-max-tokens" data-i18n="settingsBasic.maxContextTokens">返回内容最大 Token 数</label>
                                            <input type="number" id="knowledge-post-retrieve-max-tokens" min="0" max="1000000" data-i18n="settingsBasic.maxContextTokensPlaceholder" data-i18n-attr="placeholder" placeholder="0" />
                                            <small class="form-hint" data-i18n="settingsBasic.maxContextTokensHint">0 表示不限制；tiktoken 估算（与嵌入模型名一致，失败则用 cl100k_base）。</small>
                                        </div>

                                        <div class="settings-subsection-header">
                                            <h5 data-i18n="settingsBasic.indexConfig">索引配置</h5>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-chunk-strategy" data-i18n="settingsBasic.chunkStrategy">分块策略</label>
                                            <select id="knowledge-indexing-chunk-strategy">
                                                <option value="markdown_then_recursive" data-i18n="settingsBasic.chunkStrategyMarkdownRecursive">Markdown 标题切分后递归（推荐）</option>
                                                <option value="recursive" data-i18n="settingsBasic.chunkStrategyRecursive">仅递归切分</option>
                                            </select>
                                            <small class="form-hint" data-i18n="settingsBasic.chunkStrategyHint">与 Eino 官方索引链一致：技术文档建议 Markdown 标题 + 递归；纯文本可仅用递归。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-request-timeout" data-i18n="settingsBasic.requestTimeoutSeconds">嵌入 HTTP 超时（秒）</label>
                                            <input type="number" id="knowledge-indexing-request-timeout" min="0" max="600" data-i18n="settingsBasic.requestTimeoutPlaceholder" data-i18n-attr="placeholder" placeholder="120" />
                                            <small class="form-hint" data-i18n="settingsBasic.requestTimeoutHint">0 表示使用默认 120 秒；与 OpenAI 嵌入客户端一致。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-batch-size" data-i18n="settingsBasic.batchSize">嵌入批大小</label>
                                            <input type="number" id="knowledge-indexing-batch-size" min="1" max="256" data-i18n="settingsBasic.batchSizePlaceholder" data-i18n-attr="placeholder" placeholder="64" />
                                            <small class="form-hint" data-i18n="settingsBasic.batchSizeHint">单次请求嵌入的文本条数上限（SQLite 索引写入分批）。</small>
                                        </div>
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="knowledge-indexing-prefer-source-file" />
                                                <span data-i18n="settingsBasic.preferSourceFile">索引时优先从磁盘源文件读取（Eino FileLoader）</span>
                                            </label>
                                            <small class="form-hint" data-i18n="settingsBasic.preferSourceFileHint">开启后以 file_path 为准；读取失败时回退数据库中的 content。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-sub-indexes" data-i18n="settingsBasic.subIndexes">Eino 子索引（逗号分隔）</label>
                                            <input type="text" id="knowledge-indexing-sub-indexes" data-i18n="settingsBasic.subIndexesPlaceholder" data-i18n-attr="placeholder" placeholder="例如: prod, knowledge" />
                                            <small class="form-hint" data-i18n="settingsBasic.subIndexesHint">传入 indexer.WithSubIndexes，写入向量行的 sub_indexes 字段（逻辑分区标记）。</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-chunk-size" data-i18n="settingsBasic.chunkSize">分块大小（Chunk Size）</label>
                                            <input type="number" id="knowledge-indexing-chunk-size" min="128" max="4096" data-i18n="settingsBasic.chunkSizePlaceholder" data-i18n-attr="placeholder" placeholder="512" />
                                            <small class="form-hint" data-i18n="settingsBasic.chunkSizeHint">每个块的最大 token 数（默认 512），长文本会被分割成多个块</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-chunk-overlap" data-i18n="settingsBasic.chunkOverlap">分块重叠（Chunk Overlap）</label>
                                            <input type="number" id="knowledge-indexing-chunk-overlap" min="0" max="512" data-i18n="settingsBasic.chunkOverlapPlaceholder" data-i18n-attr="placeholder" placeholder="50" />
                                            <small class="form-hint" data-i18n="settingsBasic.chunkOverlapHint">块之间的重叠 token 数（默认 50），保持上下文连贯性</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-max-chunks-per-item" data-i18n="settingsBasic.maxChunksPerItem">单个知识项最大块数</label>
                                            <input type="number" id="knowledge-indexing-max-chunks-per-item" min="0" max="1000" data-i18n="settingsBasic.maxChunksPlaceholder" data-i18n-attr="placeholder" placeholder="0" />
                                            <small class="form-hint" data-i18n="settingsBasic.maxChunksHint">单个知识项的最大块数量（0 表示不限制），防止单个文件消耗过多 API 配额</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-max-rpm" data-i18n="settingsBasic.maxRpm">每分钟最大请求数（Max RPM）</label>
                                            <input type="number" id="knowledge-indexing-max-rpm" min="0" max="1000" data-i18n="settingsBasic.maxRpmPlaceholder" data-i18n-attr="placeholder" placeholder="0" />
                                            <small class="form-hint" data-i18n="settingsBasic.maxRpmHint">每分钟最大请求数（默认 0 表示不限制），如 OpenAI 默认 200 RPM</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-rate-limit-delay-ms" data-i18n="settingsBasic.rateLimitDelay">请求间隔延迟（毫秒）</label>
                                            <input type="number" id="knowledge-indexing-rate-limit-delay-ms" min="0" max="10000" data-i18n="settingsBasic.rateLimitPlaceholder" data-i18n-attr="placeholder" placeholder="300" />
                                            <small class="form-hint" data-i18n="settingsBasic.rateLimitHint">请求间隔毫秒数（默认 300），用于避免 API 速率限制，设为 0 不限制</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-max-retries" data-i18n="settingsBasic.maxRetries">最大重试次数</label>
                                            <input type="number" id="knowledge-indexing-max-retries" min="0" max="10" data-i18n="settingsBasic.maxRetriesPlaceholder" data-i18n-attr="placeholder" placeholder="3" />
                                            <small class="form-hint" data-i18n="settingsBasic.maxRetriesHint">最大重试次数（默认 3），遇到速率限制或服务器错误时自动重试</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="knowledge-indexing-retry-delay-ms" data-i18n="settingsBasic.retryDelay">重试间隔（毫秒）</label>
                                            <input type="number" id="knowledge-indexing-retry-delay-ms" min="0" max="10000" data-i18n="settingsBasic.retryDelayPlaceholder" data-i18n-attr="placeholder" placeholder="1000" />
                                            <small class="form-hint" data-i18n="settingsBasic.retryDelayHint">重试间隔毫秒数（默认 1000），每次重试会递增延迟</small>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-actions">
                                    <button class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- C2 总开关 -->
                            <div id="settings-section-c2" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.c2.title">C2 设置</h3>
                                </div>
                                <div class="settings-subsection">
                                    <h4 data-i18n="settings.c2.sectionTitle">内置 C2</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="c2-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.c2.enableLabel">启用内置 C2（监听器、会话、Payload、MCP 工具等）</span>
                                            </label>
                                            <small class="form-hint" data-i18n="settings.c2.enableHint">关闭后不再启动监听器、不注册 C2 相关 MCP 工具，侧栏 C2 入口将隐藏；仅本机使用对话与知识库时可关闭以节省资源。</small>
                                        </div>
                                    </div>
                                </div>
                                <div class="settings-actions">
                                    <button class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- 机器人设置 -->
                            <div id="settings-section-robots" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.robots.title">机器人设置</h3>
                                    <p class="settings-description" data-i18n="settings.robots.description">配置企业微信、钉钉、飞书等机器人，在手机端直接与 CyberStrikeAI 对话，无需在服务器上打开网页。</p>
                                </div>

                                <div class="robot-manager">
                                    <div class="robot-manager-toolbar">
                                        <div>
                                            <h4 data-i18n="settings.robots.managerTitle">机器人管理</h4>
                                            <p data-i18n="settings.robots.managerDesc">先选择机器人类型，再进入对应配置；已配置的平台会显示连接状态。</p>
                                        </div>
                                        <button type="button" class="btn-primary" data-require-permission="robot:write" onclick="openRobotCreateModal()" data-i18n="settings.robots.newBot">新建机器人</button>
                                    </div>

                                    <div class="robot-card-grid">
                                        <button type="button" class="robot-card" data-robot-card="wechat" data-require-permission="robot:write" onclick="openRobotEditor('wechat')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.wechat.title">微信 / iLink</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.wechat.subtitle">扫码绑定个人微信，在手机端直接与 CyberStrikeAI 对话</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-wechat-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="wecom" data-require-permission="robot:write" onclick="openRobotEditor('wecom')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.wecom.title">企业微信</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.wecom.subtitle">HTTP 回调模式，适合企业内部应用机器人</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-wecom-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="dingtalk" data-require-permission="robot:write" onclick="openRobotEditor('dingtalk')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.dingtalk.title">钉钉</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.dingtalk.subtitle">企业内部应用机器人，使用 Stream 长连接</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-dingtalk-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="lark" data-require-permission="robot:write" onclick="openRobotEditor('lark')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.lark.title">飞书 (Lark)</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.lark.subtitle">飞书企业应用机器人，支持单聊与群聊 @</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-lark-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="telegram" data-require-permission="robot:write" onclick="openRobotEditor('telegram')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.telegram.title">Telegram</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.telegram.subtitle">Bot API 长轮询，私聊与群聊 @</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-telegram-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="slack" data-require-permission="robot:write" onclick="openRobotEditor('slack')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.slack.title">Slack</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.slack.subtitle">Socket Mode，无需公网回调</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-slack-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="discord" data-require-permission="robot:write" onclick="openRobotEditor('discord')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.discord.title">Discord</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.discord.subtitle">Gateway WebSocket，私聊与服务器 @</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-discord-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                        <button type="button" class="robot-card" data-robot-card="qq" data-require-permission="robot:write" onclick="openRobotEditor('qq')">
                                            <span class="robot-card-main">
                                                <span class="robot-card-title" data-i18n="settings.robots.qq.title">QQ 机器人</span>
                                                <span class="robot-card-desc" data-i18n="settings.robots.qq.subtitle">QQ 开放平台 WebSocket，C2C 与群 @</span>
                                            </span>
                                            <span class="robot-card-meta">
                                                <span id="robot-card-qq-status" class="robot-status-pill robot-status-pill--idle" data-i18n="settings.robots.statusNotConfigured">未配置</span>
                                                <span class="robot-card-action" data-i18n="settings.robots.configure">配置</span>
                                            </span>
                                        </button>
                                    </div>

									<div class="vulnerability-alert-settings" id="vulnerability-alert-settings">
										<div class="vulnerability-alert-header">
											<div class="vulnerability-alert-copy">
												<span class="vulnerability-alert-icon" aria-hidden="true"><svg width="18" height="18" viewBox="0 0 24 24" fill="none"><path d="M18 8a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round"/><path d="M10 21h4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>
												<div>
													<strong data-i18n="vulnerabilityPage.alertTitle">机器人漏洞提醒</strong>
													<span data-i18n="vulnerabilityPage.alertDescription">按严重级别将新发现的漏洞推送至当前账号绑定的机器人。</span>
												</div>
											</div>
											<label class="vulnerability-alert-switch">
												<input type="checkbox" id="vulnerability-alert-enabled" onchange="saveVulnerabilityAlertSubscription()" />
												<span class="vulnerability-alert-switch-track" aria-hidden="true"></span>
												<span class="vulnerability-alert-switch-label" data-i18n="vulnerabilityPage.alertEnabled">启用提醒</span>
											</label>
										</div>
										<div class="vulnerability-alert-controls">
											<label class="vulnerability-alert-field" for="vulnerability-alert-min-severity">
												<span data-i18n="vulnerabilityPage.alertMinimum">最低级别</span>
												<select id="vulnerability-alert-min-severity" style="width: 168px; min-width: 168px" onchange="saveVulnerabilityAlertSubscription()">
													<option value="critical" data-i18n="dashboard.severityCritical">严重</option>
													<option value="high" data-i18n="dashboard.severityHigh">高危</option>
													<option value="medium" data-i18n="dashboard.severityMedium">中危</option>
													<option value="low" data-i18n="dashboard.severityLow">低危</option>
													<option value="info" data-i18n="dashboard.severityInfo">信息</option>
												</select>
											</label>
											<div class="vulnerability-alert-binding-row">
												<span id="vulnerability-alert-binding-hint" data-i18n="vulnerabilityPage.alertHint">发现符合级别的新漏洞后，通过已绑定机器人账号推送。</span>
												<button type="button" class="vulnerability-alert-bind-button" id="vulnerability-alert-bind-button" onclick="openRobotAccountBinding()" hidden data-i18n="vulnerabilityPage.alertBindAction">绑定接收账号</button>
											</div>
										</div>
									</div>
                                </div>

                                <div id="robot-editor-empty" class="robot-editor-empty">
                                    <h4 data-i18n="settings.robots.emptyTitle">选择一个机器人开始配置</h4>
                                    <p data-i18n="settings.robots.emptyDesc">从上方列表点击已有平台，或点击“新建机器人”按类型创建。</p>
                                </div>

                                <div id="robot-auth-policy-panel" class="settings-subsection" hidden>
                                    <h4>业务鉴权策略</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="robot-auth-mode">鉴权模式</label>
                                            <select id="robot-auth-mode" class="form-select" onchange="onRobotAuthModeChange()">
                                                <option value="user_binding">逐用户绑定（多人机器人推荐）</option>
                                                <option value="service_account">专用服务账号（仅白名单发送者）</option>
                                            </select>
                                            <small class="form-hint">平台验签负责确认消息来源；这里决定消息最终使用哪个 RBAC 身份。</small>
                                        </div>
                                        <div id="robot-service-account-fields" hidden>
                                            <div class="form-group">
                                                <label for="robot-service-user-id">服务账号 RBAC User ID</label>
                                                <input type="text" id="robot-service-user-id" placeholder="例如 admin 或专用服务账号 User ID" autocomplete="off" oninput="updateRobotServiceAccountWarning()" />
                                                <small id="robot-service-admin-warning" class="form-hint robot-service-admin-warning" hidden>当前使用 admin：白名单发送者将拥有完整平台权限，请仅添加你完全信任的账号。</small>
                                            </div>
                                            <div class="form-group">
                                                <label for="robot-allowed-external-users">允许的平台发送者 ID</label>
                                                <textarea id="robot-allowed-external-users" rows="4" placeholder="每行一个；在机器人中发送“身份”或 whoami 获取"></textarea>
                                                <small class="form-hint">不支持 * 通配符。服务账号模式只有这里列出的真实发送者可以执行。</small>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <!-- 微信 / iLink -->
                                <div class="settings-subsection robot-editor-panel robot-wechat-card" id="robot-wechat-subsection" data-robot-editor="wechat" hidden>
                                    <div class="robot-wechat-header">
                                        <div class="robot-wechat-header-text">
                                            <h4 data-i18n="settings.robots.wechat.title">微信 / iLink</h4>
                                            <p class="robot-wechat-subtitle" data-i18n="settings.robots.wechat.subtitle">扫码绑定个人微信，在手机端直接与 CyberStrikeAI 对话</p>
                                        </div>
                                        <span id="robot-wechat-status-badge" class="robot-wechat-badge robot-wechat-badge--idle" data-i18n="settings.robots.wechat.statusIdle">未绑定</span>
                                    </div>
                                    <div class="settings-form robot-wechat-form">
                                        <div class="robot-wechat-toolbar">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-wechat-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.wechat.enabled">启用微信机器人</span>
                                            </label>
                                        </div>
                                        <div class="robot-wechat-action-row">
                                            <button type="button" class="btn-primary" data-require-permission="robot:write" id="robot-wechat-bind-btn" onclick="startWechatRobotBind()" data-i18n="settings.robots.wechat.bindButton">生成二维码并绑定</button>
                                            <p class="robot-wechat-hint" id="robot-wechat-bind-hint" data-i18n="settings.robots.wechat.bindHint">用微信扫码确认后会自动保存并启用。</p>
                                        </div>
                                        <div id="robot-wechat-bound-flash" class="robot-wechat-bound-flash" hidden role="status">
                                            <span class="robot-wechat-bound-flash-icon" aria-hidden="true">
                                                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
                                            </span>
                                            <span id="robot-wechat-bound-flash-text" data-i18n="settings.robots.wechat.boundSuccess">绑定成功，微信机器人已启用。</span>
                                        </div>
                                        <p id="robot-wechat-bound-summary" class="robot-wechat-bound-summary" hidden></p>
                                        <div id="robot-wechat-qr-wrap" class="robot-wechat-panel" hidden>
                                            <div id="robot-wechat-bound-panel" class="robot-wechat-bound-panel" hidden>
                                                <div class="robot-wechat-bound-icon" aria-hidden="true">
                                                    <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></svg>
                                                </div>
                                                <p class="robot-wechat-bound-msg" data-i18n="settings.robots.wechat.boundSuccess">绑定成功，微信机器人已启用</p>
                                                <p id="robot-wechat-bound-id" class="robot-wechat-bound-id" hidden></p>
                                            </div>
                                            <div id="robot-wechat-scan-panel" class="robot-wechat-scan-panel" hidden>
                                            <div id="robot-wechat-qr-loading" class="robot-wechat-qr-loading" hidden data-i18n="settings.robots.wechat.qrLoading">正在生成二维码…</div>
                                            <img id="robot-wechat-qr-img" class="robot-wechat-qr-img" alt="" width="220" height="220" hidden />
                                            <p class="robot-wechat-qr-fallback">
                                                <a id="robot-wechat-qr-link" href="#" target="_blank" rel="noopener noreferrer" hidden data-i18n="settings.robots.wechat.openLink">无法显示二维码？点击用手机微信打开链接</a>
                                            </p>
                                            <p id="robot-wechat-qr-status" class="robot-wechat-qr-status"></p>
                                            <div id="robot-wechat-verify-wrap" class="robot-wechat-verify-wrap" hidden>
                                                <label for="robot-wechat-verify-code" data-i18n="settings.robots.wechat.verifyCodeLabel">手机显示的数字（仅部分账号需要）</label>
                                                <div class="robot-wechat-verify-row">
                                                    <input type="text" id="robot-wechat-verify-code" inputmode="numeric" autocomplete="one-time-code" maxlength="8" placeholder="000000" />
                                                    <button type="button" class="btn-primary btn-sm" data-require-permission="robot:write" onclick="submitWechatVerifyCode()" data-i18n="settings.robots.wechat.verifyCodeSubmit">提交</button>
                                                </div>
                                            </div>
                                            </div>
                                        </div>
                                        <details class="settings-collapsible robot-wechat-advanced" id="robot-wechat-advanced">
                                            <summary data-i18n="settings.robots.wechat.advanced">高级设置</summary>
                                            <div class="form-group">
                                                <label for="robot-wechat-base-url" data-i18n="settings.robots.wechat.baseUrl">API Base URL</label>
                                                <input type="text" id="robot-wechat-base-url" placeholder="https://ilinkai.weixin.qq.com" autocomplete="off" />
                                            </div>
                                            <div class="form-group">
                                                <label for="robot-wechat-bot-type" data-i18n="settings.robots.wechat.botType">Bot Type</label>
                                                <input type="text" id="robot-wechat-bot-type" placeholder="3" autocomplete="off" />
                                            </div>
                                            <div class="form-group">
                                                <label for="robot-wechat-bot-agent" data-i18n="settings.robots.wechat.botAgent">Bot Agent</label>
                                                <input type="text" id="robot-wechat-bot-agent" placeholder="CyberStrikeAI/1.0" autocomplete="off" />
                                            </div>
                                            <div class="form-group">
                                                <label for="robot-wechat-ilink-bot-id" data-i18n="settings.robots.wechat.ilinkBotId">iLink Bot ID（绑定后自动填充）</label>
                                                <input type="text" id="robot-wechat-ilink-bot-id" readonly autocomplete="off" />
                                            </div>
                                        </details>
                                    </div>
                                </div>

                                <!-- 企业微信 -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="wecom" hidden>
                                    <h4 data-i18n="settings.robots.wecom.title">企业微信</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-wecom-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.wecom.enabled">启用企业微信机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-wecom-token" data-i18n="settings.robots.wecom.token">Token</label>
                                            <input type="text" id="robot-wecom-token" data-i18n="settings.robots.wecom.tokenPlaceholder" data-i18n-attr="placeholder" placeholder="Token" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-wecom-encoding-aes-key" data-i18n="settings.robots.wecom.encodingAesKey">EncodingAESKey</label>
                                            <input type="text" id="robot-wecom-encoding-aes-key" data-i18n="settings.robots.wecom.encodingAesKeyPlaceholder" data-i18n-attr="placeholder" placeholder="EncodingAESKey（明文模式可留空）" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-wecom-corp-id" data-i18n="settings.robots.wecom.corpId">CorpID</label>
                                            <input type="text" id="robot-wecom-corp-id" data-i18n="settings.robots.wecom.corpIdPlaceholder" data-i18n-attr="placeholder" placeholder="企业 ID" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-wecom-secret" data-i18n="settings.robots.wecom.secret">Secret</label>
                                            <input type="password" id="robot-wecom-secret" data-i18n="settings.robots.wecom.secretPlaceholder" data-i18n-attr="placeholder" placeholder="应用 Secret" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-wecom-agent-id" data-i18n="settings.robots.wecom.agentId">AgentID</label>
                                            <input type="number" id="robot-wecom-agent-id" data-i18n="settings.robots.wecom.agentIdPlaceholder" data-i18n-attr="placeholder" placeholder="应用 AgentId" />
                                        </div>
                                    </div>
                                </div>

                                <!-- 钉钉 -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="dingtalk" hidden>
                                    <h4 data-i18n="settings.robots.dingtalk.title">钉钉</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-dingtalk-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.dingtalk.enabled">启用钉钉机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-dingtalk-client-id" data-i18n="settings.robots.dingtalk.clientIdLabel">Client ID (AppKey)</label>
                                            <input type="text" id="robot-dingtalk-client-id" data-i18n="settings.robots.dingtalk.clientIdPlaceholder" data-i18n-attr="placeholder" placeholder="钉钉应用 AppKey" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-dingtalk-client-secret" data-i18n="settings.robots.dingtalk.clientSecretLabel">Client Secret</label>
                                            <input type="password" id="robot-dingtalk-client-secret" data-i18n="settings.robots.dingtalk.clientSecretPlaceholder" data-i18n-attr="placeholder" placeholder="钉钉应用 Secret" autocomplete="off" />
                                            <small class="form-hint" data-i18n="settings.robots.dingtalk.streamHint">需开启机器人能力并配置流式接入</small>
                                        </div>
                                    </div>
                                </div>

                                <!-- 飞书 -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="lark" hidden>
                                    <h4 data-i18n="settings.robots.lark.title">飞书 (Lark)</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-lark-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.lark.enabled">启用飞书机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-lark-app-id" data-i18n="settings.robots.lark.appIdLabel">App ID</label>
                                            <input type="text" id="robot-lark-app-id" data-i18n="settings.robots.lark.appIdPlaceholder" data-i18n-attr="placeholder" placeholder="飞书应用 App ID" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-lark-app-secret" data-i18n="settings.robots.lark.appSecretLabel">App Secret</label>
                                            <input type="password" id="robot-lark-app-secret" data-i18n="settings.robots.lark.appSecretPlaceholder" data-i18n-attr="placeholder" placeholder="飞书应用 App Secret" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-lark-verify-token" data-i18n="settings.robots.lark.verifyTokenLabel">Verify Token（可选）</label>
                                            <input type="text" id="robot-lark-verify-token" data-i18n="settings.robots.lark.verifyTokenPlaceholder" data-i18n-attr="placeholder" placeholder="事件订阅 Verification Token" autocomplete="off" />
                                        </div>
                                    </div>
                                </div>

                                <!-- Telegram -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="telegram" hidden>
                                    <h4 data-i18n="settings.robots.telegram.title">Telegram</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-telegram-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.telegram.enabled">启用 Telegram 机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-telegram-bot-token" data-i18n="settings.robots.telegram.botToken">Bot Token</label>
                                            <input type="password" id="robot-telegram-bot-token" autocomplete="off" placeholder="从 @BotFather 获取" />
                                            <small class="form-hint" data-i18n="settings.robots.telegram.botTokenHint">通过 getUpdates 长轮询收消息，无需公网回调</small>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-telegram-bot-username" data-i18n="settings.robots.telegram.botUsername">Bot Username（可选）</label>
                                            <input type="text" id="robot-telegram-bot-username" autocomplete="off" placeholder="不含 @，留空则自动 getMe" />
                                        </div>
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-telegram-allow-group" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.telegram.allowGroup">允许群聊（仅响应 @ 机器人）</span>
                                            </label>
                                        </div>
                                    </div>
                                </div>

                                <!-- Slack -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="slack" hidden>
                                    <h4 data-i18n="settings.robots.slack.title">Slack</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-slack-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.slack.enabled">启用 Slack 机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-slack-bot-token" data-i18n="settings.robots.slack.botToken">Bot Token (xoxb-)</label>
                                            <input type="password" id="robot-slack-bot-token" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-slack-app-token" data-i18n="settings.robots.slack.appToken">App-Level Token (xapp-)</label>
                                            <input type="password" id="robot-slack-app-token" autocomplete="off" />
                                            <small class="form-hint" data-i18n="settings.robots.slack.appTokenHint">需 connections:write 权限，用于 Socket Mode</small>
                                        </div>
                                    </div>
                                </div>

                                <!-- Discord -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="discord" hidden>
                                    <h4 data-i18n="settings.robots.discord.title">Discord</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-discord-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.discord.enabled">启用 Discord 机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-discord-bot-token" data-i18n="settings.robots.discord.botToken">Bot Token</label>
                                            <input type="password" id="robot-discord-bot-token" autocomplete="off" />
                                            <small class="form-hint" data-i18n="settings.robots.discord.botTokenHint">开发者门户创建 Bot，开启 Message Content Intent</small>
                                        </div>
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-discord-allow-guild" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.discord.allowGuild">允许服务器频道（仅响应 @ 机器人）</span>
                                            </label>
                                        </div>
                                    </div>
                                </div>

                                <!-- QQ -->
                                <div class="settings-subsection robot-editor-panel" data-robot-editor="qq" hidden>
                                    <h4 data-i18n="settings.robots.qq.title">QQ 机器人</h4>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-qq-enabled" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.qq.enabled">启用 QQ 机器人</span>
                                            </label>
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-qq-app-id" data-i18n="settings.robots.qq.appId">App ID</label>
                                            <input type="text" id="robot-qq-app-id" autocomplete="off" />
                                        </div>
                                        <div class="form-group">
                                            <label for="robot-qq-client-secret" data-i18n="settings.robots.qq.clientSecret">Client Secret</label>
                                            <input type="password" id="robot-qq-client-secret" autocomplete="off" />
                                            <small class="form-hint" data-i18n="settings.robots.qq.secretHint">从 QQ 机器人开放平台获取；上线前可勾选沙箱</small>
                                        </div>
                                        <div class="form-group">
                                            <label class="checkbox-label">
                                                <input type="checkbox" id="robot-qq-sandbox" class="modern-checkbox" />
                                                <span class="checkbox-custom"></span>
                                                <span class="checkbox-text" data-i18n="settings.robots.qq.sandbox">沙箱环境</span>
                                            </label>
                                        </div>
                                    </div>
                                </div>

                                <div id="robot-create-modal" class="modal" role="dialog" aria-modal="true" aria-labelledby="robot-create-title">
                                    <div class="modal-content robot-create-modal-content">
                                        <div class="modal-header">
                                            <h2 id="robot-create-title" data-i18n="settings.robots.createTitle">新建机器人</h2>
                                            <button type="button" class="modal-close" onclick="closeRobotCreateModal()" aria-label="Close"></button>
                                        </div>
                                        <div class="modal-body">
                                            <p class="settings-description" data-i18n="settings.robots.createDesc">选择机器人类型后进入专属配置。当前版本每个平台支持一个内置机器人配置。</p>
                                            <div class="robot-type-grid">
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('wechat')">
                                                    <span data-i18n="settings.robots.wechat.title">微信 / iLink</span>
                                                    <small data-i18n="settings.robots.wechat.subtitle">扫码绑定个人微信</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('wecom')">
                                                    <span data-i18n="settings.robots.wecom.title">企业微信</span>
                                                    <small data-i18n="settings.robots.wecom.subtitle">HTTP 回调模式</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('dingtalk')">
                                                    <span data-i18n="settings.robots.dingtalk.title">钉钉</span>
                                                    <small data-i18n="settings.robots.dingtalk.subtitle">Stream 长连接</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('lark')">
                                                    <span data-i18n="settings.robots.lark.title">飞书 (Lark)</span>
                                                    <small data-i18n="settings.robots.lark.subtitle">企业应用机器人</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('telegram')">
                                                    <span data-i18n="settings.robots.telegram.title">Telegram</span>
                                                    <small data-i18n="settings.robots.telegram.subtitle">Bot API 长轮询</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('slack')">
                                                    <span data-i18n="settings.robots.slack.title">Slack</span>
                                                    <small data-i18n="settings.robots.slack.subtitle">Socket Mode</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('discord')">
                                                    <span data-i18n="settings.robots.discord.title">Discord</span>
                                                    <small data-i18n="settings.robots.discord.subtitle">Gateway WebSocket</small>
                                                </button>
                                                <button type="button" class="robot-type-option" onclick="selectRobotType('qq')">
                                                    <span data-i18n="settings.robots.qq.title">QQ 机器人</span>
                                                    <small data-i18n="settings.robots.qq.subtitle">QQ 开放平台</small>
                                                </button>
                                            </div>
                                        </div>
                                    </div>
                                </div>

                                <div id="robot-commands-modal" class="modal" role="dialog" aria-modal="true" aria-labelledby="robot-commands-title">
                                    <div class="modal-content robot-commands-modal-content">
                                        <div class="modal-header">
                                            <h2 id="robot-commands-title" data-i18n="settingsRobotsExtra.botCommandsTitle">机器人命令说明</h2>
                                            <button type="button" class="modal-close" onclick="closeRobotCommandsModal()" aria-label="Close"></button>
                                        </div>
                                        <div class="modal-body robot-commands-modal-body">
                                            <p class="settings-description" data-i18n="settingsRobotsExtra.botCommandsDesc">在对话中可发送以下命令（支持中英文）：</p>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryGeneral">通用</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>帮助</code> <code>help</code> — <span data-i18n="settingsRobotsExtra.botCmdHelp">显示本帮助 | Show this help</span></li>
                                                <li><code>版本</code> <code>version</code> — <span data-i18n="settingsRobotsExtra.botCmdVersion">显示当前版本号 | Show version</span></li>
                                            </ul>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryIdentity">身份与鉴权</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>身份</code> <code>whoami</code> — <span data-i18n="settingsRobotsExtra.botCmdIdentity">显示平台发送者、鉴权模式及当前实际 RBAC 身份 | Show effective identity</span></li>
                                                <li><code>绑定 &lt;绑定码&gt;</code> <code>bind &lt;code&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdBindUser">绑定当前平台账号到 RBAC 用户（仅逐用户绑定模式） | Bind RBAC user</span></li>
                                                <li><code>解绑</code> <code>unbind</code> — <span data-i18n="settingsRobotsExtra.botCmdUnbindUser">解除当前平台账号绑定（仅逐用户绑定模式，需确认） | Unbind RBAC user</span></li>
                                            </ul>
                                            <p class="settings-description" data-i18n="settingsRobotsExtra.botAuthHint">专用服务账号模式不接受“绑定/解绑”命令，仅允许机器人配置中白名单内的发送者。</p>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryConversation">对话</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>列表</code> <code>list</code> — <span data-i18n="settingsRobotsExtra.botCmdList">列出所有对话标题与 ID | List conversations</span></li>
                                                <li><code>切换 &lt;ID&gt;</code> <code>switch &lt;ID&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdSwitch">指定对话继续 | Switch to conversation</span></li>
                                                <li><code>新对话</code> <code>new</code> — <span data-i18n="settingsRobotsExtra.botCmdNew">开启新对话 | Start new conversation</span></li>
                                                <li><code>清空</code> <code>clear</code> — <span data-i18n="settingsRobotsExtra.botCmdClear">清空当前上下文 | Clear context</span></li>
                                                <li><code>状态</code> <code>status</code> — <span data-i18n="settingsRobotsExtra.botCmdStatus">汇总当前对话、模式、角色与项目 | Show current status</span></li>
                                                <li><code>任务</code> <code>task</code> — <span data-i18n="settingsRobotsExtra.botCmdTask">查看当前任务状态与运行时长 | Show current task</span></li>
                                                <li><code>重命名 &lt;名称&gt;</code> <code>rename &lt;name&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdRename">修改当前对话标题 | Rename conversation</span></li>
                                                <li><code>停止</code> <code>stop</code> — <span data-i18n="settingsRobotsExtra.botCmdStop">中断当前任务 | Stop running task</span></li>
                                                <li><code>删除 &lt;ID&gt;</code> <code>delete &lt;ID&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdDelete">删除指定对话（需确认） | Delete conversation</span></li>
                                            </ul>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryRole">角色</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>角色</code> <code>roles</code> — <span data-i18n="settingsRobotsExtra.botCmdRoles">列出所有可用角色 | List roles</span></li>
                                                <li><code>角色 &lt;名&gt;</code> <code>role &lt;name&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdRole">切换当前角色 | Switch role</span></li>
                                            </ul>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryMode">模式</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>模式</code> <code>modes</code> — <span data-i18n="settingsRobotsExtra.botCmdModes">列出对话模式与当前选择 | List conversation modes</span></li>
                                                <li><code>模式 &lt;名称&gt;</code> <code>mode &lt;name&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdMode">切换对话模式 | Switch conversation mode</span></li>
                                            </ul>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryProject">项目</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>项目</code> <code>projects</code> — <span data-i18n="settingsRobotsExtra.botCmdProjects">列出所有项目 | List projects</span></li>
                                                <li><code>新建项目 &lt;名称&gt;</code> <code>new project &lt;name&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdNewProject">创建项目并绑定当前对话 | Create &amp; bind project</span></li>
                                                <li><code>绑定项目 &lt;ID或名称&gt;</code> <code>bind project &lt;ID|name&gt;</code> — <span data-i18n="settingsRobotsExtra.botCmdBindProject">将当前对话绑定到项目 | Bind conversation</span></li>
                                                <li><code>解除项目</code> <code>unbind project</code> — <span data-i18n="settingsRobotsExtra.botCmdUnbindProject">解除当前对话的项目绑定 | Unbind project</span></li>
                                            </ul>

                                            <p class="robot-cmd-category" data-i18n="settingsRobotsExtra.botCmdCategoryDiagnostics">诊断与安全</p>
                                            <ul class="robot-cmd-list">
                                                <li><code>权限</code> <code>permissions</code> — <span data-i18n="settingsRobotsExtra.botCmdPermissions">查看当前业务权限 | Show effective permissions</span></li>
                                                <li><code>诊断</code> <code>doctor</code> — <span data-i18n="settingsRobotsExtra.botCmdDoctor">检查关键配置状态 | Check configuration status</span></li>
                                                <li><code>确认</code> <code>confirm</code> / <code>取消</code> <code>cancel</code> — <span data-i18n="settingsRobotsExtra.botCmdConfirmation">确认或取消高风险操作 | Confirm or cancel risky action</span></li>
                                            </ul>

                                            <p class="settings-description robot-cmd-footer" data-i18n="settingsRobotsExtra.botCommandsFooter">除以上命令外，直接输入内容将按绑定用户或服务账号的实时 RBAC 权限发送给 AI。Otherwise, text is sent to AI under the effective RBAC identity.</p>
                                        </div>
                                    </div>
                                </div>

                                <div class="settings-subsection robot-command-entry">
                                    <div class="robot-command-entry-copy">
                                        <h4 data-i18n="settingsRobotsExtra.botCommandsTitle">机器人命令说明</h4>
                                        <p class="settings-description" data-i18n="settingsRobotsExtra.botCommandsEntryDesc">查看机器人对话中可用的中英文命令，包括身份鉴权、对话、角色、模式、项目和安全诊断。</p>
                                    </div>
                                    <button type="button" class="btn-secondary" onclick="openRobotCommandsModal()" data-i18n="settingsRobotsExtra.viewAllCommands">查看全部命令</button>
                                </div>

                                <div class="settings-actions">
                                    <button class="btn-primary" onclick="applySettings()" data-require-permission="config:write" data-i18n="settings.apply.button">应用配置</button>
                                </div>
                            </div>

                            <!-- 终端 -->
                            <div id="settings-section-terminal" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settingsTerminal.title">终端</h3>
                                    <p class="settings-description" data-i18n="settingsTerminal.description">在服务器上执行命令，便于运维与调试。命令在服务端执行，请勿执行敏感或破坏性操作。</p>
                                </div>
                                <div class="terminal-wrapper">
                                    <div class="terminal-tabs">
                                        <div class="terminal-tab active" data-tab-id="1"><span class="terminal-tab-label" onclick="switchTerminalTab(1)">终端 1</span><button type="button" class="terminal-tab-close" onclick="removeTerminalTab(1); event.stopPropagation();" data-i18n="settingsTerminal.close" data-i18n-attr="title" title="关闭">×</button></div>
                                        <button type="button" class="terminal-tab-new" onclick="addTerminalTab()" data-i18n="settingsTerminal.newTerminal" data-i18n-attr="title" title="新终端">+</button>
                                    </div>
                                    <div class="terminal-panes">
                                        <div id="terminal-pane-1" class="terminal-pane active">
                                            <div id="terminal-container-1" class="terminal-container"></div>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <!-- 日志审计 -->
                            <div id="settings-section-audit" class="settings-section-content">
                                <div class="audit-section-head">
                                    <h3 data-i18n="settingsAudit.title">日志审计</h3>
                                    <div id="audit-summary-stats" class="audit-summary-tags" hidden>
                                        <span class="audit-summary-tag"><span class="audit-summary-tag-label" data-i18n="settingsAudit.statTotal">当前筛选</span><strong id="audit-stat-total">0</strong></span>
                                        <span class="audit-summary-tag audit-summary-tag--ok"><span class="audit-summary-tag-label" data-i18n="settingsAudit.statSuccess">成功</span><strong id="audit-stat-success">0</strong></span>
                                        <span class="audit-summary-tag audit-summary-tag--warn"><span class="audit-summary-tag-label" data-i18n="settingsAudit.statFailures">失败</span><strong id="audit-stat-failures">0</strong></span>
                                        <span class="audit-summary-tag"><span class="audit-summary-tag-label" data-i18n="settingsAudit.statRecent7d">近 7 天</span><strong id="audit-stat-recent">0</strong></span>
                                    </div>
                                </div>
                                <div class="audit-filter-card">
                                    <div class="audit-time-presets" id="audit-time-presets">
                                        <span class="audit-time-presets-label" data-i18n="settingsAudit.timePresets">快捷</span>
                                        <button type="button" class="audit-time-preset-btn" data-preset="15m" data-i18n="settingsAudit.preset15m">最近15分钟</button>
                                        <button type="button" class="audit-time-preset-btn" data-preset="1h" data-i18n="settingsAudit.preset1h">最近1小时</button>
                                        <button type="button" class="audit-time-preset-btn" data-preset="24h" data-i18n="settingsAudit.preset24h">最近24小时</button>
                                        <button type="button" class="audit-time-preset-btn" data-preset="7d" data-i18n="settingsAudit.preset7d">最近7天</button>
                                        <button type="button" class="audit-time-preset-btn" data-preset="today" data-i18n="settingsAudit.presetToday">今天</button>
                                    </div>
                                    <div class="audit-filter-fields">
                                        <div class="audit-filter-row">
                                        <div class="audit-field audit-field--event">
                                            <span data-i18n="settingsAudit.filterEvent">事件类型</span>
                                            <div class="audit-filter-cascade">
                                                <select id="audit-filter-category" onchange="onAuditCategoryFilterChange()" aria-label="类别">
                                                    <option value="" data-i18n="settingsAudit.filterAllCategories">全部类别</option>
                                                    <option value="auth" data-i18n="settingsAudit.cat.auth">认证</option>
                                                    <option value="config" data-i18n="settingsAudit.cat.config">配置</option>
                                                    <option value="c2" data-i18n="settingsAudit.cat.c2">C2</option>
                                                    <option value="webshell" data-i18n="settingsAudit.cat.webshell">WebShell</option>
                                                    <option value="knowledge" data-i18n="settingsAudit.cat.knowledge">知识库</option>
                                                    <option value="conversation" data-i18n="settingsAudit.cat.conversation">对话</option>
                                                    <option value="vulnerability" data-i18n="settingsAudit.cat.vulnerability">漏洞</option>
                                                    <option value="external_mcp" data-i18n="settingsAudit.cat.externalMcp">外部 MCP</option>
                                                    <option value="task" data-i18n="settingsAudit.cat.task">任务</option>
                                                    <option value="tool" data-i18n="settingsAudit.cat.tool">工具</option>
                                                    <option value="file" data-i18n="settingsAudit.cat.file">文件</option>
                                                    <option value="hitl" data-i18n="settingsAudit.cat.hitl">人机协同</option>
                                                    <option value="role" data-i18n="settingsAudit.cat.role">角色</option>
                                                    <option value="skill" data-i18n="settingsAudit.cat.skill">Skill</option>
                                                    <option value="agent" data-i18n="settingsAudit.cat.agent">子代理</option>
                                                </select>
                                                <span class="audit-filter-cascade-arrow" aria-hidden="true">→</span>
                                                <select id="audit-filter-action" disabled aria-label="操作">
                                                    <option value="" data-i18n="settingsAudit.filterAllActions">全部操作</option>
                                                </select>
                                            </div>
                                        </div>
                                        <label class="audit-field audit-field--result">
                                            <span data-i18n="settingsAudit.filterResult">结果</span>
                                            <select id="audit-filter-result">
                                                <option value="" data-i18n="settingsAudit.filterAll">全部</option>
                                                <option value="success">success</option>
                                                <option value="failure">failure</option>
                                            </select>
                                        </label>
                                        <div class="audit-filter-time-group">
                                        <label class="audit-field audit-field--time">
                                            <span data-i18n="settingsAudit.filterSince">开始时间</span>
                                            <div class="audit-datetime-field" id="audit-filter-since-field">
                                                <input type="text" id="audit-filter-since" class="audit-datetime-input" readonly autocomplete="off" data-i18n="settingsAudit.datetimePlaceholder" data-i18n-attr="placeholder" placeholder="选择日期时间" />
                                                <button type="button" class="audit-datetime-btn audit-datetime-clear-btn" title="Clear" aria-label="Clear" hidden>&times;</button>
                                                <button type="button" class="audit-datetime-btn audit-datetime-open-btn" title="Open" aria-label="Open">
                                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2"/><path d="M16 2v4M8 2v4M3 10h18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                                                </button>
                                            </div>
                                        </label>
                                        <label class="audit-field audit-field--time">
                                            <span data-i18n="settingsAudit.filterUntil">结束时间</span>
                                            <div class="audit-datetime-field" id="audit-filter-until-field">
                                                <input type="text" id="audit-filter-until" class="audit-datetime-input" readonly autocomplete="off" data-i18n="settingsAudit.datetimePlaceholder" data-i18n-attr="placeholder" placeholder="选择日期时间" />
                                                <button type="button" class="audit-datetime-btn audit-datetime-clear-btn" title="Clear" aria-label="Clear" hidden>&times;</button>
                                                <button type="button" class="audit-datetime-btn audit-datetime-open-btn" title="Open" aria-label="Open">
                                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" stroke="currentColor" stroke-width="2"/><path d="M16 2v4M8 2v4M3 10h18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                                                </button>
                                            </div>
                                        </label>
                                        </div>
                                        </div>
                                    </div>
                                    <div class="audit-filter-bottom">
                                        <label class="audit-field audit-field--keyword">
                                            <span data-i18n="settingsAudit.filterQuery">关键词</span>
                                            <input type="text" id="audit-filter-q" data-i18n="settingsAudit.filterQueryPlaceholder" data-i18n-attr="placeholder" placeholder="消息 / 资源 ID / 操作名" />
                                        </label>
                                        <div class="audit-logs-actions">
                                            <button type="button" class="btn-primary" onclick="filterAuditLogs()" data-i18n="settingsAudit.filterBtn">筛选</button>
                                            <button type="button" class="btn-secondary" onclick="resetAuditLogFilters()" data-i18n="settingsAudit.resetBtn">重置</button>
                                            <button type="button" class="btn-secondary" onclick="refreshAuditLogs()" data-i18n="common.refresh">刷新</button>
                                            <div class="audit-export-dropdown">
                                                <button type="button" class="btn-secondary audit-export-trigger" id="audit-export-trigger" onclick="toggleAuditExportMenu(event)" aria-haspopup="true" aria-expanded="false">
                                                    <span data-i18n="settingsAudit.exportBtn">导出</span>
                                                    <span class="audit-export-caret" aria-hidden="true">▾</span>
                                                </button>
                                                <div id="audit-export-menu" class="audit-export-menu" role="menu" hidden>
                                                    <button type="button" class="audit-export-menu-item" role="menuitem" data-require-permission="audit:read" onclick="runAuditExport('json')" data-i18n="settingsAudit.exportJson">导出 JSON</button>
                                                    <button type="button" class="audit-export-menu-item" role="menuitem" data-require-permission="audit:read" onclick="runAuditExport('csv')" data-i18n="settingsAudit.exportCsv">导出 CSV</button>
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                    <p id="audit-filter-timezone-hint" class="audit-timezone-hint" hidden></p>
                                </div>
                                <div id="audit-log-list" class="audit-log-list"></div>
                                <div id="audit-logs-pagination" class="pagination-container audit-logs-pagination"></div>
                            </div>

                            <!-- 安全设置 -->
                            <div id="settings-section-security" class="settings-section-content">
                                <div class="settings-section-header">
                                    <h3 data-i18n="settings.nav.security">安全设置</h3>
                                </div>
                                
                                <div class="settings-subsection">
                                    <h4 data-i18n="settingsSecurity.changePasswordTitle">修改密码</h4>
                                    <p class="settings-description" data-i18n="settingsSecurity.changePasswordDesc">修改登录密码后，需要使用新密码重新登录。</p>
                                    <div class="settings-form">
                                        <div class="form-group">
                                            <label for="auth-current-password" data-i18n="settingsSecurity.currentPassword">当前密码</label>
                                            <input type="password" id="auth-current-password" data-i18n="settingsSecurity.currentPasswordPlaceholder" data-i18n-attr="placeholder" placeholder="输入当前登录密码" autocomplete="current-password" />
                                        </div>
                                        <div class="form-group">
                                            <label for="auth-new-password" data-i18n="settingsSecurity.newPassword">新密码</label>
                                            <input type="password" id="auth-new-password" data-i18n="settingsSecurity.newPasswordPlaceholder" data-i18n-attr="placeholder" placeholder="设置新密码（至少 8 位）" autocomplete="new-password" />
                                        </div>
                                        <div class="form-group">
                                            <label for="auth-confirm-password" data-i18n="settingsSecurity.confirmPassword">确认新密码</label>
                                            <input type="password" id="auth-confirm-password" data-i18n="settingsSecurity.confirmPasswordPlaceholder" data-i18n-attr="placeholder" placeholder="再次输入新密码" autocomplete="new-password" />
                                        </div>
                                        <div class="form-actions">
                                            <button class="btn-secondary" type="button" onclick="resetPasswordForm()" data-i18n="settingsSecurity.clear">清空</button>
                                            <button class="btn-primary change-password-submit" type="button" data-require-permission="auth:self" onclick="changePassword()" data-i18n="settingsSecurity.changePasswordBtn">修改密码</button>
                                        </div>
                                    </div>
                                </div>
                            </div>

                        </div>
                    </div>
                </div>

                <!-- 平台权限页面 -->
                <div id="page-platform-rbac" class="page platform-rbac-page">
                                <div class="page-header">
                                    <div>
                                        <h2 data-i18n="rbac.title">平台权限</h2>
                                    </div>
                                    <div class="page-header-actions">
                                        <button class="btn-secondary" type="button" onclick="refreshPlatformRbac(this)" data-i18n="common.refresh">刷新</button>
                                        <button class="btn-secondary" type="button" onclick="openRbacRoleModal()" data-i18n="rbac.createRole">新建角色</button>
                                        <button class="btn-primary" type="button" onclick="openRbacUserModal()" data-i18n="rbac.createUser">添加成员</button>
                                    </div>
                                </div>
                                <div class="page-content">
                                    <div class="rbac-topbar">
                                        <div class="rbac-overview" id="rbac-overview">
                                            <div class="rbac-metric rbac-metric-users">
                                                <strong id="rbac-metric-users">0</strong>
                                                <span data-i18n="rbac.metricUsersPill">个账号</span>
                                            </div>
                                            <div class="rbac-metric rbac-metric-enabled">
                                                <strong id="rbac-metric-enabled">0</strong>
                                                <span data-i18n="rbac.metricEnabledPill">个启用账号</span>
                                            </div>
                                            <div class="rbac-metric rbac-metric-roles">
                                                <strong id="rbac-metric-roles">0</strong>
                                                <span data-i18n="rbac.metricRolesPill">个角色</span>
                                            </div>
                                            <div class="rbac-metric rbac-metric-assignments">
                                                <strong id="rbac-metric-assignments">0</strong>
                                                <span data-i18n="rbac.metricAssignmentsPill">项授权</span>
                                            </div>
                                        </div>
                                        <div id="rbac-metric-context" class="rbac-metric-context" hidden></div>
                                        <div class="rbac-workspace-nav" role="tablist" aria-label="权限管理视图">
                                            <button type="button" class="rbac-workspace-tab is-active" role="tab" aria-selected="true" data-rbac-view="users" onclick="switchRbacView('users')">
                                                <span data-i18n="rbac.memberManagement">成员管理</span>
                                                <small data-i18n="rbac.memberManagementHint">为成员分配角色与数据范围</small>
                                            </button>
                                            <button type="button" class="rbac-workspace-tab" role="tab" aria-selected="false" data-rbac-view="roles" onclick="switchRbacView('roles')">
                                                <span data-i18n="rbac.roleManagement">角色管理</span>
                                                <small data-i18n="rbac.roleManagementHint">定义权限集合与默认可见范围</small>
                                            </button>
                                        </div>
                                    </div>
                                    <div id="rbac-view-users" class="rbac-workspace-view rbac-layout">
                                        <section class="rbac-panel rbac-panel-users">
                                            <div class="rbac-panel-head">
                                                <div>
                                                    <h3 data-i18n="rbac.users">用户</h3>
                                                    <p class="rbac-muted" data-i18n="rbac.usersHint">按账号选择后管理角色与资源范围。</p>
                                                </div>
                                                <span id="rbac-users-count" class="rbac-count">0</span>
                                            </div>
                                            <div class="rbac-search">
                                                <input id="rbac-user-search" class="form-input" type="search" placeholder="搜索用户名或显示名称" data-i18n="rbac.searchUsers" data-i18n-attr="placeholder" oninput="setRbacUserSearch(this.value)">
                                            </div>
                                            <div id="rbac-users-list" class="rbac-list">
                                                <div class="loading-spinner" data-i18n="knowledgePage.loading">加载中...</div>
                                            </div>
                                        </section>
                                        <section class="rbac-panel rbac-panel-detail">
                                            <div class="rbac-detail-head">
                                                <div>
                                                    <h3 id="rbac-selected-title" data-i18n="rbac.selectUser">选择用户</h3>
                                                    <p id="rbac-selected-subtitle" class="rbac-muted" data-i18n="rbac.selectUserHint">选择一个平台用户后编辑角色、状态与资源授权。</p>
                                                </div>
                                                <div class="rbac-detail-actions">
                                                    <button class="btn-secondary btn-small btn-delete" data-require-permission="rbac:write" type="button" id="rbac-delete-user-btn" onclick="deleteSelectedRbacUser()" disabled data-i18n="common.delete">删除</button>
                                                    <button class="btn-primary btn-small" type="button" id="rbac-edit-user-btn" onclick="openRbacUserModalForSelected()" disabled data-i18n="common.edit">编辑</button>
                                                </div>
                                            </div>
                                            <div id="rbac-selected-summary" class="rbac-selected-summary"></div>
                                            <div id="rbac-no-role-notice" class="rbac-no-role-notice" hidden></div>
                                            <div class="rbac-tabs" role="tablist">
                                                <button type="button" class="rbac-tab is-active" data-rbac-tab="roles" onclick="switchRbacTab('roles')" data-i18n="rbac.tabRoles">角色权限</button>
                                                <button type="button" class="rbac-tab" data-rbac-tab="assignments" onclick="switchRbacTab('assignments')" data-i18n="rbac.tabAssignments">资源授权</button>
                                                <button type="button" class="rbac-tab" data-rbac-tab="audit" onclick="switchRbacTab('audit')" data-i18n="rbac.tabAudit">变更记录</button>
                                            </div>
                                            <div id="rbac-tab-roles" class="rbac-tab-panel">
                                                <div class="rbac-section-toolbar">
                                                    <div>
                                                        <strong data-i18n="rbac.roleMembership">角色成员关系</strong>
                                                        <p class="rbac-muted" data-i18n="rbac.roleMembershipHint">角色决定能做什么，资源范围决定能看到哪些数据。</p>
                                                    </div>
                                                    <div class="rbac-role-save-actions">
                                                        <span id="rbac-role-unsaved" class="rbac-unsaved-indicator" hidden data-i18n="rbac.unsavedChanges">有未保存的变更</span>
                                                        <button id="rbac-role-reset-btn" class="btn-secondary btn-small" type="button" onclick="resetSelectedUserRoles()" disabled data-i18n="common.cancel">取消</button>
                                                        <button id="rbac-role-apply-btn" class="btn-primary btn-small" data-require-permission="rbac:write" type="button" onclick="saveSelectedUserRoles()" disabled data-i18n="rbac.saveRoleChanges">保存角色变更</button>
                                                    </div>
                                                </div>
                                                <div id="rbac-roles-list" class="rbac-role-grid"></div>
                                            </div>
                                            <div id="rbac-tab-assignments" class="rbac-tab-panel" hidden>
                                                <p class="rbac-assignment-help" data-i18n="rbac.assignmentHelp">仅“指定资源”范围的角色需要单独授权。项目授权会覆盖该项目下的对话和漏洞。</p>
                                                <div id="rbac-pending-bar" class="rbac-pending-bar" hidden>
                                                    <div class="rbac-pending-bar-head">
                                                        <strong id="rbac-pending-title" data-i18n="rbac.pendingGrants">待授权</strong>
                                                        <span id="rbac-pending-count" class="rbac-pill is-info">0</span>
                                                    </div>
                                                    <div id="rbac-pending-list" class="rbac-pending-list"></div>
                                                    <div class="rbac-pending-bar-actions">
                                                        <button type="button" class="btn-secondary btn-small" onclick="clearRbacResourceSelection()" data-i18n="rbac.clearSelection">清空选择</button>
                                                        <button type="button" class="btn-primary btn-small" data-require-permission="rbac:write" onclick="createRbacAssignment()" data-i18n="rbac.confirmGrant">确认授权</button>
                                                    </div>
                                                </div>
                                                <div class="rbac-assignment-columns">
                                                    <section class="rbac-resource-section">
                                                        <div class="rbac-resource-section-head">
                                                            <div>
                                                                <strong data-i18n="rbac.availableResources">可授权资源</strong>
                                                                <span data-i18n="rbac.availableResourcesHint">勾选当前页资源，可跨页累计选择</span>
                                                            </div>
                                                        </div>
                                                        <div class="rbac-assignment-filterbar rbac-resource-filterbar">
                                                            <select id="rbac-assignment-type" class="form-select rbac-form-select" onchange="changeRbacResourceType()">
                                                                <option value="conversation" data-i18n="rbac.resourceTypes.conversation">对话</option>
                                                                <option value="project" data-i18n="rbac.resourceTypes.project">项目</option>
                                                                <option value="batch_task" data-i18n="rbac.resourceTypes.batch_task">批量任务</option>
                                                                <option value="vulnerability" data-i18n="rbac.resourceTypes.vulnerability">漏洞</option>
                                                                <option value="asset" data-i18n="rbac.resourceTypes.asset">资产</option>
                                                                <option value="webshell" data-i18n="rbac.resourceTypes.webshell">WebShell 连接</option>
                                                                <option value="c2_listener" data-i18n="rbac.resourceTypes.c2_listener">C2 监听器</option>
                                                            </select>
                                                            <input id="rbac-resource-search" class="form-input" type="search" placeholder="按名称或 ID 搜索可授权资源" data-i18n="rbac.searchResourcePlaceholder" data-i18n-attr="placeholder" oninput="queueRbacResourceSearch(this.value)">
                                                            <input id="rbac-assignment-id" class="form-input" type="text" placeholder="多个 ID 用逗号分隔" data-i18n="rbac.resourceIdPlaceholder" data-i18n-attr="placeholder" oninput="syncRbacAssignmentSubmit()">
                                                        </div>
                                                        <div id="rbac-resource-picker" class="rbac-resource-picker"></div>
                                                        <div id="rbac-resource-pagination" class="rbac-pagination">
                                                            <button type="button" class="btn-secondary btn-small" data-rbac-page-previous onclick="changeRbacResourcePage(-1)" data-i18n="rbac.pagination.previous">上一页</button>
                                                            <span data-rbac-page-info>第 1 页</span>
                                                            <button type="button" class="btn-secondary btn-small" data-rbac-page-next onclick="changeRbacResourcePage(1)" data-i18n="rbac.pagination.next">下一页</button>
                                                        </div>
                                                    </section>
                                                    <section class="rbac-resource-section">
                                                        <div class="rbac-resource-section-head">
                                                            <div>
                                                                <strong data-i18n="rbac.currentAssignments">当前单独授权</strong>
                                                                <span><span id="rbac-current-assignment-count">0</span> <span data-i18n="rbac.items">项</span></span>
                                                            </div>
                                                        </div>
                                                        <div class="rbac-assignment-filterbar">
                                                            <div class="rbac-assignment-filters">
                                                                <select id="rbac-assignment-filter-type" class="form-select rbac-form-select" onchange="changeRbacAssignmentFilter(this.value)" aria-label="筛选资源类型">
                                                                    <option value="all" data-i18n="rbac.allResourceTypes">全部类型</option>
                                                                    <option value="conversation" data-i18n="rbac.resourceTypes.conversation">对话</option>
                                                                    <option value="project" data-i18n="rbac.resourceTypes.project">项目</option>
                                                                    <option value="batch_task" data-i18n="rbac.resourceTypes.batch_task">批量任务</option>
                                                                    <option value="vulnerability" data-i18n="rbac.resourceTypes.vulnerability">漏洞</option>
                                                                    <option value="asset" data-i18n="rbac.resourceTypes.asset">资产</option>
                                                                    <option value="webshell" data-i18n="rbac.resourceTypes.webshell">WebShell 连接</option>
                                                                    <option value="c2_listener" data-i18n="rbac.resourceTypes.c2_listener">C2 监听器</option>
                                                                </select>
                                                                <input id="rbac-assignment-search" class="form-input" type="search" placeholder="搜索已授权资源名称或 ID" data-i18n="rbac.searchAssignments" data-i18n-attr="placeholder" oninput="filterRbacAssignments(this.value)">
                                                            </div>
                                                        </div>
                                                        <div id="rbac-assignments-list" class="rbac-assignments-list"></div>
                                                        <div id="rbac-assignment-pagination" class="rbac-pagination">
                                                            <button type="button" class="btn-secondary btn-small" data-rbac-page-previous onclick="changeRbacAssignmentPage(-1)" data-i18n="rbac.pagination.previous">上一页</button>
                                                            <span data-rbac-page-info></span>
                                                            <button type="button" class="btn-secondary btn-small" data-rbac-page-next onclick="changeRbacAssignmentPage(1)" data-i18n="rbac.pagination.next">下一页</button>
                                                        </div>
                                                    </section>
                                                </div>
                                            </div>
                                            <div id="rbac-tab-audit" class="rbac-tab-panel" hidden>
                                                <div class="rbac-audit-toolbar">
                                                    <div class="rbac-audit-heading">
                                                        <strong data-i18n="rbac.auditTitle">权限变更记录</strong>
                                                        <p class="rbac-muted" data-i18n="rbac.auditHint">展示该成员相关的平台权限操作审计。</p>
                                                    </div>
                                                    <div class="rbac-audit-filterbar" role="search" aria-label="变更记录筛选" data-i18n="rbac.auditFilters.filterBarLabel" data-i18n-attr="aria-label">
                                                        <label class="rbac-audit-filter rbac-audit-filter--action">
                                                            <span data-i18n="rbac.auditColumns.action">操作</span>
                                                            <select id="rbac-audit-action-filter" class="form-select rbac-form-select" onchange="setRbacAuditFilter('action', this.value)" aria-label="按操作筛选" data-i18n="rbac.auditFilters.actionLabel" data-i18n-attr="aria-label">
                                                                <option value="" data-i18n="rbac.auditFilters.allActions">全部操作</option>
                                                                <option value="assign_resource" data-i18n="rbac.auditActions.assign_resource">授权资源访问</option>
                                                                <option value="delete_resource_assignment" data-i18n="rbac.auditActions.delete_resource_assignment">撤销资源授权</option>
                                                                <option value="create_user" data-i18n="rbac.auditActions.create_user">创建平台用户</option>
                                                                <option value="update_user" data-i18n="rbac.auditActions.update_user">更新平台用户</option>
                                                            </select>
                                                        </label>
                                                        <label class="rbac-audit-filter rbac-audit-filter--resource">
                                                            <span data-i18n="rbac.auditColumns.resourceType">资源类型</span>
                                                            <select id="rbac-audit-resource-type-filter" class="form-select rbac-form-select" onchange="setRbacAuditFilter('resourceType', this.value)" aria-label="按资源类型筛选" data-i18n="rbac.auditFilters.resourceTypeLabel" data-i18n-attr="aria-label">
                                                                <option value="" data-i18n="rbac.auditFilters.allResourceTypes">全部资源类型</option>
                                                                <option value="user" data-i18n="rbac.resourceTypes.user">平台用户</option>
                                                                <option value="project" data-i18n="rbac.resourceTypes.project">项目</option>
                                                                <option value="conversation" data-i18n="rbac.resourceTypes.conversation">对话</option>
                                                                <option value="vulnerability" data-i18n="rbac.resourceTypes.vulnerability">漏洞</option>
                                                                <option value="asset" data-i18n="rbac.resourceTypes.asset">资产</option>
                                                                <option value="webshell" data-i18n="rbac.resourceTypes.webshell">WebShell 连接</option>
                                                                <option value="batch_task" data-i18n="rbac.resourceTypes.batch_task">批量任务</option>
                                                                <option value="c2_listener" data-i18n="rbac.resourceTypes.c2_listener">C2 监听器</option>
                                                            </select>
                                                        </label>
                                                    </div>
                                                </div>
                                                <div id="rbac-audit-list" class="rbac-audit-list">
                                                    <div class="rbac-empty"><strong data-i18n="rbac.empty.selectUserFirst">请先选择用户</strong></div>
                                                </div>
                                                <div id="rbac-audit-pagination" class="rbac-pagination rbac-audit-pagination">
                                                    <div class="rbac-audit-pagination-meta">
                                                        <span data-rbac-page-range>显示 0-0 / 共 0 条记录</span>
                                                        <label class="rbac-audit-page-size-control">
                                                            <span data-i18n="rbac.pagination.rowsPerPage">每页显示</span>
                                                            <select id="rbac-audit-page-size" class="form-select rbac-form-select" onchange="changeRbacAuditPageSize(this.value)" aria-label="每页显示条数" data-i18n="rbac.auditPageSizeLabel" data-i18n-attr="aria-label">
                                                                <option value="20">20</option>
                                                                <option value="50">50</option>
                                                                <option value="100">100</option>
                                                            </select>
                                                        </label>
                                                    </div>
                                                    <div class="rbac-audit-pagination-nav">
                                                        <button type="button" class="btn-secondary btn-small" data-rbac-page-first onclick="setRbacAuditPage(0)" data-i18n="rbac.pagination.first" disabled>首页</button>
                                                        <button type="button" class="btn-secondary btn-small" data-rbac-page-previous onclick="changeRbacAuditPage(-1)" data-i18n="rbac.pagination.previous" disabled>上一页</button>
                                                        <span data-rbac-page-info>第 1 / 1 页</span>
                                                        <button type="button" class="btn-secondary btn-small" data-rbac-page-next onclick="changeRbacAuditPage(1)" data-i18n="rbac.pagination.next" disabled>下一页</button>
                                                        <button type="button" class="btn-secondary btn-small" data-rbac-page-last onclick="setRbacAuditPage(-1)" data-i18n="rbac.pagination.last" disabled>末页</button>
                                                    </div>
                                                </div>
                                            </div>
                                        </section>
                                    </div>
                                    <div id="rbac-view-roles" class="rbac-workspace-view rbac-role-management" hidden>
                                        <div class="rbac-role-management-head">
                                            <div>
                                                <h3 data-i18n="rbac.roleCatalog">角色目录</h3>
                                                <p class="rbac-muted" data-i18n="rbac.roleCatalogHint">先定义角色的操作权限与资源范围，再分配给成员。</p>
                                            </div>
                                            <div class="rbac-role-management-actions">
                                                <div class="rbac-toolbar-search">
                                                    <label for="rbac-role-search" data-i18n="rbac.filterRoles">筛选角色</label>
                                                    <input id="rbac-role-search" class="form-input" type="search" placeholder="搜索角色或权限" data-i18n="rbac.searchRoles" data-i18n-attr="placeholder" oninput="setRbacRoleSearch(this.value)">
                                                </div>
                                                <button class="btn-primary btn-small" type="button" onclick="openRbacRoleModal()" data-i18n="rbac.createRole">新建角色</button>
                                            </div>
                                        </div>
                                        <div id="rbac-role-catalog" class="rbac-role-catalog"></div>
                                    </div>
                                </div>
                            </div>
            </div>
        </div>
    </div>


    <!-- MCP调用详情模态框 -->
    <div id="mcp-detail-modal" class="modal">
        <div class="modal-content mcp-detail-content">
            <div class="modal-header">
                <h2 data-i18n="mcpDetailModal.title">工具调用详情</h2>
                <span class="modal-close" onclick="closeMCPDetail()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="detail-section detail-section-overview">
                    <div class="detail-section-header">
                        <h3 data-i18n="mcpDetailModal.execInfo">执行信息</h3>
                    </div>
                    <div class="detail-info-grid">
                        <div class="detail-item">
                            <strong data-i18n="mcpDetailModal.tool">工具</strong>
                            <span id="detail-tool-name"></span>
                        </div>
                        <div class="detail-item">
                            <strong data-i18n="mcpDetailModal.status">状态</strong>
                            <span id="detail-status" class="status-chip status-unknown"></span>
                        </div>
                        <div class="detail-item">
                            <strong data-i18n="mcpDetailModal.time">时间</strong>
                            <span id="detail-time"></span>
                        </div>
                        <div class="detail-item">
                            <strong data-i18n="mcpDetailModal.executionId">执行 ID</strong>
                            <span id="detail-execution-id" class="mono-text"></span>
                        </div>
                    </div>
                </div>
                <div class="detail-section detail-abort-section" id="detail-abort-section" style="display: none;">
                    <div class="detail-section-header">
                        <h3 data-i18n="mcpDetailModal.abortTitle">运行控制</h3>
                    </div>
                    <p class="detail-abort-hint" data-i18n="mcpDetailModal.abortHint">仅中断当前工具调用；对话与多步任务会继续。</p>
                    <button type="button" class="btn-secondary btn-monitor-abort" id="detail-abort-btn" onclick="abortMCPToolExecutionFromDetail()">终止工具</button>
                </div>
                <div class="detail-section">
                    <div class="detail-section-header">
                        <h3 data-i18n="mcpDetailModal.requestParams">请求参数</h3>
                        <button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-request', this)" data-i18n="mcpDetailModal.copyJson">复制 JSON</button>
                    </div>
                    <div class="detail-code-card">
                        <pre id="detail-request" class="code-block"></pre>
                    </div>
                </div>
                <div class="detail-section">
                    <div class="detail-section-header">
                        <h3 data-i18n="mcpDetailModal.responseResult">响应结果</h3>
                        <button class="btn-ghost" type="button" onclick="copyActiveMCPResultDetail(this)" data-i18n="mcpDetailModal.copyContent">复制内容</button>
                    </div>
                    <div class="detail-result-tabs" role="tablist" aria-label="响应结果视图">
                        <button id="detail-result-tab-success" class="detail-result-tab active" type="button" role="tab" aria-selected="true" aria-controls="detail-result-panel-success" onclick="switchMCPResultDetailTab('success')">
                            <span data-i18n="mcpDetailModal.correctInfo">正确信息</span>
                        </button>
                        <button id="detail-result-tab-raw" class="detail-result-tab" type="button" role="tab" aria-selected="false" aria-controls="detail-result-panel-raw" onclick="switchMCPResultDetailTab('raw')">
                            <span data-i18n="mcpDetailModal.rawResponse">原始响应</span>
                        </button>
                    </div>
                    <div id="detail-result-panel-success" class="detail-result-panel active" role="tabpanel" aria-labelledby="detail-result-tab-success">
                        <div class="detail-code-card detail-success-code-card">
                            <pre id="detail-success" class="code-block"></pre>
                        </div>
                    </div>
                    <div id="detail-result-panel-raw" class="detail-result-panel" role="tabpanel" aria-labelledby="detail-result-tab-raw" hidden>
                        <div class="detail-code-card">
                            <pre id="detail-response" class="code-block"></pre>
                        </div>
                    </div>
                </div>
                <div class="detail-section detail-error-wrapper" id="detail-error-section" style="display: none;">
                    <div class="detail-section-header">
                        <h3 data-i18n="mcpDetailModal.errorInfo">错误信息</h3>
                        <button class="btn-ghost" type="button" onclick="copyDetailBlock('detail-error', this)" data-i18n="mcpDetailModal.copyError">复制错误</button>
                    </div>
                    <div class="detail-code-card">
                        <pre id="detail-error" class="code-block error"></pre>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 用户中断并说明（继续迭代） -->
    <div id="user-interrupt-modal" class="modal">
        <div class="modal-content" style="max-width: 520px;">
            <div class="modal-header">
                <h2 data-i18n="tasks.interruptModalTitle">中断当前步骤</h2>
                <span class="modal-close" onclick="closeUserInterruptModal()">&times;</span>
            </div>
            <div class="modal-body">
                <p class="detail-abort-hint" data-i18n="tasks.interruptModalHint">填写说明后将写入对话并由智能体继续迭代。</p>
                <div class="form-group">
                    <label for="user-interrupt-reason"><span data-i18n="tasks.interruptReasonLabel">中断说明</span></label>
                    <textarea id="user-interrupt-reason" class="form-control" rows="4" data-i18n="tasks.interruptReasonPlaceholder" data-i18n-attr="placeholder" placeholder=""></textarea>
                </div>
                <div class="form-actions" style="display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end;">
                    <button type="button" class="btn-secondary" onclick="closeUserInterruptModal()" data-i18n="tasks.interruptModalClose">关闭</button>
                    <button type="button" class="btn-secondary btn-delete" onclick="submitUserInterruptHardCancel()" data-i18n="tasks.interruptHardStop">彻底停止</button>
                    <button type="button" class="btn-primary" onclick="submitUserInterruptContinue()" data-i18n="tasks.interruptConfirmContinue">中断并继续</button>
                </div>
            </div>
        </div>
    </div>

    <!-- MCP 工具终止：可填写给模型的说明 -->
    <div id="mcp-tool-abort-modal" class="modal">
        <div class="modal-content" style="max-width: 520px;">
            <div class="modal-header">
                <h2 data-i18n="mcpDetailModal.abortNoteModalTitle">终止工具并补充说明</h2>
                <span class="modal-close" onclick="closeMcpToolAbortModal()">&times;</span>
            </div>
            <div class="modal-body">
                <p class="detail-abort-hint" data-i18n="mcpDetailModal.abortNoteModalHint">可选说明。</p>
                <div class="form-group">
                    <label for="mcp-tool-abort-note"><span data-i18n="mcpDetailModal.abortNoteLabel">终止说明（可选）</span></label>
                    <textarea id="mcp-tool-abort-note" class="form-control" rows="4" data-i18n="mcpDetailModal.abortNotePlaceholder" data-i18n-attr="placeholder" placeholder=""></textarea>
                </div>
                <div class="form-actions" style="display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end;">
                    <button type="button" class="btn-secondary" onclick="closeMcpToolAbortModal()" data-i18n="mcpDetailModal.abortNoteClose">取消</button>
                    <button type="button" class="btn-primary" onclick="submitMcpToolAbortModal()" data-i18n="mcpDetailModal.abortNoteSubmit">提交终止</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 外部MCP配置模态框 -->
    <div id="external-mcp-modal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2 id="external-mcp-modal-title" data-i18n="mcp.addExternalMCP">添加外部MCP</h2>
                <span class="modal-close" onclick="closeExternalMCPModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="external-mcp-json"><span data-i18n="externalMcpModal.configJson">配置JSON</span> <span style="color: red;">*</span></label>
                    <textarea id="external-mcp-json" rows="15" data-i18n="externalMcpModal.placeholder" data-i18n-attr="placeholder" style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5;"></textarea>
                    <div class="form-actions" style="justify-content: flex-start; margin-top: 0;">
                        <button type="button" class="btn-secondary" onclick="formatExternalMCPJSON()" data-i18n="externalMcpModal.formatJson">格式化JSON</button>
                        <button type="button" class="btn-secondary" onclick="loadExternalMCPExample()" data-i18n="externalMcpModal.loadExample">加载示例</button>
                    </div>
                    <div class="password-hint">
                        <strong data-i18n="externalMcpModal.formatLabel">配置格式：</strong><span data-i18n="externalMcpModal.formatDesc">JSON对象，key为配置名称，value为配置内容。状态通过"启动/停止"按钮控制，无需在JSON中配置。</span><br>
                        <strong data-i18n="externalMcpModal.configExample">配置示例：</strong><br>
                        <strong data-i18n="externalMcpModal.stdioMode">stdio模式：</strong><br>
                        <code data-i18n="externalMcpModal.exampleStdio" style="display: block; margin: 8px 0; padding: 8px; background: var(--bg-secondary); border-radius: 4px; white-space: pre-wrap;">{
  "hexstrike-ai": {
    "command": "python3",
    "args": ["/path/to/script.py", "--server", "http://example.com"],
    "description": "描述",
    "timeout": 300
  }
}</code>
                        <strong data-i18n="externalMcpModal.httpMode">HTTP模式：</strong><br>
                        <code data-i18n="externalMcpModal.exampleHttp" style="display: block; margin: 8px 0; padding: 8px; background: var(--bg-secondary); border-radius: 4px; white-space: pre-wrap;">{
  "cyberstrike-ai-http": {
    "transport": "http",
    "url": "http://127.0.0.1:8081/mcp"
  }
}</code>
                        <strong data-i18n="externalMcpModal.sseMode">SSE模式：</strong><br>
                        <code data-i18n="externalMcpModal.exampleSse" style="display: block; margin: 8px 0; padding: 8px; background: var(--bg-secondary); border-radius: 4px; white-space: pre-wrap;">{
  "cyberstrike-ai-sse": {
    "transport": "sse",
    "url": "http://127.0.0.1:8081/mcp/sse"
  }
}</code>
                    </div>
                    <div id="external-mcp-json-error" class="error-message" style="display: none; margin-top: 8px; padding: 8px; background: rgba(220, 53, 69, 0.1); border: 1px solid rgba(220, 53, 69, 0.3); border-radius: 4px; color: var(--error-color); font-size: 0.875rem;"></div>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeExternalMCPModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="mcp:write" onclick="saveExternalMCP()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <!-- 攻击链可视化模态框 -->
    <div id="attack-chain-modal" class="modal">
        <div class="modal-content attack-chain-modal-content">
            <div class="modal-header">
                <h2 data-i18n="attackChainModal.title">攻击链可视化</h2>
                <div class="modal-header-actions">
                    <button class="btn-primary attack-chain-action-btn" data-require-permission="attackchain:write" onclick="regenerateAttackChain()" data-i18n="attackChainModal.regenerateTitle" data-i18n-attr="title" data-i18n-skip-text="true" title="重新生成攻击链（包含最新对话内容）">
                        <span data-i18n="attackChainModal.regenerate">重新生成</span>
                    </button>
                    <button class="btn-secondary attack-chain-action-btn" onclick="exportAttackChain('png')" data-i18n="attackChainModal.exportPng" data-i18n-attr="title" title="导出为PNG">
                        📥 PNG
                    </button>
                    <button class="btn-secondary attack-chain-action-btn" onclick="exportAttackChain('svg')" data-i18n="attackChainModal.exportSvg" data-i18n-attr="title" title="导出为SVG">
                        📥 SVG
                    </button>
                    <button class="btn-secondary attack-chain-action-btn" onclick="refreshAttackChain()" data-i18n="attackChainModal.refreshTitle" data-i18n-attr="title" title="刷新当前攻击链（不重新生成）">
                        <span data-i18n="common.refresh">刷新</span>
                    </button>
                    <span class="modal-close" onclick="closeAttackChainModal()">&times;</span>
                </div>
            </div>
            <div class="modal-body attack-chain-body">
                <div class="attack-chain-main-layout">
                    <div class="attack-chain-visualization-area">
                        <div class="attack-chain-toolbar">
                            <div class="attack-chain-info">
                                <span id="attack-chain-stats">Nodes: 0 | Edges: 0</span>
                            </div>
                            <div class="attack-chain-filters">
                                <input type="text" id="attack-chain-search" data-i18n="attackChainModal.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索节点..." 
                                       oninput="filterAttackChainNodes(this.value)">
                                <select id="attack-chain-type-filter" 
                                        onchange="filterAttackChainByType(this.value)">
                                    <option value="all" data-i18n="attackChainModal.allTypes">所有类型</option>
                                    <option value="target" data-i18n="attackChainModal.target">目标</option>
                                    <option value="action" data-i18n="attackChainModal.action">行动</option>
                                    <option value="vulnerability" data-i18n="attackChainModal.vulnerability">漏洞</option>
                                </select>
                                <select id="attack-chain-risk-filter"
                                        onchange="filterAttackChainByRisk(this.value)">
                                    <option value="all" data-i18n="attackChainModal.allRisks">所有风险</option>
                                    <option value="high" data-i18n="attackChainModal.highRisk">高风险 (80-100)</option>
                                    <option value="medium-high" data-i18n="attackChainModal.mediumHighRisk">中高风险 (60-79)</option>
                                    <option value="medium" data-i18n="attackChainModal.mediumRisk">中风险 (40-59)</option>
                                    <option value="low" data-i18n="attackChainModal.lowRisk">低风险 (0-39)</option>
                                </select>
                                <button class="btn-secondary" onclick="resetAttackChainFilters()" data-i18n="attackChainModal.resetFilter">
                                    重置筛选
                                </button>
                            </div>
                        </div>
                        <div id="attack-chain-container" class="attack-chain-container">
                            <div class="loading-spinner" data-i18n="attackChainModal.loading">加载中...</div>
                        </div>
                    </div>
                    <div class="attack-chain-sidebar">
                        <div class="attack-chain-sidebar-content">
                            <div class="attack-chain-legend">
                                <div class="legend-section">
                                    <div class="legend-title" data-i18n="attackChainModal.riskLevel">风险等级</div>
                                    <div class="legend-item">
                                        <span class="legend-color" style="background: #ff4444;"></span>
                                        <span data-i18n="attackChainModal.highRisk">高风险 (80-100)</span>
                                    </div>
                                    <div class="legend-item">
                                        <span class="legend-color" style="background: #ff8800;"></span>
                                        <span data-i18n="attackChainModal.mediumHighRisk">中高风险 (60-79)</span>
                                    </div>
                                    <div class="legend-item">
                                        <span class="legend-color" style="background: #ffbb00;"></span>
                                        <span data-i18n="attackChainModal.mediumRisk">中风险 (40-59)</span>
                                    </div>
                                    <div class="legend-item">
                                        <span class="legend-color" style="background: #88cc00;"></span>
                                        <span data-i18n="attackChainModal.lowRisk">低风险 (0-39)</span>
                                    </div>
                                </div>
                                <div class="legend-section">
                                    <div class="legend-title" data-i18n="attackChainModal.lineMeaning">连接线含义</div>
                                    <div class="legend-item">
                                        <span class="legend-line" style="border-top: 2px solid #42a5f5;"></span>
                                        <span data-i18n="attackChainModal.blueLine">蓝色线：行动发现漏洞</span>
                                    </div>
                                    <div class="legend-item">
                                        <span class="legend-line" style="border-top: 2px solid #e53935;"></span>
                                        <span data-i18n="attackChainModal.redLine">红色线：使能/促成关系</span>
                                    </div>
                                    <div class="legend-item">
                                        <span class="legend-line" style="border-top: 2px solid #616161;"></span>
                                        <span data-i18n="attackChainModal.grayLine">灰色线：逻辑顺序</span>
                                    </div>
                                </div>
                                <div id="attack-chain-details" class="legend-section attack-chain-details" style="display: none;">
                                    <div class="legend-title attack-chain-details-title">
                                        <span data-i18n="attackChainModal.nodeDetails">节点详情</span>
                                        <button class="attack-chain-details-close" onclick="closeNodeDetails()" data-i18n="attackChainModal.closeDetails" data-i18n-attr="title" title="关闭详情">
                                            <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                                <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                                            </svg>
                                        </button>
                                    </div>
                                    <div id="attack-chain-details-content" class="attack-chain-details-content"></div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="chat-files-edit-modal" class="modal">
        <div class="modal-content" style="max-width: 720px;">
            <div class="modal-header">
                <h2 data-i18n="chatFilesPage.editTitle">编辑文件</h2>
                <span class="modal-close" onclick="closeChatFilesEditModal()">&times;</span>
            </div>
            <div class="modal-body">
                <p class="chat-files-modal-path"><code id="chat-files-edit-path"></code></p>
                <textarea id="chat-files-edit-textarea" class="form-control chat-files-edit-textarea" rows="18"></textarea>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn-secondary" onclick="closeChatFilesEditModal()" data-i18n="common.cancel">取消</button>
                <button type="button" class="btn-primary" data-require-permission="files:write" onclick="saveChatFilesEdit()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <div id="chat-files-rename-modal" class="modal chat-files-form-modal">
        <div class="modal-content chat-files-form-modal-content chat-files-mkdir-modal-content">
            <div class="modal-header chat-files-form-modal-header">
                <h2 data-i18n="chatFilesPage.renameTitle">重命名</h2>
                <span class="modal-close chat-files-form-modal-close" onclick="closeChatFilesRenameModal()" aria-label="Close">&times;</span>
            </div>
            <div class="modal-body chat-files-mkdir-body">
                <div class="chat-files-mkdir-location">
                    <div class="chat-files-mkdir-location-caption" data-i18n="chatFilesPage.renameCurrentFile">当前文件</div>
                    <div class="chat-files-mkdir-path-box">
                        <code class="chat-files-mkdir-path" id="chat-files-rename-path-hint"></code>
                    </div>
                </div>
                <label class="chat-files-rename-label chat-files-mkdir-label">
                    <span class="chat-files-mkdir-field-name">
                        <svg class="chat-files-mkdir-field-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
                        <span data-i18n="chatFilesPage.newFileName">新文件名</span>
                    </span>
                    <input type="text" id="chat-files-rename-input" class="form-control chat-files-mkdir-input" autocomplete="off" />
                </label>
            </div>
            <div class="modal-footer chat-files-mkdir-footer">
                <button type="button" class="btn-secondary chat-files-mkdir-btn-cancel" onclick="closeChatFilesRenameModal()" data-i18n="common.cancel">取消</button>
                <button type="button" class="btn-primary chat-files-mkdir-btn-submit" onclick="submitChatFilesRename()" data-i18n="common.ok">确定</button>
            </div>
        </div>
    </div>

    <div id="chat-files-mkdir-modal" class="modal chat-files-form-modal">
        <div class="modal-content chat-files-form-modal-content chat-files-mkdir-modal-content">
            <div class="modal-header chat-files-form-modal-header">
                <h2 data-i18n="chatFilesPage.newFolderTitle">新建文件夹</h2>
                <span class="modal-close chat-files-form-modal-close" onclick="closeChatFilesMkdirModal()" aria-label="Close">&times;</span>
            </div>
            <div class="modal-body chat-files-mkdir-body">
                <div class="chat-files-mkdir-location" aria-live="polite">
                    <div class="chat-files-mkdir-location-caption" data-i18n="chatFilesPage.newFolderLocation">位置</div>
                    <div class="chat-files-mkdir-path-box">
                        <code class="chat-files-mkdir-path" id="chat-files-mkdir-parent-hint">chat_uploads</code>
                    </div>
                </div>
                <label class="chat-files-rename-label chat-files-mkdir-label">
                    <span class="chat-files-mkdir-field-name">
                        <svg class="chat-files-mkdir-field-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
                        <span data-i18n="chatFilesPage.newFolderNameLabel">文件夹名称</span>
                    </span>
                    <input type="text" id="chat-files-mkdir-input" class="form-control chat-files-mkdir-input" data-i18n="chatFilesPage.newFolderNamePlaceholder" data-i18n-attr="placeholder" placeholder="仅名称，不含 /" autocomplete="off" />
                </label>
            </div>
            <div class="modal-footer chat-files-mkdir-footer">
                <button type="button" class="btn-secondary chat-files-mkdir-btn-cancel" onclick="closeChatFilesMkdirModal()" data-i18n="common.cancel">取消</button>
                <button type="button" class="btn-primary chat-files-mkdir-btn-submit" onclick="submitChatFilesMkdir()" data-i18n="common.ok">确定</button>
            </div>
        </div>
    </div>

    <!-- Marked.js + DOMPurify + 其他前端依赖：本地 vendor，内网/离线部署不依赖 CDN -->
    <script src="/static/vendor/marked.min.js"></script>
    <script src="/static/vendor/purify.min.js"></script>
    <script src="/static/js/sanitize-markdown.js"></script>
    <!-- Cytoscape.js for attack chain visualization -->
    <script src="/static/vendor/cytoscape.min.js"></script>
    <!-- ELK.js for high-quality DAG layout (reduces edge crossings) -->
    <script src="/static/vendor/elk.bundled.js"></script>
    <!-- SheetJS for XLSX export (info-collect) -->
    <script src="/static/vendor/xlsx.full.min.js"></script>
    <script>
        // 确保ELK对象全局可用
        if (typeof ELK === 'undefined' && typeof elk !== 'undefined') {
            window.ELK = elk;
        }
    </script>
    <!-- 工作流信息 -->
    <div id="workflow-meta-modal" class="modal" style="display: none;">
        <div class="modal-content workflow-meta-modal-content">
            <div class="modal-header workflow-meta-modal-header">
                <h2 data-i18n="workflows.metaModalTitle">工作流信息</h2>
                <span class="modal-close" onclick="closeWorkflowMetaModal()">&times;</span>
            </div>
            <div class="modal-body workflow-meta-modal-body">
                <div class="form-group workflow-meta-field">
                    <label for="workflow-name"><span data-i18n="workflows.metaName">名称</span> <span class="form-required">*</span></label>
                    <input type="text" id="workflow-name" class="form-input" data-i18n="workflows.namePlaceholder" data-i18n-attr="placeholder" placeholder="基础 Web 扫描" autocomplete="off">
                </div>
                <div class="form-group workflow-meta-field workflow-meta-id-group" id="workflow-meta-id-group">
                    <label for="workflow-id"><span data-i18n="workflows.metaId">ID</span> <span class="form-required">*</span></label>
                    <div id="workflow-id-locked" class="workflow-meta-id-locked" hidden>
                        <code id="workflow-id-display"></code>
                    </div>
                    <input type="text" id="workflow-id" class="form-input workflow-meta-id-input" placeholder="web-scan-basic" autocomplete="off">
                    <small class="workflow-meta-id-hint form-hint" data-i18n="workflows.metaIdHint">创建后不可修改，用于 API 与角色绑定</small>
                </div>
                <div class="form-group workflow-meta-field">
                    <label for="workflow-description" data-i18n="workflows.metaDescription">描述</label>
                    <input type="text" id="workflow-description" class="form-input" data-i18n="workflows.descriptionPlaceholder" data-i18n-attr="placeholder" placeholder="可选" autocomplete="off">
                </div>
                <div class="workflow-meta-enable-row">
                    <span class="workflow-meta-enable-label" data-i18n="workflows.metaEnabled">启用</span>
                    <label class="workflow-switch workflow-switch--modal" data-i18n="workflows.metaEnabledHint" data-i18n-attr="title" title="禁用后无法被角色自动触发">
                        <input type="checkbox" id="workflow-enabled" checked>
                        <span class="workflow-switch-slider" aria-hidden="true"></span>
                    </label>
                </div>
            </div>
            <div class="modal-footer workflow-meta-modal-footer">
                <button type="button" class="btn-secondary btn-small" onclick="closeWorkflowMetaModal()" data-i18n="common.cancel">取消</button>
                <button type="button" class="btn-primary btn-small" onclick="applyWorkflowMetaModal()" data-i18n="common.confirm">确认</button>
            </div>
        </div>
    </div>
    <div id="workflow-dry-run-modal" class="modal" style="display: none;" role="dialog" aria-modal="true" aria-labelledby="workflow-dry-run-modal-title" onclick="if(event.target===this)closeWorkflowDryRunModal()" onkeydown="if(event.key==='Escape')closeWorkflowDryRunModal()">
        <form class="modal-content workflow-dry-run-modal-content" onsubmit="event.preventDefault(); submitWorkflowDryRun()" onclick="event.stopPropagation()">
            <div class="modal-header workflow-dry-run-modal-header">
                <div class="workflow-dry-run-modal-title-group">
                    <span class="workflow-dry-run-modal-icon" aria-hidden="true">
                        <svg width="17" height="17" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5.4v13.2a1 1 0 0 0 1.55.84l9.2-6.6a1 1 0 0 0 0-1.68l-9.2-6.6A1 1 0 0 0 8 5.4Z"/></svg>
                    </span>
                    <h2 id="workflow-dry-run-modal-title" data-i18n="workflows.dryRun">试运行</h2>
                </div>
                <button type="button" class="modal-close" onclick="closeWorkflowDryRunModal()" data-i18n="common.close" data-i18n-attr="aria-label" data-i18n-skip-text="true" aria-label="关闭"></button>
            </div>
            <div class="modal-body workflow-dry-run-modal-body">
                <div class="form-group workflow-dry-run-modal-field">
                    <label for="workflow-dry-run-message" data-i18n="workflows.dryRunPrompt">输入试运行消息</label>
                    <input type="text" id="workflow-dry-run-message" class="form-input" value="ping" autocomplete="off" spellcheck="false">
                    <small class="form-hint" data-i18n="workflows.dryRunPromptHint">该消息将作为开始节点的 message 输入。</small>
                </div>
            </div>
            <div class="modal-footer workflow-dry-run-modal-footer">
                <button type="button" class="btn-secondary btn-small" onclick="closeWorkflowDryRunModal()" data-i18n="common.cancel">取消</button>
                <button type="submit" class="btn-primary btn-small" data-i18n="workflows.dryRun">试运行</button>
            </div>
        </form>
    </div>
    <div id="workflow-ai-modal" class="modal" style="display: none;" role="dialog" aria-modal="true" aria-labelledby="workflow-ai-modal-title" onclick="if(event.target===this)closeWorkflowAiModal()" onkeydown="if(event.key==='Escape')closeWorkflowAiModal()">
        <form class="modal-content workflow-ai-modal-content" onsubmit="event.preventDefault(); generateWorkflowFromNaturalLanguage()" onclick="event.stopPropagation()">
            <div class="modal-header workflow-ai-modal-header">
                <div>
                    <h2 id="workflow-ai-modal-title" data-i18n="workflows.ai.title">用自然语言创建工作流</h2>
                    <p class="workflow-ai-subtitle" data-i18n="workflows.ai.subtitle">AI 会生成可编辑草稿，不会自动保存或运行。</p>
                </div>
                <button type="button" class="modal-close" onclick="closeWorkflowAiModal()" data-i18n="common.close" data-i18n-attr="aria-label" data-i18n-skip-text="true" aria-label="关闭"></button>
            </div>
            <div class="modal-body workflow-ai-modal-body">
                <div class="form-group workflow-ai-prompt-field">
                    <label for="workflow-ai-prompt" data-i18n="workflows.ai.promptLabel">工作流需求</label>
                    <textarea id="workflow-ai-prompt" class="form-input" rows="5" data-i18n="workflows.ai.promptPlaceholder" data-i18n-attr="placeholder" placeholder="例如：持续监控一个域名的子域名、证书和暴露页面，发现新增资产后生成报告"></textarea>
                </div>
                <div class="workflow-ai-examples" aria-label="示例需求" data-i18n="workflows.ai.examplesLabel" data-i18n-attr="aria-label">
                    <button type="button" class="btn-secondary btn-small" onclick="useWorkflowAiExample('domainMonitor')" data-i18n="workflows.ai.exampleDomain">域名监控</button>
                    <button type="button" class="btn-secondary btn-small" onclick="useWorkflowAiExample('reportReview')" data-i18n="workflows.ai.exampleReport">报告审批</button>
                    <button type="button" class="btn-secondary btn-small" onclick="useWorkflowAiExample('assetTriage')" data-i18n="workflows.ai.exampleTriage">资产研判</button>
                </div>
                <div class="workflow-ai-options">
                    <label><input type="checkbox" id="workflow-ai-include-objective" checked> <span data-i18n="workflows.ai.includeObjective">同时生成 objective 配置</span></label>
                    <label><input type="checkbox" id="workflow-ai-allow-schedule"> <span data-i18n="workflows.ai.allowSchedule">允许生成定时触发建议</span></label>
                    <label><input type="checkbox" id="workflow-ai-allow-high-risk"> <span data-i18n="workflows.ai.allowHighRisk">允许包含高风险节点草稿</span></label>
                </div>
                <div id="workflow-ai-progress" class="workflow-ai-progress" hidden aria-live="polite"></div>
                <div id="workflow-ai-result" class="workflow-ai-result" aria-live="polite"></div>
            </div>
            <div class="modal-footer workflow-ai-modal-footer">
                <button type="button" class="btn-secondary btn-small" onclick="closeWorkflowAiModal()" data-i18n="common.cancel">取消</button>
                <button id="workflow-ai-apply-btn" type="button" class="btn-secondary btn-small" onclick="applyWorkflowAiDraft()" disabled data-i18n="workflows.ai.apply">渲染到画布</button>
                <button id="workflow-ai-generate-btn" type="submit" class="btn-primary btn-small" data-i18n="workflows.ai.generate">生成草稿</button>
            </div>
        </form>
    </div>
    <div id="workflow-package-import-modal" class="modal workflow-package-modal" style="display: none;" role="dialog" aria-modal="true" aria-labelledby="workflow-package-import-title">
        <div class="modal-content workflow-package-modal-content">
            <div class="modal-header workflow-package-modal-header">
                <div class="workflow-package-title-group">
                    <span class="workflow-package-title-icon" aria-hidden="true">
                        <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12"/><path d="m7 10 5 5 5-5"/><path d="M5 19h14"/></svg>
                    </span>
                    <div>
                        <div class="workflow-package-title-line">
                            <h2 id="workflow-package-import-title" data-i18n="workflows.package.title">导入本地包</h2>
                            <span class="workflow-package-safe-badge" data-i18n="workflows.package.safeBadge">安全预检</span>
                        </div>
                        <p class="workflow-package-subtitle" data-i18n="workflows.package.preflightHint">先检查包内容与冲突，再由你确认是否导入</p>
                    </div>
                </div>
                <span class="modal-close" onclick="closeWorkflowPackageImportModal()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label">&times;</span>
            </div>
            <div class="workflow-package-steps" aria-label="导入步骤" data-i18n="workflows.package.stepsLabel" data-i18n-attr="aria-label">
                <span class="is-active" id="workflow-package-step-inspection"><b>1</b><span><strong data-i18n="workflows.package.stepInspection">上传与预检</strong><small data-i18n="workflows.package.stepInspectionHint">校验格式、内容与版本</small></span></span>
                <span id="workflow-package-step-import"><b>2</b><span><strong data-i18n="workflows.package.stepImport">处理冲突与导入</strong><small data-i18n="workflows.package.stepImportHint">确认处理方式并完成导入</small></span></span>
            </div>
            <div class="modal-body workflow-package-modal-body">
                <section class="workflow-package-pane workflow-package-pane--inspection">
                    <div class="workflow-package-pane-heading">
                        <div>
                            <span class="workflow-package-eyebrow" data-i18n="workflows.package.packageEyebrow">本地工作流包</span>
                            <h3 data-i18n="workflows.package.packageTitle">选择需要导入的文件</h3>
                        </div>
                        <span class="workflow-package-format-pill">.CSAPKG.ZIP</span>
                    </div>
                    <input id="workflow-package-file-input" type="file" accept=".csapkg.zip,application/zip" hidden onchange="onWorkflowPackageFileSelected()">
                    <div id="workflow-package-dropzone" class="workflow-package-dropzone" role="button" tabindex="0" aria-controls="workflow-package-file-input" aria-describedby="workflow-package-file-hint" onclick="openWorkflowPackageFilePicker()" onkeydown="onWorkflowPackageDropzoneKeydown(event)" ondragenter="onWorkflowPackageDragEnter(event)" ondragover="onWorkflowPackageDragOver(event)" ondragleave="onWorkflowPackageDragLeave(event)" ondrop="onWorkflowPackageDrop(event)">
                        <span class="workflow-package-upload-icon" aria-hidden="true">
                            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M12 16V4"/><path d="m7 9 5-5 5 5"/><path d="M5 14v4a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-4"/></svg>
                        </span>
                        <span class="workflow-package-dropzone-copy">
                            <strong data-i18n="workflows.package.dropTitle">拖拽本地包到这里</strong>
                            <span><span data-i18n="workflows.package.dropOr">或</span> <span class="workflow-package-browse" data-i18n="workflows.package.selectFile">浏览文件</span></span>
                        </span>
                    </div>
                    <div id="workflow-package-selected-file" class="workflow-package-selected-file" hidden>
                        <span class="workflow-package-file-badge" aria-hidden="true">ZIP</span>
                        <span class="workflow-package-file-details">
                            <strong id="workflow-package-file-name" class="workflow-package-file-name"></strong>
                            <small id="workflow-package-file-size"></small>
                        </span>
                        <button type="button" class="workflow-package-file-remove" onclick="clearWorkflowPackageFile(event)" aria-label="移除文件" title="移除文件" data-i18n="workflows.package.removeFile" data-i18n-attr="aria-label,title" data-i18n-skip-text="true">&times;</button>
                    </div>
                    <p id="workflow-package-file-hint" class="workflow-package-file-hint" data-i18n="workflows.package.fileHint">仅支持单个 .csapkg.zip，文件不得超过 10 MiB。</p>
                    <button id="workflow-package-inspect-btn" type="button" class="btn-primary workflow-package-inspect-btn" onclick="inspectWorkflowPackage()" disabled data-i18n="workflows.package.inspect">上传并预检</button>
                    <div id="workflow-package-inspection" class="workflow-package-summary" aria-live="polite"></div>
                </section>
                <section class="workflow-package-pane workflow-package-pane--resolution">
                    <div class="workflow-package-pane-heading">
                        <div>
                            <span class="workflow-package-eyebrow" data-i18n="workflows.package.decisionEyebrow">导入策略</span>
                            <h3 data-i18n="workflows.package.resolutionTitle">处理方式</h3>
                        </div>
                        <span class="workflow-package-decision-status" data-i18n="workflows.package.pending">待预检</span>
                    </div>
                    <div id="workflow-package-resolution" class="workflow-package-resolution" aria-live="polite"></div>
                </section>
            </div>
            <div class="modal-footer workflow-package-modal-footer">
                <div class="workflow-package-footer-note">
                    <span aria-hidden="true">✓</span>
                    <span data-i18n="workflows.package.footerNote">导入前不会改动现有工作流</span>
                </div>
                <div class="workflow-package-footer-actions">
                    <button type="button" class="btn-secondary" onclick="closeWorkflowPackageImportModal()" data-i18n="common.cancel">取消</button>
                    <button id="workflow-package-submit-btn" type="button" class="btn-primary" onclick="submitWorkflowPackageImport()" disabled data-i18n="workflows.package.confirmImport">确认导入</button>
                </div>
            </div>
        </div>
    </div>
    <div id="workflow-package-overwrite-modal" class="modal workflow-package-modal" style="display: none;" role="dialog" aria-modal="true" aria-labelledby="workflow-package-overwrite-title">
        <div class="modal-content workflow-package-overwrite-content">
            <div class="modal-header">
                <h2 id="workflow-package-overwrite-title" data-i18n="workflows.package.overwriteTitle">确认覆盖本地工作流？</h2>
                <span class="modal-close" onclick="closeWorkflowPackageOverwriteModal()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label">&times;</span>
            </div>
            <div class="modal-body">
                <p data-i18n="workflows.package.overwriteWarning">覆盖将替换名称、描述、图定义和启用状态。本期不提供回滚。</p>
                <label class="workflow-package-confirm-check"><input id="workflow-package-overwrite-confirm" type="checkbox" onchange="updateWorkflowPackageOverwriteConfirmation()"> <span data-i18n="workflows.package.overwriteCheck">我已确认覆盖当前本地工作流</span></label>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn-secondary" onclick="closeWorkflowPackageOverwriteModal()" data-i18n="common.cancel">取消</button>
                <button id="workflow-package-overwrite-submit-btn" type="button" class="btn-primary" onclick="confirmWorkflowPackageOverwrite()" disabled data-i18n="workflows.package.overwriteConfirm">确认覆盖并导入</button>
            </div>
        </div>
    </div>
    <!-- 知识项编辑模态框 -->
    <!-- Skill模态框 -->
    <div id="skill-modal" class="modal">
        <div class="modal-content" style="max-width: 1100px;">
            <div class="modal-header">
                <h2 id="skill-modal-title" data-i18n="skillModal.addSkill">添加Skill</h2>
                <span class="modal-close" onclick="closeSkillModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="skill-name"><span data-i18n="skillModal.skillName">Skill名称</span> <span style="color: red;">*</span></label>
                    <input type="text" id="skill-name" data-i18n="skillModal.skillNamePlaceholder" data-i18n-attr="placeholder" placeholder="例如: sql-injection-testing" required />
                    <small class="form-hint" data-i18n="skillModal.skillNameHint">小写字母、数字、连字符（与 Agent Skills 的 name 一致）</small>
                </div>
                <div class="form-group">
                    <label for="skill-description"><span data-i18n="skillModal.description">描述</span> <span style="color: red;">*</span></label>
                    <input type="text" id="skill-description" data-i18n="skillModal.descriptionPlaceholder" data-i18n-attr="placeholder" placeholder="Skill的简短描述" required />
                    <small class="form-hint" data-i18n="skillModal.descriptionHint">写入 SKILL.md 的 YAML front matter（description 字段）</small>
                </div>
                <div class="form-group" id="skill-package-editor" style="display: none;">
                    <label data-i18n="skillModal.packageFiles">包内文件（标准 Agent Skills 布局）</label>
                    <small class="skill-package-tree-hint" data-i18n="skillModal.packageFilesHint">点击文件进行编辑；文件夹仅作分组展示，不可点击</small>
                    <div style="display: flex; gap: 12px; align-items: flex-start; min-height: 300px;">
                        <div id="skill-package-tree"></div>
                        <div style="flex: 1; min-width: 0;">
                            <div style="margin-bottom: 8px; font-size: 13px;">
                                <span data-i18n="skillModal.editingFile">正在编辑</span> <code id="skill-active-path">SKILL.md</code>
                            </div>
                            <div id="skill-new-file-row" style="display: flex; gap: 8px; margin-bottom: 8px; align-items: center;">
                                <input type="text" id="skill-new-file-path" data-i18n="skillModal.newFilePlaceholder" data-i18n-attr="placeholder" placeholder="新文件路径，如 FORMS.md" style="flex: 1;" />
                                <button type="button" class="btn-secondary btn-small" id="skill-new-file-btn" data-i18n="skillModal.newFile">新建文件</button>
                            </div>
                            <label for="skill-content"><span data-i18n="skillModal.contentLabel">内容</span> <span style="color: red;">*</span></label>
                            <textarea id="skill-content" rows="18" data-i18n="skillModal.contentPlaceholder" data-i18n-attr="placeholder" placeholder="输入skill内容，支持Markdown格式..." style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5; width: 100%; box-sizing: border-box;" required></textarea>
                            <small class="form-hint" id="skill-body-hint-edit" data-i18n="skillModal.bodyHintEdit" style="display: none;">选择 SKILL.md 时，此处为正文（不含 YAML 头）；保存时与上方描述一并写回标准 SKILL.md。</small>
                        </div>
                    </div>
                </div>
                <div class="form-group" id="skill-add-editor">
                    <label for="skill-content-add"><span data-i18n="skillModal.contentLabel">正文（Markdown）</span> <span style="color: red;">*</span></label>
                    <textarea id="skill-content-add" rows="18" data-i18n="skillModal.contentPlaceholderAdd" data-i18n-attr="placeholder" placeholder="SKILL.md 正文（无需手写 front matter，由名称与描述自动生成）..." style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5; width: 100%; box-sizing: border-box;" required></textarea>
                    <small class="form-hint" data-i18n="skillModal.contentHintAdd">创建时只需填写正文；保存后生成标准 SKILL.md（含 YAML 头）。开源技能包可直接放入 skills/&lt;name&gt;/ 使用。</small>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeSkillModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="skills:write" onclick="saveSkill()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <div id="knowledge-item-modal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2 id="knowledge-item-modal-title">添加知识</h2>
                <span class="modal-close" onclick="closeKnowledgeItemModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="knowledge-item-category">分类（风险类型）<span style="color: red;">*</span></label>
                    <input type="text" id="knowledge-item-category" placeholder="例如：SQL注入" required />
                </div>
                <div class="form-group">
                    <label for="knowledge-item-title">标题<span style="color: red;">*</span></label>
                    <input type="text" id="knowledge-item-title" placeholder="知识项标题" required />
                </div>
                <div class="form-group">
                    <label for="knowledge-item-content">内容（Markdown格式）<span style="color: red;">*</span></label>
                    <textarea id="knowledge-item-content" rows="20" placeholder="输入知识内容，支持Markdown格式..." style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5;" required></textarea>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeKnowledgeItemModal()">取消</button>
                <button class="btn-primary" data-require-permission="knowledge:write" onclick="saveKnowledgeItem()">保存</button>
            </div>
        </div>
    </div>

    <!-- 批量管理对话模态框 -->
    <div id="batch-manage-modal" class="modal">
        <div class="modal-content batch-manage-modal-content">
            <div class="modal-header">
                <h2 id="batch-manage-title">管理对话记录·共<span id="batch-manage-count">0</span>条</h2>
                <div class="batch-manage-header-actions">
                    <select id="batch-project-filter" class="conversation-project-filter-native" onchange="applyBatchConversationFilters()" data-i18n="batchManageModal.filterByProject" data-i18n-attr="title" title="按项目筛选">
                        <option value="" data-i18n="chat.filterAllProjects">全部项目</option>
                        <option value="__none__" data-i18n="chat.filterUnboundProjects">未绑定项目</option>
                    </select>
                    <div class="batch-search-box">
                        <input type="text" id="batch-search-input" data-i18n="batchManageModal.searchPlaceholder" data-i18n-attr="placeholder" placeholder="搜索历史记录" oninput="filterBatchConversations(this.value)" />
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <circle cx="11" cy="11" r="8" stroke="currentColor" stroke-width="2"/>
                            <path d="m21 21-4.35-4.35" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                        </svg>
                    </div>
                    <span class="modal-close" onclick="closeBatchManageModal()">&times;</span>
                </div>
            </div>
            <div class="modal-body batch-manage-body">
                <div class="batch-conversations-table">
                    <div class="batch-table-header">
                        <div class="batch-table-col-checkbox">
                            <input type="checkbox" id="batch-select-all" class="theme-checkbox" onchange="toggleSelectAllBatch()" data-i18n="batchManageModal.selectAll" data-i18n-attr="title" title="全选" />
                        </div>
                        <div class="batch-table-col-name" data-i18n="batchManageModal.conversationName">对话名称</div>
                        <div class="batch-table-col-project" data-i18n="batchManageModal.project">项目</div>
                        <div class="batch-table-col-time" data-i18n="batchManageModal.lastTime">最近一次对话时间</div>
                        <div class="batch-table-col-action" data-i18n="batchManageModal.action">操作</div>
                    </div>
                    <div id="batch-conversations-list" class="batch-conversations-list"></div>
                </div>
            </div>
            <div class="modal-footer batch-manage-footer">
                <div class="batch-footer-actions">
                    <button class="btn-secondary" onclick="closeBatchManageModal()" data-i18n="common.cancel">取消</button>
                    <button class="btn-primary" data-require-permission="chat:delete" onclick="deleteSelectedConversations()" data-i18n="batchManageModal.deleteSelected">删除所选</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 上下文菜单 -->
    <div id="conversation-context-menu" class="context-menu" style="display: none;">
        <div id="attack-chain-menu-item" class="context-menu-item" onclick="showAttackChainFromContext()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M10.5 13.5l3-3M8 8H5a4 4 0 1 0 0 8h3m8-8h3a4 4 0 0 1 0 8h-3" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span data-i18n="contextMenu.viewAttackChain">查看攻击链</span>
        </div>
        <div class="context-menu-item context-menu-item-has-submenu" onmouseenter="handleDownloadMarkdownSubmenuEnter()" onmouseleave="handleDownloadMarkdownSubmenuLeave(event)">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 3v12m0 0l-4-4m4 4l4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span data-i18n="contextMenu.downloadMarkdown">下载 Markdown</span>
            <svg class="submenu-arrow" width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M9 18l6-6-6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <div id="download-markdown-submenu" class="context-submenu" style="display: none;" onmouseenter="clearDownloadMarkdownSubmenuHideTimeout()" onmouseleave="hideDownloadMarkdownSubmenu()">
                <div class="context-submenu-item" onclick="downloadConversationMarkdownFromContext(false)">
                    <span data-i18n="contextMenu.downloadMarkdownSummary">简版</span>
                </div>
                <div class="context-submenu-item" onclick="downloadConversationMarkdownFromContext(true)">
                    <span data-i18n="contextMenu.downloadMarkdownFull">完整版</span>
                </div>
            </div>
        </div>
        <div class="context-menu-item" onclick="navigateToVulnerabilitiesForContextConversation()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M9 12l2 2 4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span data-i18n="contextMenu.viewVulnerabilities">查看漏洞</span>
        </div>
        <div class="context-menu-divider"></div>
        <div class="context-menu-item" onclick="renameConversation()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
                <path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span data-i18n="contextMenu.rename">重命名</span>
        </div>
        <div class="context-menu-item" onclick="pinConversation()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 17v5M5 17h14l-1-7H6l-1 7zM9 10V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span id="pin-conversation-menu-text" data-i18n="contextMenu.pinConversation">置顶此对话</span>
        </div>
        <div class="context-menu-item" onclick="showBatchManageModal()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <line x1="3" y1="12" x2="21" y2="12" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                <line x1="3" y1="6" x2="21" y2="6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                <line x1="3" y1="18" x2="21" y2="18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                <circle cx="8" cy="6" r="1" fill="currentColor"/>
                <circle cx="8" cy="12" r="1" fill="currentColor"/>
                <circle cx="8" cy="18" r="1" fill="currentColor"/>
            </svg>
            <span data-i18n="contextMenu.batchManage">批量管理</span>
        </div>
        <div class="context-menu-divider"></div>
        <div class="context-menu-item context-menu-item-danger" data-require-permission="chat:delete" onclick="deleteConversationFromContext()">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m3 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6h14z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
            </svg>
            <span data-i18n="contextMenu.deleteConversation">删除此对话</span>
        </div>
    </div>

    <!-- 项目列表操作菜单 -->
    <div id="projects-list-action-menu" class="context-menu" style="display: none;" role="menu">
        <div id="projects-list-menu-edit" class="context-menu-item" data-require-permission="project:write" onclick="editProjectFromListMenu()">
            <span id="projects-list-menu-edit-text"></span>
        </div>
        <div id="projects-list-menu-pin" class="context-menu-item" data-require-permission="project:write" onclick="toggleProjectPinnedFromListMenu()">
            <span id="projects-list-menu-pin-text"></span>
        </div>
        <div id="projects-list-menu-archive" class="context-menu-item" data-require-permission="project:write" onclick="toggleProjectArchiveFromListMenu()">
            <span id="projects-list-menu-archive-text"></span>
        </div>
        <div class="context-menu-divider"></div>
        <div class="context-menu-item context-menu-item-danger" data-require-permission="project:delete" onclick="deleteProjectFromListMenu()">
            <span id="projects-list-menu-delete-text"></span>
        </div>
    </div>

    <!-- 新建任务模态框 -->
    <div id="batch-import-modal" class="modal">
        <div class="modal-content" style="max-width: 800px;">
            <div class="modal-header">
                <h2 data-i18n="batchImportModal.title">新建任务</h2>
                <span class="modal-close" onclick="closeBatchImportModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="batch-queue-title" data-i18n="batchImportModal.queueTitle">任务标题</label>
                    <input type="text" id="batch-queue-title" data-i18n="batchImportModal.queueTitlePlaceholder" data-i18n-attr="placeholder" placeholder="请输入任务标题（可选，用于标识和筛选）" />
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.queueTitleHint">为批量任务队列设置一个标题，方便后续查找和管理。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-role" data-i18n="batchImportModal.role">角色</label>
                    <select id="batch-queue-role">
                        <option value="" data-i18n="batchImportModal.defaultRole">默认</option>
                    </select>
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.roleHint">选择一个角色，所有任务将使用该角色的配置（提示词和工具）执行。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-project-id" data-i18n="batchImportModal.project">所属项目</label>
                    <select id="batch-queue-project-id">
                        <option value="" data-i18n="batchImportModal.projectNone">（未绑定）</option>
                    </select>
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.projectHint">可为队列绑定项目；留空则不绑定项目上下文。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-agent-mode" data-i18n="batchImportModal.agentMode">代理模式</label>
                    <select id="batch-queue-agent-mode">
                        <option value="eino_single" data-i18n="chat.agentModeEinoSingle">Eino 单代理（ADK）</option>
                        <option value="deep" data-i18n="chat.agentModeDeep">Deep（DeepAgent）</option>
                        <option value="plan_execute" data-i18n="chat.agentModePlanExecuteLabel">Plan-Execute</option>
                        <option value="supervisor" data-i18n="chat.agentModeSupervisorLabel">Supervisor</option>
                    </select>
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.agentModeHint">与对话页一致：Eino 单代理（ADK），或 Deep / Plan-Execute / Supervisor（后三种需已启用多代理）。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-concurrency" data-i18n="batchImportModal.concurrency">并发数</label>
                    <input type="number" id="batch-queue-concurrency" min="1" max="8" value="1" style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; font-size: 0.875rem;" />
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.concurrencyHint">同时执行的子任务数量（1-8）。默认 1 为串行；含扫描类工具时建议 1-2。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-schedule-mode" data-i18n="batchImportModal.scheduleMode">调度方式</label>
                    <select id="batch-queue-schedule-mode" onchange="handleBatchScheduleModeChange()">
                        <option value="manual" data-i18n="batchImportModal.scheduleModeManual">手工执行</option>
                        <option value="cron" data-i18n="batchImportModal.scheduleModeCron">调度表达式（Cron）</option>
                    </select>
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.scheduleModeHint">手工执行用于一次性任务；Cron 用于周期任务，建议先手工验证任务正确性。</div>
                </div>
                <div class="form-group" id="batch-queue-cron-group" style="display: none;">
                    <label for="batch-queue-cron-expr"><span data-i18n="batchImportModal.cronExpr">Cron 表达式</span><span style="color: red;">*</span></label>
                    <input type="text" id="batch-queue-cron-expr" data-i18n="batchImportModal.cronExprPlaceholder" data-i18n-attr="placeholder" placeholder="例如：0 */2 * * *（每2小时执行一次）" />
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.cronExprHint">采用标准 5 段 Cron：分 时 日 月 周，例如 `0 2 * * *` 表示每天 02:00 执行。</div>
                </div>
                <div class="form-group">
                    <label for="batch-queue-execute-now" class="batch-execute-now-label">
                        <input type="checkbox" id="batch-queue-execute-now" />
                        <span data-i18n="batchImportModal.executeNow">创建后立即执行</span>
                    </label>
                    <div class="form-hint" style="margin-top: 4px;" data-i18n="batchImportModal.executeNowHint">默认不立即执行；关闭后队列保持待执行，可在需要时手动开始。</div>
                </div>
                <div class="form-group">
                    <label for="batch-tasks-input"><span data-i18n="batchImportModal.tasksList">任务列表（每行一个任务）</span><span style="color: red;">*</span></label>
                    <textarea id="batch-tasks-input" rows="15" data-i18n="batchImportModal.tasksListPlaceholderExample" data-i18n-attr="placeholder" placeholder="请输入任务列表，每行一个任务，例如：&#10;扫描 192.168.1.1 的开放端口&#10;检查 https://example.com 是否存在SQL注入&#10;枚举 example.com 的子域名" style="font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-size: 0.875rem; line-height: 1.5;"></textarea>
                    <div class="form-hint" style="margin-top: 8px;" data-i18n="batchImportModal.tasksListHintFull">提示：每行输入一个任务指令，系统将依次执行这些任务。空行会被自动忽略。</div>
                </div>
                <div class="form-group">
                    <div id="batch-import-stats" class="batch-import-stats"></div>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeBatchImportModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="tasks:write" onclick="createBatchQueue()" data-i18n="batchImportModal.createQueue">创建队列</button>
            </div>
        </div>
    </div>

    <!-- 批量任务队列详情模态框 -->
    <div id="batch-queue-detail-modal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2 id="batch-queue-detail-title" data-i18n="batchQueueDetailModal.title">批量任务队列详情</h2>
                <div style="display: flex; align-items: center; gap: 12px;">
                    <div class="modal-header-actions">
                        <button class="btn-secondary btn-small" data-require-permission="tasks:write" id="batch-queue-add-task-btn" onclick="showAddBatchTaskModal()" style="display: none;" data-i18n="batchQueueDetailModal.addTask">添加任务</button>
                        <button class="btn-primary btn-small" data-require-permission="tasks:write" id="batch-queue-start-btn" onclick="startBatchQueue()" style="display: none;" data-i18n="batchQueueDetailModal.startExecute">开始执行</button>
                        <button class="btn-primary btn-small" data-require-permission="tasks:write" id="batch-queue-rerun-btn" onclick="rerunBatchQueue()" style="display: none;" data-i18n="batchQueueDetailModal.rerunQueue">重跑一轮</button>
                        <button class="btn-secondary btn-small" data-require-permission="tasks:write" id="batch-queue-pause-btn" onclick="pauseBatchQueue()" style="display: none;" data-i18n="batchQueueDetailModal.pauseQueue">暂停队列</button>
                        <button class="btn-secondary btn-small btn-danger" data-require-permission="tasks:delete" id="batch-queue-delete-btn" onclick="deleteBatchQueue()" style="display: none;" data-i18n="batchQueueDetailModal.deleteQueue">删除队列</button>
                    </div>
                    <span class="modal-close" onclick="closeBatchQueueDetailModal()">&times;</span>
                </div>
            </div>
            <div class="modal-body">
                <div id="batch-queue-detail-content"></div>
            </div>
        </div>
    </div>

    <!-- 添加批量任务模态框 -->
    <div id="add-batch-task-modal" class="modal">
        <div class="modal-content" style="max-width: 600px;">
            <div class="modal-header">
                <h2 data-i18n="addBatchTaskModal.title">添加任务</h2>
                <span class="modal-close" onclick="closeAddBatchTaskModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="add-task-message" data-i18n="addBatchTaskModal.taskMessage">任务消息</label>
                    <textarea id="add-task-message" class="form-control" rows="5" data-i18n="addBatchTaskModal.taskMessagePlaceholder" data-i18n-attr="placeholder" placeholder="请输入任务消息"></textarea>
                </div>
                <div class="form-actions">
                    <button class="btn-primary" data-require-permission="tasks:write" onclick="saveAddBatchTask()" data-i18n="addBatchTaskModal.add">添加</button>
                    <button class="btn-secondary" onclick="closeAddBatchTaskModal()" data-i18n="common.cancel">取消</button>
                </div>
            </div>
        </div>
    </div>

    <!-- 漏洞编辑模态框 -->
    <div id="vulnerability-modal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2 id="vulnerability-modal-title" data-i18n="vulnerability.addVuln">添加漏洞</h2>
                <span class="modal-close" onclick="closeVulnerabilityModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="vulnerability-project-id" data-i18n="vulnerabilityModal.project">所属项目</label>
                    <select id="vulnerability-project-id" class="form-input">
                        <option value="" data-i18n="vulnerabilityModal.projectNone">（未绑定）</option>
                    </select>
                    <p class="form-hint" data-i18n="vulnerabilityModal.projectHint">绑定后 Agent 在项目范围内可通过 list_vulnerabilities 看到本条记录；留空则尝试从会话自动关联。</p>
                </div>
                <div class="form-group">
                    <label for="vulnerability-conversation-id"><span data-i18n="vulnerabilityModal.conversationId">会话ID</span> <span style="color: red;">*</span></label>
                    <input type="text" id="vulnerability-conversation-id" data-i18n="vulnerabilityModal.conversationIdPlaceholder" data-i18n-attr="placeholder" placeholder="输入会话ID" required />
                </div>
                <div class="form-group">
                    <label for="vulnerability-conversation-tag" data-i18n="vulnerabilityModal.conversationTag">对话标签</label>
                    <input type="text" id="vulnerability-conversation-tag" data-i18n="vulnerabilityModal.conversationTagPlaceholder" data-i18n-attr="placeholder" placeholder="如：红队演练A、客户A周报" />
                </div>
                <div class="form-group">
                    <label for="vulnerability-task-tag" data-i18n="vulnerabilityModal.taskTag">任务标签</label>
                    <input type="text" id="vulnerability-task-tag" data-i18n="vulnerabilityModal.taskTagPlaceholder" data-i18n-attr="placeholder" placeholder="如：批量扫描Q2、专项复测" />
                </div>
                <div class="form-group">
                    <label for="vulnerability-title"><span data-i18n="vulnerabilityModal.title">标题</span> <span style="color: red;">*</span></label>
                    <input type="text" id="vulnerability-title" data-i18n="vulnerabilityModal.titlePlaceholder" data-i18n-attr="placeholder" placeholder="/api/login 存在 SQL 注入" required />
                </div>
                <div class="form-group">
                    <label for="vulnerability-description"><span data-i18n="vulnerabilityModal.description">描述</span> <span style="color: red;">*</span></label>
                    <textarea id="vulnerability-description" rows="7" data-i18n="vulnerabilityModal.descriptionPlaceholder" data-i18n-attr="placeholder" placeholder="建议包含：摘要、测试环境与范围、前置条件、复现步骤、预期结果、实际结果。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-severity"><span data-i18n="vulnerabilityModal.severity">严重程度</span> <span style="color: red;">*</span></label>
                    <select id="vulnerability-severity" required>
                        <option value="" data-i18n="vulnerabilityModal.pleaseSelect">请选择</option>
                        <option value="critical" data-i18n="vulnerabilityModal.severityCritical">严重</option>
                        <option value="high" data-i18n="vulnerabilityModal.severityHigh">高危</option>
                        <option value="medium" data-i18n="vulnerabilityModal.severityMedium">中危</option>
                        <option value="low" data-i18n="vulnerabilityModal.severityLow">低危</option>
                        <option value="info" data-i18n="vulnerabilityModal.severityInfo">信息</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="vulnerability-status" data-i18n="vulnerabilityModal.status">状态</label>
                    <select id="vulnerability-status">
                        <option value="open" data-i18n="vulnerabilityModal.statusOpen">待处理</option>
                        <option value="confirmed" data-i18n="vulnerabilityModal.statusConfirmed">已确认</option>
                        <option value="fixed" data-i18n="vulnerabilityModal.statusFixed">已修复</option>
                        <option value="ignored" data-i18n="vulnerabilityModal.statusIgnored">已忽略</option>
                        <option value="false_positive" data-i18n="vulnerabilityModal.statusFalsePositive">误报</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="vulnerability-type"><span data-i18n="vulnerabilityModal.type">漏洞类型</span> <span style="color: red;">*</span></label>
                    <input type="text" id="vulnerability-type" data-i18n="vulnerabilityModal.typePlaceholder" data-i18n-attr="placeholder" placeholder="如：SQL注入、XSS、CSRF等" />
                </div>
                <div class="form-group">
                    <label for="vulnerability-target"><span data-i18n="vulnerabilityModal.target">目标</span> <span style="color: red;">*</span></label>
                    <input type="text" id="vulnerability-target" data-i18n="vulnerabilityModal.targetPlaceholder" data-i18n-attr="placeholder" placeholder="精确到 URL/IP:端口/接口路径/参数名" />
                </div>
                <div class="form-group">
                    <label for="vulnerability-preconditions" data-i18n="vulnerabilityModal.preconditions">前置条件</label>
                    <textarea id="vulnerability-preconditions" rows="3" data-i18n="vulnerabilityModal.preconditionsPlaceholder" data-i18n-attr="placeholder" placeholder="登录状态、权限、账号、Header/Cookie、特定数据、环境/版本；无则写无。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-reproduction-steps"><span data-i18n="vulnerabilityModal.reproductionSteps">复现步骤</span> <span style="color: red;">*</span></label>
                    <textarea id="vulnerability-reproduction-steps" rows="6" data-i18n="vulnerabilityModal.reproductionStepsPlaceholder" data-i18n-attr="placeholder" placeholder="按 1/2/3 编号，写清入口、参数、payload、执行命令、观察点。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-evidence"><span data-i18n="vulnerabilityModal.evidence">证据 / POC</span> <span style="color: red;">*</span></label>
                    <textarea id="vulnerability-evidence" rows="8" data-i18n="vulnerabilityModal.evidencePlaceholder" data-i18n-attr="placeholder" placeholder="原始请求/响应、curl/工具命令、截图说明、日志、DNSLog/回连记录、数据库结果、文件路径、时间戳等。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-impact"><span data-i18n="vulnerabilityModal.impact">影响</span> <span style="color: red;">*</span></label>
                    <textarea id="vulnerability-impact" rows="3" data-i18n="vulnerabilityModal.impactPlaceholder" data-i18n-attr="placeholder" placeholder="结合已验证事实说明实际影响，例如越权读取哪些数据。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-recommendation"><span data-i18n="vulnerabilityModal.recommendation">修复建议</span> <span style="color: red;">*</span></label>
                    <textarea id="vulnerability-recommendation" rows="3" data-i18n="vulnerabilityModal.recommendationPlaceholder" data-i18n-attr="placeholder" placeholder="写具体修复点和复测标准。"></textarea>
                </div>
                <div class="form-group">
                    <label for="vulnerability-retest-notes" data-i18n="vulnerabilityModal.retestNotes">复测方式</label>
                    <textarea id="vulnerability-retest-notes" rows="3" data-i18n="vulnerabilityModal.retestNotesPlaceholder" data-i18n-attr="placeholder" placeholder="修复后如何验证漏洞已关闭，包括应返回的状态码、错误信息或访问控制结果。"></textarea>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeVulnerabilityModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="vulnerability:write" onclick="saveVulnerability()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <!-- WebShell 添加连接模态框 -->
    <div id="webshell-modal" class="modal">
        <div class="modal-content" style="max-width: 560px;">
            <div class="modal-header">
                <h2 id="webshell-modal-title" data-i18n="webshell.addConnection">添加连接</h2>
                <span class="modal-close" onclick="closeWebshellModal()">&times;</span>
            </div>
            <div class="modal-body">
                <input type="hidden" id="webshell-edit-id" value="" />
                <div class="form-group">
                    <label for="webshell-url"><span data-i18n="webshell.url">Shell 地址</span> <span style="color: red;">*</span></label>
                    <input type="text" id="webshell-url" data-i18n="webshell.urlPlaceholder" data-i18n-attr="placeholder" placeholder="http(s)://target.com/shell.php" />
                </div>
                <div class="form-group">
                    <label for="webshell-password" data-i18n="webshell.password">连接密码/密钥</label>
                    <input type="text" id="webshell-password" data-i18n="webshell.passwordPlaceholder" data-i18n-attr="placeholder" placeholder="如冰蝎/蚁剑的连接密码" />
                </div>
                <div class="form-group">
                    <label for="webshell-type" data-i18n="webshell.type">Shell 类型</label>
                    <select id="webshell-type">
                        <option value="php" data-i18n="webshell.typePhp">PHP</option>
                        <option value="asp" data-i18n="webshell.typeAsp">ASP</option>
                        <option value="aspx" data-i18n="webshell.typeAspx">ASPX</option>
                        <option value="jsp" data-i18n="webshell.typeJsp">JSP</option>
                        <option value="custom" data-i18n="webshell.typeCustom">自定义</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="webshell-method" data-i18n="webshell.method">请求方式</label>
                    <select id="webshell-method">
                        <option value="post" data-i18n="webshell.methodPost">POST</option>
                        <option value="get" data-i18n="webshell.methodGet">GET</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="webshell-cmd-param" data-i18n="webshell.cmdParam">命令参数名</label>
                    <input type="text" id="webshell-cmd-param" data-i18n="webshell.cmdParamPlaceholder" data-i18n-attr="placeholder" placeholder="不填默认为 cmd，如 xxx 则请求为 xxx=命令" />
                </div>
                <div class="form-group">
                    <label for="webshell-os" data-i18n="webshell.os">目标系统</label>
                    <select id="webshell-os">
                        <option value="auto" data-i18n="webshell.osAuto">自动（按 Shell 类型推断）</option>
                        <option value="linux" data-i18n="webshell.osLinux">Linux / Unix</option>
                        <option value="windows" data-i18n="webshell.osWindows">Windows</option>
                    </select>
                    <small class="form-hint" data-i18n="webshell.osHint">决定文件管理/上传使用 Linux 还是 Windows 命令；PHP/JSP 跑在 Windows 上请选 Windows</small>
                </div>
                <div class="form-group">
                    <label for="webshell-encoding" data-i18n="webshell.encoding">响应编码</label>
                    <select id="webshell-encoding">
                        <option value="auto" data-i18n="webshell.encodingAuto">自动检测</option>
                        <option value="utf-8" data-i18n="webshell.encodingUtf8">UTF-8</option>
                        <option value="gbk" data-i18n="webshell.encodingGbk">GBK（中文 Windows）</option>
                        <option value="gb18030" data-i18n="webshell.encodingGb18030">GB18030</option>
                    </select>
                    <small class="form-hint" data-i18n="webshell.encodingHint">中文 Windows 目标若出现乱码，请切换为 GBK 或 GB18030</small>
                </div>
                <div class="form-group">
                    <label for="webshell-project-id" data-i18n="assets.project">所属项目</label>
                    <select id="webshell-project-id">
                        <option value="" data-i18n="assets.unboundProject">暂不绑定</option>
                    </select>
                </div>
                <div class="form-group">
                    <label for="webshell-remark" data-i18n="webshell.remark">备注</label>
                    <input type="text" id="webshell-remark" data-i18n="webshell.remarkPlaceholder" data-i18n-attr="placeholder" placeholder="便于识别的备注名" />
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn-secondary" id="webshell-test-btn" onclick="testWebshellConnection()" data-i18n="webshell.testConnectivity">测试连通性</button>
                <button class="btn-secondary" onclick="closeWebshellModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="webshell:write" onclick="saveWebshellConnection()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <!-- 角色选择弹窗 -->
    <div id="role-select-modal" class="modal">
        <div class="modal-content role-select-modal-content">
            <div class="modal-header">
                <h2 data-i18n="chat.rolePanelTitle">选择角色</h2>
                <span class="modal-close" onclick="closeRoleSelectModal()">&times;</span>
            </div>
            <div class="modal-body role-select-body">
                <div id="role-select-list" class="role-select-list"></div>
            </div>
        </div>
    </div>

    <!-- 角色编辑模态框 -->
    <div id="role-modal" class="modal">
        <div class="modal-content" style="max-width: 900px;">
            <div class="modal-header">
                <h2 id="role-modal-title" data-i18n="roleModal.addRole">添加角色</h2>
                <span class="modal-close" onclick="closeRoleModal()">&times;</span>
            </div>
            <div class="modal-body">
                <div class="form-group">
                    <label for="role-name"><span data-i18n="roleModal.roleName">角色名称</span> <span style="color: red;">*</span></label>
                    <input type="text" id="role-name" data-i18n="roleModal.roleNamePlaceholder" data-i18n-attr="placeholder" placeholder="输入角色名称" required />
                </div>
                <div class="form-group">
                    <label for="role-description" data-i18n="roleModal.roleDescription">角色描述</label>
                    <input type="text" id="role-description" data-i18n="roleModal.roleDescriptionPlaceholder" data-i18n-attr="placeholder" placeholder="输入角色描述" />
                </div>
                <div class="form-group">
                    <label for="role-icon" data-i18n="roleModal.roleIcon">角色图标</label>
                    <input type="text" id="role-icon" data-i18n="roleModal.roleIconPlaceholder" data-i18n-attr="placeholder" placeholder="输入emoji图标，例如: 🏆" maxlength="10" />
                    <small class="form-hint" data-i18n="roleModal.roleIconHint">输入一个emoji作为角色的图标，将显示在角色选择器中。</small>
                </div>
                <div class="form-group">
                    <label for="role-user-prompt" data-i18n="roleModal.userPrompt">用户提示词</label>
                    <textarea id="role-user-prompt" rows="10" data-i18n="roleModal.userPromptPlaceholder" data-i18n-attr="placeholder" placeholder="输入用户提示词，会在用户消息前追加此提示词..."></textarea>
                    <small class="form-hint" data-i18n="roleModal.userPromptHint">此提示词会追加到用户消息前，用于指导AI的行为。注意：这不会修改系统提示词。</small>
                </div>
                <div class="form-group">
                    <label for="role-workflow-id" data-i18n="roleModal.bindWorkflow">绑定工作流</label>
                    <select id="role-workflow-id" class="role-form-select-native">
                        <option value="" data-i18n="roleModal.noWorkflowBind">不绑定工作流</option>
                    </select>
                    <small class="form-hint" data-i18n="roleModal.bindWorkflowHint">选中工作流后，对话页使用该角色会自动触发；工作流字段由图定义 JSON 自由配置。</small>
                </div>
                <div class="form-group">
                    <label for="role-workflow-policy" data-i18n="roleModal.workflowPolicy">工作流触发策略</label>
                    <select id="role-workflow-policy" class="role-form-select-native">
                        <option value="auto" data-i18n="roleModal.workflowPolicyAuto">自动触发</option>
                        <option value="off" data-i18n="roleModal.workflowPolicyOff">关闭</option>
                    </select>
                </div>
                <div class="form-group" id="role-tools-section">
                    <label data-i18n="roleModal.relatedTools">关联的工具（可选）</label>
                    <div id="role-tools-default-hint" class="role-tools-default-hint" style="display: none;">
                        <div class="role-tools-default-info">
                            <span class="role-tools-default-icon">ℹ️</span>
                            <div class="role-tools-default-content">
                                <div class="role-tools-default-title" data-i18n="roleModal.defaultRoleToolsTitle">默认角色使用所有工具</div>
                                <div class="role-tools-default-desc" data-i18n="roleModal.defaultRoleToolsDesc">默认角色会自动使用MCP管理中启用的所有工具，无需单独配置。</div>
                            </div>
                        </div>
                    </div>
                    <div class="role-tools-controls">
                        <div class="role-tools-actions">
                            <button type="button" class="btn-secondary" onclick="selectAllRoleTools()" data-i18n="roleModal.selectAll">全选</button>
                            <button type="button" class="btn-secondary" onclick="deselectAllRoleTools()" data-i18n="roleModal.deselectAll">全不选</button>
                            <div id="role-tools-status-filter" class="tools-status-filter">
                                <button type="button" class="btn-filter active" data-filter="" onclick="filterRoleToolsByStatus('')" data-i18n="roleModal.filterRoleAll">全部</button>
                                <button type="button" class="btn-filter" data-filter="role_on" onclick="filterRoleToolsByStatus('role_on')" data-i18n="roleModal.filterRoleOn">本角色已开</button>
                                <button type="button" class="btn-filter" data-filter="role_off" onclick="filterRoleToolsByStatus('role_off')" data-i18n="roleModal.filterRoleOff">本角色已关</button>
                            </div>
                            <div class="role-tools-search-box">
                                <input type="text" id="role-tools-search" data-i18n="roleModal.searchToolsPlaceholder" data-i18n-attr="placeholder" placeholder="搜索工具..." 
                                       oninput="searchRoleTools(this.value)" 
                                       onkeypress="if(event.key === 'Enter') searchRoleTools(this.value)" />
                                <button class="role-tools-search-clear" id="role-tools-search-clear" 
                                        onclick="clearRoleToolsSearch()" style="display: none;" data-i18n="common.clearSearch" data-i18n-attr="title" title="清除搜索">
                                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                                        <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
                                        <path d="M15 9l-6 6M9 9l6 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
                                    </svg>
                                </button>
                            </div>
                        </div>
                        <div id="role-tools-stats" class="role-tools-stats"></div>
                    </div>
                    <div id="role-tools-list" class="role-tools-list">
                        <div class="tools-loading" data-i18n="roleModal.loadingTools">正在加载工具列表...</div>
                    </div>
                    <small class="form-hint" data-i18n="roleModal.relatedToolsHint">勾选要关联的工具，留空则使用MCP管理中的全部工具配置。</small>
                </div>
                <div class="form-group">
                    <label class="checkbox-label">
                        <input type="checkbox" id="role-enabled" class="modern-checkbox" checked />
                        <span class="checkbox-custom"></span>
                        <span class="checkbox-text" data-i18n="roleModal.enableRole">启用此角色</span>
                    </label>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" onclick="closeRoleModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="roles:write" onclick="saveRole()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <div id="rbac-user-modal" class="modal">
        <div class="modal-content" style="max-width: 640px;">
            <div class="modal-header">
                <h2 id="rbac-user-modal-title" data-i18n="rbac.userModalTitle">平台用户</h2>
                <span class="modal-close" onclick="closeRbacUserModal()">&times;</span>
            </div>
            <div class="modal-body">
                <input type="hidden" id="rbac-user-id">
                <div class="form-group">
                    <label for="rbac-username" data-i18n="rbac.username">用户名</label>
                    <input type="text" id="rbac-username" class="form-input" autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="rbac-display-name" data-i18n="rbac.displayName">显示名称</label>
                    <input type="text" id="rbac-display-name" class="form-input" autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="rbac-password" data-i18n="rbac.password">密码</label>
                    <input type="password" id="rbac-password" class="form-input" autocomplete="new-password" placeholder="编辑时留空表示不修改" data-i18n="rbac.passwordPlaceholder" data-i18n-attr="placeholder">
                </div>
                <div class="form-group">
                    <label class="checkbox-label">
                        <input type="checkbox" id="rbac-user-enabled" class="modern-checkbox" checked>
                        <span class="checkbox-custom"></span>
                        <span class="checkbox-text" data-i18n="rbac.enabled">启用账号</span>
                    </label>
                </div>
                <div class="form-group" id="rbac-user-roles-create-section">
                    <label data-i18n="rbac.roles">角色</label>
                    <div id="rbac-user-role-checkboxes" class="rbac-checkbox-grid"></div>
                </div>
                <div class="form-group" id="rbac-user-roles-edit-section" hidden>
                    <label data-i18n="rbac.roles">角色</label>
                    <div id="rbac-user-roles-readonly" class="rbac-user-roles-readonly"></div>
                    <p class="rbac-field-hint" data-i18n="rbac.editUserRolesHint">角色请在成员详情页的「角色权限」标签中统一管理。</p>
                    <button type="button" class="btn-secondary btn-small" onclick="openRbacRolesFromUserModal()" data-i18n="rbac.assignRolesNow">去分配角色</button>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" type="button" onclick="closeRbacUserModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="rbac:write" type="button" onclick="saveRbacUser()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <div id="rbac-role-modal" class="modal">
        <div class="modal-content" style="max-width: 840px;">
            <div class="modal-header">
                <h2 id="rbac-role-modal-title" data-i18n="rbac.roleModalTitle">平台角色</h2>
                <span class="modal-close" onclick="closeRbacRoleModal()">&times;</span>
            </div>
            <div class="modal-body">
                <input type="hidden" id="rbac-role-id">
                <div class="form-group">
                    <label for="rbac-role-name" data-i18n="rbac.roleName">角色名称</label>
                    <input type="text" id="rbac-role-name" class="form-input" autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="rbac-role-description" data-i18n="rbac.description">描述</label>
                    <input type="text" id="rbac-role-description" class="form-input" autocomplete="off">
                </div>
                <div class="form-group">
                    <label for="rbac-role-scope" data-i18n="rbac.scope">资源范围</label>
                    <select id="rbac-role-scope" class="form-select rbac-form-select">
                        <option value="all" data-i18n="rbac.scopes.all.option">全部资源 — 可访问平台内所有数据</option>
                        <option value="assigned" data-i18n="rbac.scopes.assigned.option">指定资源 — 仅访问管理员授权的数据</option>
                        <option value="own" data-i18n="rbac.scopes.own.option">本人创建 — 仅访问自己创建的数据</option>
                    </select>
                    <p id="rbac-role-scope-hint" class="rbac-field-hint" data-i18n="rbac.scopeHint">资源范围与操作权限共同决定最终访问能力。</p>
                </div>
                <div class="form-group">
                    <label data-i18n="rbac.permissions">权限</label>
                    <div class="rbac-permission-tools">
                        <input id="rbac-permission-search" class="form-input" type="search" placeholder="搜索权限，例如 project:read" data-i18n="rbac.searchPermissions" data-i18n-attr="placeholder" oninput="filterRbacPermissions(this.value)">
                        <button class="btn-secondary btn-small" type="button" onclick="selectVisibleRbacPermissions(true)" data-i18n="rbac.selectVisible">选择可见</button>
                        <button class="btn-secondary btn-small" type="button" onclick="selectVisibleRbacPermissions(false)" data-i18n="rbac.clearVisible">清空可见</button>
                    </div>
                    <div id="rbac-permission-checkboxes" class="rbac-permission-groups"></div>
                </div>
            </div>
            <div class="modal-footer">
                <button class="btn-secondary" type="button" onclick="closeRbacRoleModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="rbac:write" id="rbac-role-save-btn" type="button" onclick="saveRbacRole()" data-i18n="common.save">保存</button>
            </div>
        </div>
    </div>

    <!-- 项目管理弹窗（挂 body 下，避免被 .page overflow 裁剪） -->
    <div id="project-modal" class="modal-overlay projects-modal-overlay" style="display:none;" role="dialog" aria-modal="true" aria-labelledby="project-modal-title" onclick="if(event.target===this)closeProjectModal()">
        <div class="projects-modal-dialog" onclick="event.stopPropagation()">
            <div class="projects-modal-header">
                <div class="projects-modal-header-text">
                    <div>
                        <h3 id="project-modal-title" data-i18n="projects.modalNewTitle">新建项目</h3>
                        <p id="project-modal-subtitle" class="projects-modal-subtitle" data-i18n="projects.modalNewSubtitle">创建后可绑定对话，跨会话共享事实黑板</p>
                    </div>
                </div>
                <button type="button" class="projects-modal-close" onclick="closeProjectModal()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label" data-i18n-skip-text="true">&times;</button>
            </div>
            <div class="projects-modal-body">
                <div class="projects-form-field">
                    <label for="project-modal-name" data-i18n="projects.projectName">项目名称 <span class="required">*</span></label>
                    <input type="text" id="project-modal-name" class="form-input" maxlength="200" placeholder="例如：某客户 Web 渗透" autocomplete="off" data-i18n="projects.projectNamePlaceholder" data-i18n-attr="placeholder">
                </div>
                <div class="projects-form-field">
                    <label for="project-modal-description" data-i18n="projects.projectDescription">项目描述</label>
                    <textarea id="project-modal-description" class="form-input projects-description-textarea" rows="4" maxlength="4000" placeholder="客户/任务备注、协作说明…" data-i18n="projects.projectDescriptionPlaceholder" data-i18n-attr="placeholder"></textarea>
                    <small class="form-hint" data-i18n="projects.descriptionLengthHint">仅供团队成员查阅，Agent 不会读取；简要说明即可（最多 4000 字）。需让 Agent 知晓的内容请写入事实黑板</small>
                </div>
            </div>
            <div class="projects-modal-footer">
                <button class="btn-secondary" type="button" onclick="closeProjectModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="project:write" type="button" id="project-modal-submit-btn" onclick="saveProjectModal()" data-i18n="projects.createProject">创建项目</button>
            </div>
        </div>
    </div>

    <div id="fact-modal" class="modal-overlay projects-modal-overlay" style="display:none;" role="dialog" aria-modal="true" onclick="if(event.target===this)closeFactModal()">
        <div class="projects-modal-dialog projects-modal-dialog--wide" onclick="event.stopPropagation()">
            <div class="projects-modal-header">
                <div class="projects-modal-header-text">
                    <div>
                        <h3 id="fact-modal-title" data-i18n="projects.addFact">添加事实</h3>
                        <p class="projects-modal-subtitle" data-i18n="projects.factModalSubtitle">摘要注入黑板索引；body 沉淀攻击链与 POC，供审计复现（与漏洞记录分工）</p>
                    </div>
                </div>
                <button type="button" class="projects-modal-close" onclick="closeFactModal()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label" data-i18n-skip-text="true">&times;</button>
            </div>
            <div class="projects-modal-body">
                <div class="projects-form-field">
                    <label for="fact-modal-key">fact_key</label>
                    <input type="text" id="fact-modal-key" class="form-input" placeholder="target/primary_domain 或 finding/sqli-login" oninput="updateFactFormHints()">
                    <p class="projects-field-hint">环境类：target/、auth/、infra/、business/；发现/利用：finding/、chain/、exploit/、poc/</p>
                </div>
                <div class="projects-form-row">
                    <div class="projects-form-field">
                        <label for="fact-modal-category" data-i18n="projects.category">分类</label>
                        <select id="fact-modal-category" class="form-input" onchange="updateFactFormHints()">
                            <option value="target">target（目标）</option>
                            <option value="auth">auth（认证）</option>
                            <option value="infra">infra（基础设施）</option>
                            <option value="business">business（业务）</option>
                            <option value="finding">finding（发现）</option>
                            <option value="chain">chain（攻击链）</option>
                            <option value="exploit">exploit（利用）</option>
                            <option value="poc">poc（POC）</option>
                            <option value="note" selected>note（备注）</option>
                        </select>
                    </div>
                    <div class="projects-form-field">
                        <label for="fact-modal-confidence" data-i18n="projects.confidence">置信度</label>
                        <select id="fact-modal-confidence" class="form-input">
                            <option value="tentative">待确认</option>
                            <option value="confirmed">已确认</option>
                            <option value="deprecated">已废弃</option>
                        </select>
                    </div>
                </div>
                <div class="projects-form-field">
                    <label for="fact-modal-summary">摘要（索引一行）</label>
                    <input type="text" id="fact-modal-summary" class="form-input" maxlength="400" placeholder="什么 + 在哪 + 如何验证（勿仅写「存在 XSS」）" oninput="updateFactFormHints()">
                </div>
                <div class="projects-form-field">
                    <div class="projects-form-label-row">
                        <label for="fact-modal-body">body（可复现详情）</label>
                        <div class="projects-form-label-actions">
                            <button type="button" class="btn-link btn-small" onclick="insertFactBodyTemplate('attack')">插入攻击链模板</button>
                            <button type="button" class="btn-link btn-small" onclick="insertFactBodyTemplate('env')">插入环境模板</button>
                        </div>
                    </div>
                    <textarea id="fact-modal-body" class="form-input fact-modal-body-input" rows="14" placeholder="攻击链步骤、HTTP/命令 POC、响应现象、证据…" oninput="updateFactFormHints()"></textarea>
                    <p id="fact-modal-body-hint" class="projects-field-hint" role="status"></p>
                </div>
                <div class="projects-form-field">
                    <label class="projects-filter-check projects-pin-toggle">
                        <input type="checkbox" id="fact-modal-pinned"> <span data-i18n="projects.pinFact">置顶事实（列表与黑板索引优先）</span>
                    </label>
                </div>
                <div class="projects-form-field">
                    <label for="fact-modal-related-vuln" data-i18n="projects.relatedVulnIdLabel">关联漏洞 ID</label>
                    <input type="text" id="fact-modal-related-vuln" class="form-input" placeholder="可选" data-i18n="projects.optional" data-i18n-attr="placeholder">
                </div>
                <div class="form-group">
                    <label for="fact-modal-links" data-i18n="projects.factLinksLabel">关系边（from → 本事实）</label>
                    <textarea id="fact-modal-links" class="form-input" rows="4" placeholder="discovered_on: target/primary_domain&#10;exploits: exploit/upload-rce" data-i18n="projects.factLinksPlaceholder" data-i18n-attr="placeholder"></textarea>
                    <p class="projects-field-hint" data-i18n="projects.factLinksHint">每行一条：type: source_fact_key（来源 → 当前事实）。常用 type：discovered_on、depends_on、leads_to、enables、exploits。保存时替换全部关系边。</p>
                </div>
            </div>
            <div class="projects-modal-footer">
                <button class="btn-secondary" type="button" onclick="closeFactModal()" data-i18n="common.cancel">取消</button>
                <button class="btn-primary" data-require-permission="project:write" type="button" id="fact-modal-submit-btn" onclick="saveFactModal()" data-i18n="projects.saveFact">保存事实</button>
            </div>
        </div>
    </div>
    <div id="fact-detail-modal" class="modal-overlay projects-modal-overlay" style="display:none;" role="dialog" aria-modal="true" onclick="if(event.target===this)closeFactDetailModal()">
        <div class="projects-modal-dialog projects-modal-dialog--wide" onclick="event.stopPropagation()">
            <div class="projects-modal-header">
                <div class="projects-modal-header-text">
                    <div>
                        <h3 id="fact-detail-title" data-i18n="projects.factDetails">事实详情</h3>
                        <p id="fact-detail-meta" class="projects-modal-subtitle"></p>
                    </div>
                </div>
                <button type="button" class="projects-modal-close" onclick="closeFactDetailModal()" aria-label="关闭" data-i18n="common.close" data-i18n-attr="aria-label" data-i18n-skip-text="true">&times;</button>
            </div>
            <div class="projects-modal-body">
                <p id="fact-detail-sparse-warn" class="projects-fact-sparse-warn" hidden></p>
                <pre id="fact-detail-body" class="fact-detail-body"></pre>
            </div>
            <div class="projects-modal-footer projects-modal-footer--split">
                <div class="projects-modal-footer-left">
                    <button class="btn-secondary btn-small" type="button" id="fact-detail-link-vuln-btn" onclick="linkFactToExistingVulnerability()" hidden data-i18n="projects.linkVulnerability">关联漏洞</button>
                    <button class="btn-secondary btn-small" data-require-permission="vulnerability:write" type="button" id="fact-detail-create-vuln-btn" onclick="createVulnerabilityFromCurrentFact()" hidden data-i18n="projects.createVulnerabilityDraft">生成漏洞草稿</button>
                </div>
                <div class="projects-modal-footer-right">
                    <button class="btn-secondary" type="button" onclick="closeFactDetailModal()" data-i18n="common.close">关闭</button>
                    <button class="btn-primary" type="button" id="fact-detail-edit-btn" onclick="editFactFromDetail()" data-i18n="common.edit">编辑</button>
                </div>
            </div>
        </div>
    </div>

    <div id="robot-account-binding-modal" class="modal" role="dialog" aria-modal="true" aria-labelledby="robot-account-binding-title">
        <div class="modal-content robot-account-binding-content">
            <div class="modal-header robot-binding-header">
                <div class="robot-binding-heading">
                    <span class="robot-binding-heading-icon" aria-hidden="true">
                        <svg width="22" height="22" viewBox="0 0 24 24" fill="none"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                    </span>
                    <div>
                        <h2 id="robot-account-binding-title">绑定机器人账号</h2>
                        <p>将 IM 平台身份安全关联到当前 RBAC 用户</p>
                    </div>
                </div>
                <button type="button" class="modal-close" onclick="closeRobotAccountBinding()" aria-label="关闭"></button>
            </div>
            <div class="modal-body robot-binding-body">
                <div class="robot-binding-guide">
                    <span class="robot-binding-guide-number">1</span><span>生成一次性绑定码</span>
                    <span class="robot-binding-guide-arrow">→</span>
                    <span class="robot-binding-guide-number">2</span><span>在机器人中发送绑定命令</span>
                    <span class="robot-binding-guide-arrow">→</span>
                    <span class="robot-binding-guide-number">3</span><span>立即继承当前用户权限</span>
                </div>

                <section id="robot-binding-code-card" class="robot-binding-code-card is-empty">
                    <div class="robot-binding-code-meta">
                        <span class="robot-binding-one-time-badge">一次性安全码</span>
                        <span id="robot-binding-code-state" class="robot-binding-state">等待生成</span>
                    </div>
                    <div class="robot-binding-code-row">
                        <code id="robot-binding-code">••••-••••</code>
                        <div class="robot-binding-code-actions">
                            <button type="button" class="btn-primary" id="robot-binding-generate-btn" onclick="generateRobotBindingCode()">生成绑定码</button>
                            <button type="button" class="btn-secondary robot-binding-copy-btn" id="robot-binding-copy-btn" onclick="copyRobotBindingCode()" disabled>
                                <svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true"><rect x="9" y="9" width="11" height="11" rx="2" stroke="currentColor" stroke-width="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" stroke="currentColor" stroke-width="2"/></svg>
                                <span>复制命令</span>
                            </button>
                        </div>
                    </div>
                    <div id="robot-binding-timer" class="robot-binding-timer" hidden>
                        <div class="robot-binding-timer-copy">
                            <span id="robot-binding-expiry">请在机器人中发送绑定命令</span>
                            <strong id="robot-binding-countdown">05:00</strong>
                        </div>
                        <div class="robot-binding-progress" aria-hidden="true"><span id="robot-binding-progress-bar"></span></div>
                    </div>
                    <p class="robot-binding-security-note">
                        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10Z" stroke="currentColor" stroke-width="2"/><path d="m9 12 2 2 4-4" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
                        绑定码仅保存哈希、只能使用一次，新码会使旧码立即失效
                    </p>
                </section>

                <section class="robot-binding-list-section">
                    <div class="robot-binding-section-heading">
                        <div>
                            <h3>已绑定平台账号</h3>
                            <p>这些平台身份可使用当前用户的实时 RBAC 权限</p>
                        </div>
                        <button type="button" class="btn-secondary btn-small" onclick="loadRobotAccountBindings()">刷新</button>
                    </div>
                    <div id="robot-account-binding-list" class="robot-account-binding-list"><div class="robot-binding-list-loading">正在加载绑定信息…</div></div>
                </section>
            </div>
            <div class="modal-footer robot-binding-footer">
                <div class="robot-binding-service-hint">
                    <span class="robot-binding-service-hint-icon" aria-hidden="true">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.09a2 2 0 0 1 1 1.74v.5a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.38a2 2 0 0 0-.73-2.73l-.15-.09a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2Z" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><circle cx="12" cy="12" r="3" stroke="currentColor" stroke-width="1.8"/></svg>
                    </span>
                    <span>如需配置专用服务账号，请前往“系统设置 → 机器人设置”。</span>
                </div>
                <button type="button" class="btn-secondary" onclick="closeRobotAccountBinding()">关闭</button>
            </div>
        </div>
    </div>

    <script src="/static/vendor/i18next.min.js"></script>
    <script src="/static/js/i18n.js"></script>
    <script src="/static/js/theme.js"></script>
    <script src="/static/js/builtin-tools.js"></script>
    <script src="/static/js/auth.js?v=20260907-blocked-1"></script>
    <script src="/static/js/modal.js"></script>
    <script src="/static/js/notifications.js"></script>
    <script src="/static/js/info-collect.js?v=20260717-1"></script>
    <script src="/static/js/assets.js?v=20260717-7"></script>
    <script src="/static/js/agents.js"></script>
    <script src="/static/js/dashboard.js"></script>
    <script src="/static/js/chat-scroll.js?v=20260815-1"></script>
    <script src="/static/js/monitor.js?v=20260907-blocked-1"></script>
    <script src="/static/js/chat.js?v=20260907-blocked-1"></script>
    <script src="/static/js/chat-plan-progress.js?v=20260815-1"></script>
    <script src="/static/js/hitl.js?v=20260819-1"></script>
    <script src="/static/js/tool-guard.js?v=20260907-7"></script>
    <script src="/static/js/settings.js?v=20260717-1"></script>
    <script src="/static/js/audit-datetime-picker.js"></script>
    <script src="/static/js/audit.js"></script>
    <script src="/static/js/wechat-robot.js"></script>
    <script src="/static/vendor/xterm.js"></script>
    <script src="/static/vendor/xterm-addon-fit.js"></script>
    <script src="/static/js/terminal.js"></script>
    <script src="/static/js/knowledge.js"></script>
    <script src="/static/js/skills.js"></script>
    <script src="/static/js/fact-graph.js"></script>
    <script src="/static/js/projects.js?v=20260819-1"></script>
    <script src="/static/js/vulnerability.js?v=14"></script>
    <script src="/static/js/webshell.js?v=20260907-blocked-1"></script>
    <script src="/static/js/chat-files.js"></script>
    <script src="/static/js/tasks.js"></script>
    <script src="/static/js/workflow-package-client.js"></script>
    <script src="/static/js/workflows.js"></script>
    <script src="/static/js/roles.js"></script>
    <script src="/static/js/rbac.js"></script>
    <script src="/static/js/c2.js"></script>
    <script src="/static/js/rbac-guards.js?v=20260907-1"></script>
</body>
</html>
