// 角色管理相关功能 let currentRole = localStorage.getItem('currentRole') || ''; let roles = []; let allRoleTools = []; // 存储所有工具列表(用于角色工具选择) let roleToolsPagination = { page: 1, pageSize: 20, total: 0, totalPages: 1 }; let roleToolsSearchKeyword = ''; // 工具搜索关键词 let roleToolStateMap = new Map(); // 工具状态映射:toolKey -> { enabled: boolean, ... } let roleUsesAllTools = false; // 标记角色是否使用所有工具(当没有配置tools时) let totalEnabledToolsInMCP = 0; // 已启用的工具总数(从MCP管理中获取,从API响应中获取) let roleConfiguredTools = new Set(); // 角色配置的工具列表(用于确定哪些工具应该被选中) // 对角色列表进行排序:默认角色排在第一个,其他按名称排序 function sortRoles(rolesArray) { const sortedRoles = [...rolesArray]; // 将"默认"角色分离出来 const defaultRole = sortedRoles.find(r => r.name === '默认'); const otherRoles = sortedRoles.filter(r => r.name !== '默认'); // 其他角色按名称排序,保持固定顺序 otherRoles.sort((a, b) => { const nameA = a.name || ''; const nameB = b.name || ''; return nameA.localeCompare(nameB, 'zh-CN'); }); // 将"默认"角色放在第一个,其他角色按排序后的顺序跟在后面 const result = defaultRole ? [defaultRole, ...otherRoles] : otherRoles; return result; } // 加载所有角色 async function loadRoles() { try { const response = await apiFetch('/api/roles'); if (!response.ok) { throw new Error('加载角色失败'); } const data = await response.json(); roles = data.roles || []; updateRoleSelectorDisplay(); renderRoleSelectionSidebar(); // 渲染侧边栏角色列表 return roles; } catch (error) { console.error('加载角色失败:', error); showNotification('加载角色失败: ' + error.message, 'error'); return []; } } // 处理角色变更 function handleRoleChange(roleName) { const oldRole = currentRole; currentRole = roleName || ''; localStorage.setItem('currentRole', currentRole); updateRoleSelectorDisplay(); renderRoleSelectionSidebar(); // 更新侧边栏选中状态 // 当角色切换时,如果工具列表已加载,标记为需要重新加载 // 这样下次触发@工具建议时会使用新的角色重新加载工具列表 if (oldRole !== currentRole && typeof window !== 'undefined') { // 通过设置一个标记来通知chat.js需要重新加载工具列表 window._mentionToolsRoleChanged = true; } } // 更新角色选择器显示 function updateRoleSelectorDisplay() { const roleSelectorBtn = document.getElementById('role-selector-btn'); const roleSelectorIcon = document.getElementById('role-selector-icon'); const roleSelectorText = document.getElementById('role-selector-text'); if (!roleSelectorBtn || !roleSelectorIcon || !roleSelectorText) return; let selectedRole; if (currentRole && currentRole !== '默认') { selectedRole = roles.find(r => r.name === currentRole); } else { selectedRole = roles.find(r => r.name === '默认'); } if (selectedRole) { // 使用配置中的图标,如果没有则使用默认图标 let icon = selectedRole.icon || '🔵'; // 如果 icon 是 Unicode 转义格式(\U0001F3C6),需要转换为 emoji if (icon && typeof icon === 'string') { const unicodeMatch = icon.match(/^"?\\U([0-9A-F]{8})"?$/i); if (unicodeMatch) { try { const codePoint = parseInt(unicodeMatch[1], 16); icon = String.fromCodePoint(codePoint); } catch (e) { // 如果转换失败,使用默认图标 console.warn('转换 icon Unicode 转义失败:', icon, e); icon = '🔵'; } } } roleSelectorIcon.textContent = icon; roleSelectorText.textContent = selectedRole.name || '默认'; } else { // 默认角色 roleSelectorIcon.textContent = '🔵'; roleSelectorText.textContent = '默认'; } } // 渲染主内容区域角色选择列表 function renderRoleSelectionSidebar() { const roleList = document.getElementById('role-selection-list'); if (!roleList) return; // 清空列表 roleList.innerHTML = ''; // 根据角色配置获取图标,如果没有配置则使用默认图标 function getRoleIcon(role) { if (role.icon) { // 如果 icon 是 Unicode 转义格式(\U0001F3C6),需要转换为 emoji let icon = role.icon; // 检查是否是 Unicode 转义格式(可能包含引号) const unicodeMatch = icon.match(/^"?\\U([0-9A-F]{8})"?$/i); if (unicodeMatch) { try { const codePoint = parseInt(unicodeMatch[1], 16); icon = String.fromCodePoint(codePoint); } catch (e) { // 如果转换失败,使用原值 console.warn('转换 icon Unicode 转义失败:', icon, e); } } return icon; } // 如果没有配置图标,根据角色名称的首字符生成默认图标 // 使用一些通用的默认图标 return '👤'; } // 对角色进行排序:默认角色第一个,其他按名称排序 const sortedRoles = sortRoles(roles); // 只显示已启用的角色 const enabledSortedRoles = sortedRoles.filter(r => r.enabled !== false); enabledSortedRoles.forEach(role => { const isDefaultRole = role.name === '默认'; const isSelected = isDefaultRole ? (currentRole === '' || currentRole === '默认') : (currentRole === role.name); const roleItem = document.createElement('div'); roleItem.className = 'role-selection-item-main' + (isSelected ? ' selected' : ''); roleItem.onclick = () => { selectRole(role.name); closeRoleSelectionPanel(); // 选择后自动关闭面板 }; const icon = getRoleIcon(role); // 处理默认角色的描述 let description = role.description || '暂无描述'; if (isDefaultRole && !role.description) { description = '默认角色,不额外携带用户提示词,使用默认MCP'; } roleItem.innerHTML = `