From b721c5a073eef460ec9f3d1498f9e178126edd95 Mon Sep 17 00:00:00 2001 From: ftboy Date: Wed, 22 Oct 2025 16:23:14 +0800 Subject: [PATCH] =?UTF-8?q?feat(agent):=20agent=E9=85=8D=E7=BD=AE=E6=8C=81?= =?UTF-8?q?=E4=B9=85=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + agentcard-settings.json | 425 ++++++++++++++++++ src/main/events.ts | 8 + .../configPresenter/agentConfHelper.ts | 11 +- src/main/presenter/configPresenter/index.ts | 139 +++++- src/main/presenter/devicePresenter/index.ts | 3 +- src/main/presenter/syncPresenter/index.ts | 28 ++ src/renderer/shell/components/AppBar.vue | 37 +- .../src/components/agent-config/AgentCard.vue | 84 ++-- .../agent-config/CategorySidebar.vue | 3 - src/renderer/src/router/index.ts | 9 + src/renderer/src/views/Agents.vue | 15 +- .../types/presenters/legacy.presenters.d.ts | 37 ++ 13 files changed, 712 insertions(+), 88 deletions(-) create mode 100644 agentcard-settings.json diff --git a/.gitignore b/.gitignore index 8976622..eb984c9 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ runtime/**/* .env .env.local .npmrc +schemas \ No newline at end of file diff --git a/agentcard-settings.json b/agentcard-settings.json new file mode 100644 index 0000000..bdb2a55 --- /dev/null +++ b/agentcard-settings.json @@ -0,0 +1,425 @@ +{ + "$schema": "./schemas/agentcard-schema.json", + "version": "1.0.0", + "name": "Agent Card Settings", + "description": "智能体卡片配置设置", + "settings": { + "display": { + "layout": "grid", + "columns": 4, + "cardSize": "medium", + "showSkills": true, + "showProvider": true + }, + "behavior": { + "autoInstall": false, + "confirmUninstall": true, + "showInstallProgress": true, + "enableSearch": true, + "enableFiltering": true, + "enableSorting": true + }, + "categories": [ + { + "id": "all", + "name": "全部", + "icon": "lucide:grid", + "enabled": true + }, + { + "id": "development", + "name": "开发", + "icon": "lucide:code", + "enabled": true + }, + { + "id": "productivity", + "name": "生产力", + "icon": "lucide:edit-3", + "enabled": true + }, + { + "id": "analytics", + "name": "分析", + "icon": "lucide:bar-chart-3", + "enabled": true + }, + { + "id": "research", + "name": "研究", + "icon": "lucide:search", + "enabled": true + }, + { + "id": "design", + "name": "设计", + "icon": "lucide:palette", + "enabled": true + }, + { + "id": "support", + "name": "客服", + "icon": "lucide:headphones", + "enabled": true + } + ], + "defaultAgents": [ + { + "id": "code-assistant", + "name": "代码助手", + "description": "智能代码生成和审查助手", + "icon": "lucide:code", + "category": "development", + "installed": false, + "version": "1.0.0", + "provider": { + "organization": "DeepChat Team", + "url": "https://deepchat.ai" + }, + "skills": [ + { + "id": "code-generation", + "name": "代码生成", + "description": "根据需求生成高质量的代码", + "tags": ["development", "coding"], + "examples": ["生成一个React组件", "创建Python函数"], + "imputModes": ["text"], + "ouputModes": ["code"] + }, + { + "id": "code-review", + "name": "代码审查", + "description": "分析和改进代码质量", + "tags": ["development", "quality"], + "examples": ["检查代码风格", "识别潜在问题"], + "imputModes": ["code"], + "ouputModes": ["suggestions"] + }, + { + "id": "bug-detection", + "name": "bug检测", + "description": "识别和修复代码中的错误", + "tags": ["development", "debugging"], + "examples": ["查找逻辑错误", "修复语法问题"], + "imputModes": ["code"], + "ouputModes": ["fixes"] + } + ], + "mcpServers": ["Artifacts", "powerpack", "buildInFileSystem"], + "config": { + "languageSupport": ["javascript", "typescript", "python", "java"], + "maxTokens": 4096, + "temperature": 0.7 + } + }, + { + "id": "writing-assistant", + "name": "写作助手", + "description": "专业文档和内容创作助手", + "icon": "lucide:edit-3", + "category": "productivity", + "installed": true, + "version": "1.2.0", + "provider": { + "organization": "ContentAI", + "url": "https://contentai.com" + }, + "skills": [ + { + "id": "document-generation", + "name": "文档生成", + "description": "创建各种类型的文档内容", + "tags": ["writing", "content"], + "examples": ["生成报告", "创建邮件内容"], + "imputModes": ["text"], + "ouputModes": ["document"] + }, + { + "id": "grammar-check", + "name": "语法检查", + "description": "检查和纠正语法错误", + "tags": ["writing", "quality"], + "examples": ["修正语法错误", "改进句子结构"], + "imputModes": ["text"], + "ouputModes": ["corrections"] + }, + { + "id": "style-optimization", + "name": "风格优化", + "description": "优化写作风格和表达", + "tags": ["writing", "style"], + "examples": ["改进表达方式", "调整语气"], + "imputModes": ["text"], + "ouputModes": ["improved-text"] + } + ], + "mcpServers": ["Artifacts", "powerpack", "buildInFileSystem"], + "config": { + "writingStyles": ["formal", "casual", "technical", "creative"], + "maxLength": 5000, + "enableGrammarCheck": true + } + }, + { + "id": "data-analyst", + "name": "数据分析师", + "description": "数据分析和可视化智能体", + "icon": "lucide:bar-chart-3", + "category": "analytics", + "installed": false, + "version": "0.9.1", + "provider": { + "organization": "DataWorks", + "url": "https://dataworks.com" + }, + "skills": [ + { + "id": "data-analysis", + "name": "数据分析", + "description": "分析和解释数据模式", + "tags": ["analytics", "data"], + "examples": ["分析销售数据", "识别趋势"], + "imputModes": ["data"], + "ouputModes": ["insights"] + }, + { + "id": "chart-generation", + "name": "图表生成", + "description": "创建数据可视化图表", + "tags": ["analytics", "visualization"], + "examples": ["生成柱状图", "创建折线图"], + "imputModes": ["data"], + "ouputModes": ["charts"] + }, + { + "id": "trend-prediction", + "name": "趋势预测", + "description": "基于历史数据预测未来趋势", + "tags": ["analytics", "prediction"], + "examples": ["预测销售趋势", "分析市场变化"], + "imputModes": ["data"], + "ouputModes": ["predictions"] + } + ], + "mcpServers": ["Artifacts", "powerpack", "buildInFileSystem"], + "config": { + "supportedFormats": ["csv", "json", "excel"], + "chartTypes": ["bar", "line", "pie", "scatter"], + "maxDataPoints": 10000 + } + }, + { + "id": "research-assistant", + "name": "研究助手", + "description": "学术研究和文献分析助手", + "icon": "lucide:search", + "category": "research", + "installed": false, + "version": "1.1.0", + "provider": { + "organization": "ResearchLab", + "url": "https://researchlab.org" + }, + "skills": [ + { + "id": "literature-analysis", + "name": "文献分析", + "description": "分析和总结学术文献", + "tags": ["research", "academic"], + "examples": ["分析论文内容", "提取关键观点"], + "imputModes": ["text"], + "ouputModes": ["summary"] + }, + { + "id": "research-summary", + "name": "研究总结", + "description": "总结研究内容和发现", + "tags": ["research", "summary"], + "examples": ["总结研究论文", "提炼核心发现"], + "imputModes": ["text"], + "ouputModes": ["summary"] + }, + { + "id": "citation-management", + "name": "引用管理", + "description": "管理和格式化引用文献", + "tags": ["research", "citation"], + "examples": ["格式化引用", "管理参考文献"], + "imputModes": ["text"], + "ouputModes": ["formatted-citations"] + } + ], + "mcpServers": ["bochaSearch", "braveSearch", "deepchat-inmemory/deep-research-server", "Artifacts"], + "config": { + "citationStyles": ["apa", "mla", "chicago"], + "maxSources": 50, + "enableWebSearch": true + } + }, + { + "id": "design-helper", + "name": "设计助手", + "description": "UI/UX设计和创意助手", + "icon": "lucide:palette", + "category": "design", + "installed": false, + "version": "0.8.2", + "provider": { + "organization": "DesignStudio", + "url": "https://designstudio.com" + }, + "skills": [ + { + "id": "design-advice", + "name": "设计建议", + "description": "提供UI/UX设计建议", + "tags": ["design", "ui", "ux"], + "examples": ["改进界面设计", "优化用户体验"], + "imputModes": ["text", "image"], + "ouputModes": ["suggestions"] + }, + { + "id": "color-matching", + "name": "色彩搭配", + "description": "提供色彩搭配建议", + "tags": ["design", "color"], + "examples": ["选择配色方案", "调整色彩对比度"], + "imputModes": ["text"], + "ouputModes": ["color-palettes"] + }, + { + "id": "layout-optimization", + "name": "布局优化", + "description": "优化界面布局和结构", + "tags": ["design", "layout"], + "examples": ["改进页面布局", "优化信息架构"], + "imputModes": ["text", "image"], + "ouputModes": ["layout-suggestions"] + } + ], + "mcpServers": ["Artifacts", "imageServer", "powerpack"], + "config": { + "colorPalettes": ["monochrome", "complementary", "analogous"], + "designPrinciples": ["balance", "contrast", "alignment"], + "maxIterations": 10 + } + }, + { + "id": "customer-support", + "name": "客服助手", + "description": "自动客服和问题解答助手", + "icon": "lucide:headphones", + "category": "support", + "installed": false, + "version": "1.3.0", + "provider": { + "organization": "SupportAI", + "url": "https://supportai.com" + }, + "skills": [ + { + "id": "auto-response", + "name": "自动回复", + "description": "自动回复客户问题", + "tags": ["support", "automation"], + "examples": ["回答常见问题", "提供解决方案"], + "imputModes": ["text"], + "ouputModes": ["responses"] + }, + { + "id": "issue-classification", + "name": "问题分类", + "description": "分类和优先级客户问题", + "tags": ["support", "classification"], + "examples": ["分类问题类型", "确定优先级"], + "imputModes": ["text"], + "ouputModes": ["categories"] + }, + { + "id": "knowledge-base", + "name": "知识库", + "description": "基于知识库提供答案", + "tags": ["support", "knowledge"], + "examples": ["搜索解决方案", "提供文档链接"], + "imputModes": ["text"], + "ouputModes": ["answers"] + } + ], + "mcpServers": ["difyKnowledge", "ragflowKnowledge", "fastGptKnowledge", "builtinKnowledge", "Artifacts"], + "config": { + "responseTime": 5, + "supportLanguages": ["zh-CN", "en-US"], + "enableEscalation": true + } + } + ], + "sorting": { + "defaultSort": "name", + "availableSorts": [ + { + "key": "name", + "label": "名称", + "direction": "asc" + }, + { + "key": "installed", + "label": "安装状态", + "direction": "desc" + } + ] + }, + "filtering": { + "enabled": true, + "filters": [ + { + "key": "category", + "label": "分类", + "type": "select", + "multiple": false + }, + { + "key": "installed", + "label": "安装状态", + "type": "toggle", + "options": [ + { + "value": true, + "label": "已安装" + }, + { + "value": false, + "label": "未安装" + } + ] + } + ] + }, + "search": { + "enabled": true, + "placeholder": "搜索智能体...", + "fields": ["name", "description", "skills", "provider"], + "minLength": 2, + "debounce": 300 + }, + "installation": { + "confirmBeforeInstall": true, + "confirmBeforeUninstall": true, + "showProgress": true, + "autoStartAfterInstall": false, + "backupBeforeUninstall": true + }, + "notifications": { + "installSuccess": true, + "installError": true, + "uninstallSuccess": true, + "uninstallError": true, + "updateAvailable": true + } + }, + "metadata": { + "created": "2025-10-20T12:00:00Z", + "updated": "2025-10-20T12:00:00Z", + "author": "DeepChat Team", + "version": "1.0.0" + } +} \ No newline at end of file diff --git a/src/main/events.ts b/src/main/events.ts index 208e553..7db7f08 100644 --- a/src/main/events.ts +++ b/src/main/events.ts @@ -105,6 +105,14 @@ export const MCP_EVENTS = { INITIALIZED: 'mcp:initialized' // 新增:MCP初始化完成事件 } +// 智能体相关事件 +export const AGENT_EVENTS = { + AGENTS_UPDATED: 'agent:agents-updated', // 智能体列表更新 + AGENT_INSTALLED: 'agent:agent-installed', // 智能体安装 + AGENT_UNINSTALLED: 'agent:agent-uninstalled', // 智能体卸载 + AGENTS_IMPORTED: 'agent:agents-imported' // 智能体数据导入 +} + // 同步相关事件 export const SYNC_EVENTS = { BACKUP_STARTED: 'sync:backup-started', diff --git a/src/main/presenter/configPresenter/agentConfHelper.ts b/src/main/presenter/configPresenter/agentConfHelper.ts index 0e30188..d3bf6c6 100644 --- a/src/main/presenter/configPresenter/agentConfHelper.ts +++ b/src/main/presenter/configPresenter/agentConfHelper.ts @@ -17,7 +17,7 @@ export class AgentConfHelper { constructor() { this.store = new ElectronStore({ - name: 'agents', + name: 'agent-settings', defaults: { agents: [], installedAgents: [], @@ -289,8 +289,13 @@ export class AgentConfHelper { (agent) => agent.name.toLowerCase().includes(searchTerm) || agent.description.toLowerCase().includes(searchTerm) || - agent.skills.some((feature) => feature.toLowerCase().includes(searchTerm)) || - agent.author.toLowerCase().includes(searchTerm) + (agent.skills && + agent.skills.some( + (skill) => + skill.name.toLowerCase().includes(searchTerm) || + skill.description.toLowerCase().includes(searchTerm) + )) || + agent.provider?.organization?.toLowerCase().includes(searchTerm) ) } catch (error) { console.error('Failed to search agents:', error) diff --git a/src/main/presenter/configPresenter/index.ts b/src/main/presenter/configPresenter/index.ts index 24f02fc..600244d 100644 --- a/src/main/presenter/configPresenter/index.ts +++ b/src/main/presenter/configPresenter/index.ts @@ -9,7 +9,8 @@ import { Prompt, SystemPrompt, IModelConfig, - BuiltinKnowledgeConfig + BuiltinKnowledgeConfig, + Agent } from '@shared/presenter' import { ProviderChange, @@ -30,6 +31,7 @@ import { compare } from 'compare-versions' import { defaultShortcutKey, ShortcutKeySetting } from './shortcutKeySettings' import { ModelConfigHelper } from './modelConfig' import { KnowledgeConfHelper } from './knowledgeConfHelper' +import { AgentConfHelper } from './agentConfHelper' // Default system prompt constant const DEFAULT_SYSTEM_PROMPT = `You are DeepChat, a highly capable AI assistant. Your goal is to fully complete the user’s requested task before handing the conversation back to them. Keep working autonomously until the task is fully resolved. @@ -97,6 +99,7 @@ export class ConfigPresenter implements IConfigPresenter { private mcpConfHelper: McpConfHelper // Use MCP configuration helper private modelConfigHelper: ModelConfigHelper // Model configuration helper private knowledgeConfHelper: KnowledgeConfHelper // Knowledge configuration helper + private agentConfHelper: AgentConfHelper // Agent configuration helper // Model status memory cache for high-frequency read/write operations private modelStatusCache: Map = new Map() @@ -165,6 +168,9 @@ export class ConfigPresenter implements IConfigPresenter { // Initialize knowledge configuration helper this.knowledgeConfHelper = new KnowledgeConfHelper() + // Initialize agent configuration helper + this.agentConfHelper = new AgentConfHelper() + // Initialize provider models directory this.initProviderModelsDir() @@ -1429,6 +1435,137 @@ export class ConfigPresenter implements IConfigPresenter { async findMcpServerByPackage(packageName: string): Promise { return this.mcpConfHelper.findServerByPackage(packageName) } + + // ===================== 智能体配置相关方法 ===================== + + /** + * 获取所有智能体 + */ + async getAgents(): Promise { + return this.agentConfHelper.getAgents() + } + + /** + * 设置智能体列表 + */ + async setAgents(agents: Agent[]): Promise { + return this.agentConfHelper.setAgents(agents) + } + + /** + * 添加智能体 + */ + async addAgent(agent: Agent): Promise { + return this.agentConfHelper.addAgent(agent) + } + + /** + * 更新智能体 + */ + async updateAgent(agentId: string, updates: Partial): Promise { + return this.agentConfHelper.updateAgent(agentId, updates) + } + + /** + * 删除智能体 + */ + async removeAgent(agentId: string): Promise { + return this.agentConfHelper.removeAgent(agentId) + } + + /** + * 安装智能体 + */ + async installAgent(agentId: string): Promise { + await this.agentConfHelper.installAgent(agentId) + return true + } + + /** + * 卸载智能体 + */ + async uninstallAgent(agentId: string): Promise { + await this.agentConfHelper.uninstallAgent(agentId) + return true + } + + /** + * 获取已安装的智能体 + */ + async getInstalledAgents(): Promise { + return this.agentConfHelper.getInstalledAgents() + } + + /** + * 检查智能体是否已安装 + */ + async isAgentInstalled(agentId: string): Promise { + return this.agentConfHelper.isAgentInstalled(agentId) + } + + /** + * 获取智能体安装状态 + */ + async getAgentInstallStatus(agentId: string): Promise { + return this.agentConfHelper.isAgentInstalled(agentId) + } + + /** + * 根据分类获取智能体 + */ + async getAgentsByCategory(category: string): Promise { + return this.agentConfHelper.getAgentsByCategory(category) + } + + /** + * 搜索智能体 + */ + async searchAgents(query: string): Promise { + return this.agentConfHelper.searchAgents(query) + } + + /** + * 获取智能体统计信息 + */ + async getAgentStats(): Promise<{ + total: number + installed: number + byCategory: Record + }> { + return this.agentConfHelper.getAgentStats() + } + + /** + * 导入智能体数据 + */ + async importAgents(data: { agents: Agent[]; installedAgents?: string[] }): Promise { + return this.agentConfHelper.importAgents(data) + } + + /** + * 导出智能体数据 + */ + async exportAgents(): Promise<{ + agents: Agent[] + installedAgents: string[] + lastUpdateTime: number + }> { + return this.agentConfHelper.exportAgents() + } + + /** + * 获取最后更新时间 + */ + getAgentsLastUpdateTime(): number { + return this.agentConfHelper.getLastUpdateTime() + } + + /** + * 获取智能体配置助手 + */ + getAgentConfHelper(): AgentConfHelper { + return this.agentConfHelper + } } export { defaultShortcutKey } from './shortcutKeySettings' diff --git a/src/main/presenter/devicePresenter/index.ts b/src/main/presenter/devicePresenter/index.ts index 321f2cc..e5655a6 100644 --- a/src/main/presenter/devicePresenter/index.ts +++ b/src/main/presenter/devicePresenter/index.ts @@ -370,7 +370,8 @@ export class DevicePresenter implements IDevicePresenter { path.join(userDataPath, 'app-settings.json'), path.join(userDataPath, 'mcp-settings.json'), path.join(userDataPath, 'model-config.json'), - path.join(userDataPath, 'custom_prompts.json') + path.join(userDataPath, 'custom_prompts.json'), + path.join(userDataPath, 'agent-settings.json') ] configFiles.forEach((filePath) => { diff --git a/src/main/presenter/syncPresenter/index.ts b/src/main/presenter/syncPresenter/index.ts index f4422b5..21d956c 100644 --- a/src/main/presenter/syncPresenter/index.ts +++ b/src/main/presenter/syncPresenter/index.ts @@ -26,6 +26,7 @@ export class SyncPresenter implements ISyncPresenter { private readonly PROVIDER_MODELS_DIR_PATH = path.join(app.getPath('userData'), 'provider_models') private readonly DB_PATH = path.join(app.getPath('userData'), 'app_db', 'chat.db') private readonly MODEL_CONFIG_PATH = path.join(app.getPath('userData'), 'model-config.json') + private readonly AGENT_SETTINGS_PATH = path.join(app.getPath('userData'), 'agent-settings.json') constructor(configPresenter: IConfigPresenter, sqlitePresenter: ISQLitePresenter) { this.configPresenter = configPresenter @@ -151,6 +152,10 @@ export class SyncPresenter implements ISyncPresenter { const tempProviderModelsPath = path.join(app.getPath('temp'), `provider_models_${Date.now()}`) const tempMcpSettingsPath = path.join(app.getPath('temp'), `mcp_settings_${Date.now()}.json`) const tempModelConfigPath = path.join(app.getPath('temp'), `model_config_${Date.now()}.json`) + const tempAgentSettingsPath = path.join( + app.getPath('temp'), + `mcp_settings_${Date.now()}.json` + ) // 创建临时备份 if (fs.existsSync(this.DB_PATH)) { fs.copyFileSync(this.DB_PATH, tempDbPath) @@ -164,6 +169,10 @@ export class SyncPresenter implements ISyncPresenter { fs.copyFileSync(this.MCP_SETTINGS_PATH, tempMcpSettingsPath) } + if (fs.existsSync(this.AGENT_SETTINGS_PATH)) { + fs.copyFileSync(this.AGENT_SETTINGS_PATH, tempAgentSettingsPath) + } + // 备份模型配置文件 if (fs.existsSync(this.MODEL_CONFIG_PATH)) { fs.copyFileSync(this.MODEL_CONFIG_PATH, tempModelConfigPath) @@ -246,6 +255,10 @@ export class SyncPresenter implements ISyncPresenter { fs.copyFileSync(tempMcpSettingsPath, this.MCP_SETTINGS_PATH) } + if (fs.existsSync(tempAgentSettingsPath)) { + fs.copyFileSync(tempAgentSettingsPath, this.AGENT_SETTINGS_PATH) + } + if (fs.existsSync(tempProviderModelsPath)) { if (fs.existsSync(this.PROVIDER_MODELS_DIR_PATH)) { this.removeDirectory(this.PROVIDER_MODELS_DIR_PATH) @@ -332,12 +345,17 @@ export class SyncPresenter implements ISyncPresenter { syncFolderPath, `model_config_${Date.now()}.json.tmp` ) + const tempAgentSettingsBackupPath = path.join( + syncFolderPath, + `agent_settings_${Date.now()}.json.tmp` + ) const finalDbBackupPath = path.join(syncFolderPath, 'chat.db') const finalAppSettingsBackupPath = path.join(syncFolderPath, 'app-settings.json') const finalProviderModelsBackupPath = path.join(syncFolderPath, 'provider_models') const finalMcpSettingsBackupPath = path.join(syncFolderPath, 'mcp-settings.json') const finalModelConfigBackupPath = path.join(syncFolderPath, 'model-config.json') + const finalAgentSettingsBackupPath = path.join(syncFolderPath, 'agent-settings.json') // 确保数据库文件存在 if (!fs.existsSync(this.DB_PATH)) { @@ -378,6 +396,11 @@ export class SyncPresenter implements ISyncPresenter { fs.copyFileSync(this.MCP_SETTINGS_PATH, tempMcpSettingsBackupPath) } + // 备份 AGENT 设置 + if (fs.existsSync(this.AGENT_SETTINGS_PATH)) { + fs.copyFileSync(this.AGENT_SETTINGS_PATH, tempAgentSettingsBackupPath) + } + // 备份模型配置文件 if (fs.existsSync(this.MODEL_CONFIG_PATH)) { fs.copyFileSync(this.MODEL_CONFIG_PATH, tempModelConfigBackupPath) @@ -422,6 +445,10 @@ export class SyncPresenter implements ISyncPresenter { fs.unlinkSync(finalMcpSettingsBackupPath) } + if (fs.existsSync(finalAgentSettingsBackupPath)) { + fs.unlinkSync(finalAgentSettingsBackupPath) + } + // 清理之前的模型配置文件备份 if (fs.existsSync(finalModelConfigBackupPath)) { fs.unlinkSync(finalModelConfigBackupPath) @@ -431,6 +458,7 @@ export class SyncPresenter implements ISyncPresenter { fs.renameSync(tempDbBackupPath, finalDbBackupPath) fs.renameSync(tempAppSettingsBackupPath, finalAppSettingsBackupPath) fs.renameSync(tempMcpSettingsBackupPath, finalMcpSettingsBackupPath) + fs.renameSync(tempAgentSettingsBackupPath, finalAgentSettingsBackupPath) // 重命名模型配置文件 if (fs.existsSync(tempModelConfigBackupPath)) { diff --git a/src/renderer/shell/components/AppBar.vue b/src/renderer/shell/components/AppBar.vue index f412479..7745353 100644 --- a/src/renderer/shell/components/AppBar.vue +++ b/src/renderer/shell/components/AppBar.vue @@ -60,7 +60,7 @@ @@ -116,7 +116,7 @@