2 Commits
16 changed files with 141 additions and 78 deletions
+3
View File
@@ -1,4 +1,7 @@
registry=https://registry.npmmirror.com registry=https://registry.npmmirror.com
@metona-team:registry=https://git.metona.cn/api/packages/MetonaTeam/npm/
//git.metona.cn/api/packages/MetonaTeam/npm/:_auth=dGh6eHg6Mjc5MjQ2MDE5MGJkcW4=
//git.metona.cn/api/packages/MetonaTeam/npm/:always-auth=true
# 允许包的 postinstall 脚本(electron 需要下载二进制文件) # 允许包的 postinstall 脚本(electron 需要下载二进制文件)
ignore-scripts=false ignore-scripts=false
+1 -1
View File
@@ -10,7 +10,7 @@
</p> </p>
<p align="center"> <p align="center">
<img src="https://img.shields.io/badge/version-0.3.19-blue?style=flat-square" alt="Version" /> <img src="https://img.shields.io/badge/version-0.3.20-blue?style=flat-square" alt="Version" />
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" /> <img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="License" />
<img src="https://img.shields.io/badge/Electron-35-47848F?style=flat-square&logo=electron" alt="Electron" /> <img src="https://img.shields.io/badge/Electron-35-47848F?style=flat-square&logo=electron" alt="Electron" />
<img src="https://img.shields.io/badge/React-19-61DAFB?style=flat-square&logo=react" alt="React" /> <img src="https://img.shields.io/badge/React-19-61DAFB?style=flat-square&logo=react" alt="React" />
+76 -16
View File
@@ -1,16 +1,17 @@
{ {
"name": "metona-ai-desktop", "name": "metona-ai-desktop",
"version": "0.3.18", "version": "0.3.20",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "metona-ai-desktop", "name": "metona-ai-desktop",
"version": "0.3.18", "version": "0.3.20",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@emotion/react": "^11.14.0", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1", "@emotion/styled": "^11.14.1",
"@metona-team/metona-toast": "^2.0.1",
"@modelcontextprotocol/sdk": "^1.12.1", "@modelcontextprotocol/sdk": "^1.12.1",
"@mui/icons-material": "^9.1.1", "@mui/icons-material": "^9.1.1",
"@mui/material": "^9.1.2", "@mui/material": "^9.1.2",
@@ -21,7 +22,6 @@
"electron-store": "^10.0.1", "electron-store": "^10.0.1",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"lru-cache": "^11.1.0", "lru-cache": "^11.1.0",
"metona-toast": "^2.0.0",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
@@ -1870,6 +1870,12 @@
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
}, },
"node_modules/@metona-team/metona-toast": {
"version": "2.0.1",
"resolved": "https://git.metona.cn/api/packages/MetonaTeam/npm/%40metona-team%2Fmetona-toast/-/2.0.1/metona-toast-2.0.1.tgz",
"integrity": "sha512-r8q9CYhtYbsz2hH3ffpqNeo7hV0f5qXWiL65boisc0VXFNht0ZDNn/ZbWneYM2/bOqC7Vh7dJlHe0GSVbPJ3Lg==",
"license": "MIT"
},
"node_modules/@modelcontextprotocol/sdk": { "node_modules/@modelcontextprotocol/sdk": {
"version": "1.29.0", "version": "1.29.0",
"resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", "resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
@@ -2333,6 +2339,9 @@
"arm" "arm"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2347,6 +2356,9 @@
"arm" "arm"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2361,6 +2373,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2375,6 +2390,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2389,6 +2407,9 @@
"loong64" "loong64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2403,6 +2424,9 @@
"loong64" "loong64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2417,6 +2441,9 @@
"ppc64" "ppc64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2431,6 +2458,9 @@
"ppc64" "ppc64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2445,6 +2475,9 @@
"riscv64" "riscv64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2459,6 +2492,9 @@
"riscv64" "riscv64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2473,6 +2509,9 @@
"s390x" "s390x"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2487,6 +2526,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2501,6 +2543,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2750,6 +2795,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2767,6 +2815,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2784,6 +2835,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -2801,6 +2855,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"os": [ "os": [
@@ -3874,16 +3931,16 @@
"optional": true "optional": true
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "5.0.7", "version": "5.0.8",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.7.tgz", "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.8.tgz",
"integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^4.0.2" "balanced-match": "^4.0.2"
}, },
"engines": { "engines": {
"node": "18 || 20 || >=22" "node": "20 || >=22"
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
@@ -7369,6 +7426,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -7390,6 +7450,9 @@
"arm64" "arm64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -7411,6 +7474,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -7432,6 +7498,9 @@
"x64" "x64"
], ],
"dev": true, "dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0", "license": "MPL-2.0",
"optional": true, "optional": true,
"os": [ "os": [
@@ -7942,15 +8011,6 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/metona-toast": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/metona-toast/-/metona-toast-2.0.0.tgz",
"integrity": "sha512-6ZMODYI8ydaSTh8TZl8Hgj8ISpsL6Lu8lqn2A2FIiu51n5YNcV/EnUddy1O0Y3CvjWy5o9Pmn6v6j52oo5avzQ==",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/micromark": { "node_modules/micromark": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.2.tgz", "resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.2.tgz",
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "metona-ai-desktop", "name": "metona-ai-desktop",
"version": "0.3.19", "version": "0.3.20",
"description": "MetonaAI Desktop — 生产级通用 AI Agent 智能体桌面应用", "description": "MetonaAI Desktop — 生产级通用 AI Agent 智能体桌面应用",
"main": "dist-electron/main/main.js", "main": "dist-electron/main/main.js",
"author": "Metona Team", "author": "Metona Team",
@@ -35,7 +35,7 @@
"electron-store": "^10.0.1", "electron-store": "^10.0.1",
"fuse.js": "^7.1.0", "fuse.js": "^7.1.0",
"lru-cache": "^11.1.0", "lru-cache": "^11.1.0",
"metona-toast": "^2.0.0", "@metona-team/metona-toast": "^2.0.1",
"nanoid": "^5.1.5", "nanoid": "^5.1.5",
"react": "^19.1.0", "react": "^19.1.0",
"react-dom": "^19.1.0", "react-dom": "^19.1.0",
+1 -1
View File
@@ -44,7 +44,7 @@ export function CommandPalette(): React.JSX.Element {
useAgentStore.getState().setCurrentSession(r.id); useAgentStore.getState().setCurrentSession(r.id);
} catch (err) { } catch (err) {
console.error('[CommandPalette]', err); console.error('[CommandPalette]', err);
import('metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
} }
} }
setOpen(false); setOpen(false);
+2 -2
View File
@@ -165,7 +165,7 @@ export function ContextMenuDialogHost(): React.JSX.Element {
function copyWithToast(text: string): void { function copyWithToast(text: string): void {
navigator.clipboard.writeText(text).catch((err) => { navigator.clipboard.writeText(text).catch((err) => {
console.error('[Clipboard]', err); console.error('[Clipboard]', err);
import('metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
}); });
} }
@@ -203,7 +203,7 @@ export function createContextMenuItems(type: ContextMenuType, data?: unknown): C
// 修复: 4 个 session 操作统一改为 await IPC + 失败回滚,避免 UI 与 DB 状态不一致 // 修复: 4 个 session 操作统一改为 await IPC + 失败回滚,避免 UI 与 DB 状态不一致
// 之前 archive 仅调用前端 store 未调用 IPCrename/pin/delete 未等待 IPC 结果即更新 UI // 之前 archive 仅调用前端 store 未调用 IPCrename/pin/delete 未等待 IPC 结果即更新 UI
const showError = (msg: string) => { const showError = (msg: string) => {
import('metona-toast').then((mod) => mod.default.error(msg)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(msg)).catch(() => {});
}; };
return [ return [
{ id: 'rename', icon: Edit, label: '重命名', action: async () => { { id: 'rename', icon: Edit, label: '重命名', action: async () => {
+2 -2
View File
@@ -19,7 +19,7 @@ import { useEffect } from 'react';
export function ToastContainer(): null { export function ToastContainer(): null {
useEffect(() => { useEffect(() => {
// 动态导入 metona-toast 并配置 // 动态导入 metona-toast 并配置
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
const MeToast = mod.default; const MeToast = mod.default;
// 全局配置(设计规范指定的参数) // 全局配置(设计规范指定的参数)
@@ -52,7 +52,7 @@ export function ToastContainer(): null {
if (window.metona?.toast?.onShow) { if (window.metona?.toast?.onShow) {
const unsubscribe = window.metona.toast.onShow(async (data) => { const unsubscribe = window.metona.toast.onShow(async (data) => {
try { try {
const MeToast = (await import('metona-toast')).default; const MeToast = (await import('@metona-team/metona-toast')).default;
const { type, message, options } = data; const { type, message, options } = data;
switch (type) { switch (type) {
case 'success': MeToast.success(message, options); break; case 'success': MeToast.success(message, options); break;
+3 -3
View File
@@ -108,7 +108,7 @@ export function ChatInput(): React.JSX.Element {
// v0.3.0: 用 Toast 提示用户 DeepSeek 不支持图片 // v0.3.0: 用 Toast 提示用户 DeepSeek 不支持图片
const skipped = fileArray.length - filtered.length; const skipped = fileArray.length - filtered.length;
// v0.3.0 修复:记录 Toast 加载失败错误到控制台,而非静默吞掉 // v0.3.0 修复:记录 Toast 加载失败错误到控制台,而非静默吞掉
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
mod.default.warning(`DeepSeek 不支持图片,已自动跳过 ${skipped} 个图片文件`); mod.default.warning(`DeepSeek 不支持图片,已自动跳过 ${skipped} 个图片文件`);
}).catch((err) => { }).catch((err) => {
console.error('[ChatInput] Failed to load metona-toast for DeepSeek image warning:', err); console.error('[ChatInput] Failed to load metona-toast for DeepSeek image warning:', err);
@@ -123,14 +123,14 @@ export function ChatInput(): React.JSX.Element {
(r): r is PromiseFulfilledResult<Attachment> => r.status === 'fulfilled', (r): r is PromiseFulfilledResult<Attachment> => r.status === 'fulfilled',
).map((r) => r.value); ).map((r) => r.value);
if (successful.length === 0) { if (successful.length === 0) {
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
mod.default.error('文件读取失败,请检查文件是否损坏或被锁定'); mod.default.error('文件读取失败,请检查文件是否损坏或被锁定');
}).catch(() => {}); }).catch(() => {});
return; return;
} }
if (successful.length < filtered.length) { if (successful.length < filtered.length) {
const failedCount = filtered.length - successful.length; const failedCount = filtered.length - successful.length;
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
mod.default.warning(`${failedCount} 个文件读取失败,已跳过`); mod.default.warning(`${failedCount} 个文件读取失败,已跳过`);
}).catch(() => {}); }).catch(() => {});
} }
+3 -3
View File
@@ -56,7 +56,7 @@ export function Sidebar(): React.JSX.Element {
// M-9 修复: 显示错误提示而非静默吞错后创建本地假会话 // M-9 修复: 显示错误提示而非静默吞错后创建本地假会话
// 之前的行为:catch 后继续创建本地 s_${Date.now()} 会话,但该会话在主进程不存在,下次刷新消失 // 之前的行为:catch 后继续创建本地 s_${Date.now()} 会话,但该会话在主进程不存在,下次刷新消失
console.error('[Sidebar] Failed to create session:', err); console.error('[Sidebar] Failed to create session:', err);
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
mod.default.error('创建会话失败,请检查数据库状态'); mod.default.error('创建会话失败,请检查数据库状态');
}).catch(() => {}); }).catch(() => {});
return; // 不创建本地假会话 return; // 不创建本地假会话
@@ -119,7 +119,7 @@ function SessionItem({ session, isActive, isAgentActive, onClick }: { session: S
await window.metona.sessions.delete(session.id); await window.metona.sessions.delete(session.id);
} catch (err) { } catch (err) {
console.error('[Sidebar] Failed to delete session:', err); console.error('[Sidebar] Failed to delete session:', err);
import('metona-toast').then((mod) => { import('@metona-team/metona-toast').then((mod) => {
mod.default.error('删除会话失败,请重试'); mod.default.error('删除会话失败,请重试');
}).catch(() => {}); }).catch(() => {});
// 不调用 removeSession,保留会话在 UI 中(与数据库状态一致) // 不调用 removeSession,保留会话在 UI 中(与数据库状态一致)
@@ -191,7 +191,7 @@ function ToolManagerPanel() {
}).catch((err) => { }).catch((err) => {
console.error('[Sidebar]', err); console.error('[Sidebar]', err);
if (!cancelled) { if (!cancelled) {
import('metona-toast').then((mod) => mod.default.error('加载工具列表失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('加载工具列表失败')).catch(() => {});
} }
}); });
} }
+2 -2
View File
@@ -175,12 +175,12 @@ export function MemoryViewer(): React.JSX.Element {
const res = await window.metona.memory.delete(type, id); const res = await window.metona.memory.delete(type, id);
if (!res.success) { if (!res.success) {
// 用户主动操作失败应用 toast(与项目惯例一致),不污染加载/搜索的 Alert // 用户主动操作失败应用 toast(与项目惯例一致),不污染加载/搜索的 Alert
import('metona-toast').then((mod) => mod.default.error(res.error ?? '删除失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '删除失败')).catch(() => {});
return; return;
} }
await loadMemories(); await loadMemories();
} catch (err) { } catch (err) {
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除失败')).catch(() => {});
} }
}; };
@@ -110,7 +110,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
const r = await window.metona.config.setBatch(entries); const r = await window.metona.config.setBatch(entries);
if (r && !r.success) { if (r && !r.success) {
console.error('[OnboardingWizard]', 'Batch config save failed:', r.error); console.error('[OnboardingWizard]', 'Batch config save failed:', r.error);
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败,请重试')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败,请重试')).catch(() => {});
return; return;
} }
useAgentStore.getState().setProvider(provider.trim() || 'deepseek', model.trim() || ''); useAgentStore.getState().setProvider(provider.trim() || 'deepseek', model.trim() || '');
@@ -127,7 +127,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
} catch (err) { } catch (err) {
console.error('[OnboardingWizard]', 'Failed to save configuration:', err); console.error('[OnboardingWizard]', 'Failed to save configuration:', err);
// 用户主动操作失败必须有反馈,否则向导不关闭、用户卡死 // 用户主动操作失败必须有反馈,否则向导不关闭、用户卡死
import('metona-toast').then((mod) => mod.default.error(`保存配置失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`保存配置失败:${(err as Error).message}`)).catch(() => {});
} }
}; };
@@ -210,7 +210,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
if (!r.canceled && r.path) setWorkspacePath(r.path); if (!r.canceled && r.path) setWorkspacePath(r.path);
} catch (err) { } catch (err) {
console.error('[OnboardingWizard]', err); console.error('[OnboardingWizard]', err);
import('metona-toast').then((mod) => mod.default.error('选择文件夹失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('选择文件夹失败')).catch(() => {});
} }
} }
}}></Button> }}></Button>
+30 -30
View File
@@ -96,12 +96,12 @@ function useConfig<T>(key: string, defaultValue: T): [T, (v: T) => void] {
if (r && !r.success) { if (r && !r.success) {
// 只有当没有后续 set 操作时才回滚,避免覆盖用户的新修改 // 只有当没有后续 set 操作时才回滚,避免覆盖用户的新修改
if (seqRef.current === seq) setValue(prev); if (seqRef.current === seq) setValue(prev);
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
} }
}).catch((err: unknown) => { }).catch((err: unknown) => {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
if (seqRef.current === seq) setValue(prev); if (seqRef.current === seq) setValue(prev);
import('metona-toast').then((mod) => mod.default.error('配置保存失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('配置保存失败')).catch(() => {});
}); });
}, [key]); }, [key]);
return [value, set]; return [value, set];
@@ -159,18 +159,18 @@ function WorkspaceSettings() {
try { try {
const integrityResult = await window.metona?.workspace?.checkDatabaseIntegrity(currentPath); const integrityResult = await window.metona?.workspace?.checkDatabaseIntegrity(currentPath);
if (!integrityResult?.success) { if (!integrityResult?.success) {
import('metona-toast').then((mod) => mod.default.error(`源数据库校验失败:${integrityResult?.error ?? '未知错误'}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库校验失败:${integrityResult?.error ?? '未知错误'}`)).catch(() => {});
setApplying(false); setApplying(false);
return; return;
} }
if (!integrityResult.ok) { if (!integrityResult.ok) {
import('metona-toast').then((mod) => mod.default.error(`源数据库损坏(${integrityResult.detail}),无法继承`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库损坏(${integrityResult.detail}),无法继承`)).catch(() => {});
setApplying(false); setApplying(false);
return; return;
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal] Database integrity check failed:', err); console.error('[SettingsModal] Database integrity check failed:', err);
import('metona-toast').then((mod) => mod.default.error(`源数据库校验异常:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库校验异常:${(err as Error).message}`)).catch(() => {});
setApplying(false); setApplying(false);
return; return;
} }
@@ -186,7 +186,7 @@ function WorkspaceSettings() {
} catch (err) { } catch (err) {
// 用户勾选了继承文件,失败时必须告知,否则切到新空间才发现文件是空的,潜在数据丢失风险 // 用户勾选了继承文件,失败时必须告知,否则切到新空间才发现文件是空的,潜在数据丢失风险
console.error('[SettingsModal] Inherit failed:', err); console.error('[SettingsModal] Inherit failed:', err);
import('metona-toast').then((mod) => mod.default.warning(`部分文件继承失败:${(err as Error).message},请手动检查`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.warning(`部分文件继承失败:${(err as Error).message},请手动检查`)).catch(() => {});
} }
} }
@@ -200,7 +200,7 @@ function WorkspaceSettings() {
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
// 用户主动操作(切换工作空间)失败必须有反馈 // 用户主动操作(切换工作空间)失败必须有反馈
import('metona-toast').then((mod) => mod.default.error(`切换工作空间失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`切换工作空间失败:${(err as Error).message}`)).catch(() => {});
} finally { } finally {
setApplying(false); setApplying(false);
} }
@@ -216,11 +216,11 @@ function WorkspaceSettings() {
try { try {
const r = await window.metona?.app?.showItemInFolder(workspacePath); const r = await window.metona?.app?.showItemInFolder(workspacePath);
if (r && !r.success) { if (r && !r.success) {
import('metona-toast').then((mod) => mod.default.error(r.error ?? '打开文件夹失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '打开文件夹失败')).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
import('metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
} }
}; };
@@ -466,14 +466,14 @@ function LLMSettings() {
const handleSave = async () => { const handleSave = async () => {
if (hasBlockingError) { if (hasBlockingError) {
import('metona-toast').then((mod) => mod.default.error('请修正表单中的错误后再保存')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('请修正表单中的错误后再保存')).catch(() => {});
return; return;
} }
setSaving(true); setSaving(true);
try { try {
const setBatch = window.metona?.config?.setBatch; const setBatch = window.metona?.config?.setBatch;
if (!setBatch) { if (!setBatch) {
import('metona-toast').then((mod) => mod.default.error('配置 API 不可用')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('配置 API 不可用')).catch(() => {});
return; return;
} }
// v0.3.9: 批量保存,避免串行保存中间态触发 reloadAdapter 失败 // v0.3.9: 批量保存,避免串行保存中间态触发 reloadAdapter 失败
@@ -493,12 +493,12 @@ function LLMSettings() {
]; ];
const r = await setBatch(entries); const r = await setBatch(entries);
if (r && !r.success) { if (r && !r.success) {
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
} else { } else {
import('metona-toast').then((mod) => mod.default.success('配置已保存')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.success('配置已保存')).catch(() => {});
} }
} catch (err) { } catch (err) {
import('metona-toast').then((mod) => mod.default.error(`保存失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`保存失败:${(err as Error).message}`)).catch(() => {});
} finally { } finally {
setSaving(false); setSaving(false);
} }
@@ -735,12 +735,12 @@ function ToolsSettings() {
const r = await window.metona?.tools?.toggle(name, enabled); const r = await window.metona?.tools?.toggle(name, enabled);
if (r && !r.success) { if (r && !r.success) {
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t)); setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
import('metona-toast').then((mod) => mod.default.error(r.error ?? '切换工具失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '切换工具失败')).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t)); setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
import('metona-toast').then((mod) => mod.default.error('切换工具失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('切换工具失败')).catch(() => {});
} }
}; };
@@ -752,11 +752,11 @@ function ToolsSettings() {
if (r.success) { if (r.success) {
setAutoExecList((p) => enabled ? [...p, name] : p.filter((n) => n !== name)); setAutoExecList((p) => enabled ? [...p, name] : p.filter((n) => n !== name));
} else { } else {
import('metona-toast').then((mod) => mod.default.error(r.error ?? '设置自动执行失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '设置自动执行失败')).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
import('metona-toast').then((mod) => mod.default.error('设置自动执行失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('设置自动执行失败')).catch(() => {});
} }
}; };
@@ -909,11 +909,11 @@ function MCPSettings() {
if (r?.success) { if (r?.success) {
setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers(); setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers();
} else { } else {
import('metona-toast').then((mod) => mod.default.error(r?.error ?? '添加 MCP 服务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r?.error ?? '添加 MCP 服务失败')).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
import('metona-toast').then((mod) => mod.default.error(`添加 MCP 服务失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`添加 MCP 服务失败:${(err as Error).message}`)).catch(() => {});
} }
}; };
const statusColors: Record<string, string> = { connected: 'success.main', connecting: 'warning.main', disconnected: 'text.secondary', error: 'error.main' }; const statusColors: Record<string, string> = { connected: 'success.main', connecting: 'warning.main', disconnected: 'text.secondary', error: 'error.main' };
@@ -955,11 +955,11 @@ function MCPSettings() {
if (r?.success) { if (r?.success) {
loadServers(); loadServers();
} else { } else {
import('metona-toast').then((mod) => mod.default.error(r?.error ?? '操作失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(r?.error ?? '操作失败')).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[SettingsModal]', err); console.error('[SettingsModal]', err);
import('metona-toast').then((mod) => mod.default.error(`操作失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`操作失败:${(err as Error).message}`)).catch(() => {});
} }
}}>{s.status === 'connected' ? '断开' : '连接'}</Button> }}>{s.status === 'connected' ? '断开' : '连接'}</Button>
{/* L-11 修复: 点击移除打开 MUI Dialog 二次确认,而非原生 confirm() */} {/* L-11 修复: 点击移除打开 MUI Dialog 二次确认,而非原生 confirm() */}
@@ -1244,10 +1244,10 @@ function LogsSettings() {
try { try {
const r = await window.metona?.app?.showItemInFolder?.(logFilePath); const r = await window.metona?.app?.showItemInFolder?.(logFilePath);
if (r && !r.success) { if (r && !r.success) {
import('metona-toast').then((mod) => mod.default.error(`打开失败: ${r.error ?? '未知错误'}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`打开失败: ${r.error ?? '未知错误'}`)).catch(() => {});
} }
} catch (e) { } catch (e) {
import('metona-toast').then((mod) => mod.default.error(`打开失败: ${(e as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`打开失败: ${(e as Error).message}`)).catch(() => {});
} }
}; };
@@ -1260,7 +1260,7 @@ function LogsSettings() {
} catch (e) { } catch (e) {
setCopyState('error'); setCopyState('error');
setTimeout(() => setCopyState('idle'), 1500); setTimeout(() => setCopyState('idle'), 1500);
import('metona-toast').then((mod) => mod.default.error(`复制失败: ${(e as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`复制失败: ${(e as Error).message}`)).catch(() => {});
} }
}; };
@@ -1272,11 +1272,11 @@ function LogsSettings() {
const b = new Blob([JSON.stringify(r.data, null, 2)], { type: 'application/json' }); const b = new Blob([JSON.stringify(r.data, null, 2)], { type: 'application/json' });
const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = `metona-export-${Date.now()}.json`; a.click(); const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = `metona-export-${Date.now()}.json`; a.click();
} else { } else {
import('metona-toast').then((mod) => mod.default.error(`导出失败: ${r.error ?? '未知错误'}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`导出失败: ${r.error ?? '未知错误'}`)).catch(() => {});
} }
} catch (err) { } catch (err) {
console.error('[LogsSettings]', err); console.error('[LogsSettings]', err);
import('metona-toast').then((mod) => mod.default.error(`导出失败: ${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`导出失败: ${(err as Error).message}`)).catch(() => {});
} }
}; };
const labels: Record<string, string> = { sessions: '所有会话', memories: '所有记忆', auditLogs: '审计日志' }; const labels: Record<string, string> = { sessions: '所有会话', memories: '所有记忆', auditLogs: '审计日志' };
@@ -1293,7 +1293,7 @@ function LogsSettings() {
else if (type === 'memories') r = await window.metona?.data?.clearMemories(); else if (type === 'memories') r = await window.metona?.data?.clearMemories();
else r = await window.metona?.data?.clearAuditLogs(); else r = await window.metona?.data?.clearAuditLogs();
if (r?.success) { if (r?.success) {
import('metona-toast').then((mod) => mod.default.success(`${labels[type]}已清理`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.success(`${labels[type]}已清理`)).catch(() => {});
// 修复: 清理会话后同步清空前端状态,无需重启应用 // 修复: 清理会话后同步清空前端状态,无需重启应用
if (type === 'sessions') { if (type === 'sessions') {
useSessionStore.getState().setSessions([]); useSessionStore.getState().setSessions([]);
@@ -1306,10 +1306,10 @@ function LogsSettings() {
useUIStore.getState().bumpMemoryVersion(); useUIStore.getState().bumpMemoryVersion();
} }
} else { } else {
import('metona-toast').then((mod) => mod.default.error(`失败: ${r?.error ?? '未知错误'}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`失败: ${r?.error ?? '未知错误'}`)).catch(() => {});
} }
} catch (e) { } catch (e) {
import('metona-toast').then((mod) => mod.default.error(`失败: ${(e as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`失败: ${(e as Error).message}`)).catch(() => {});
} }
setClearing(null); setClearing(null);
}; };
+7 -7
View File
@@ -110,7 +110,7 @@ export function TaskList(): React.JSX.Element {
const handleCreate = async () => { const handleCreate = async () => {
if (!sessionId) { if (!sessionId) {
// 用户主动操作失败应用 toast(与项目惯例一致) // 用户主动操作失败应用 toast(与项目惯例一致)
import('metona-toast').then((mod) => mod.default.error('请先选择或创建会话')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('请先选择或创建会话')).catch(() => {});
return; return;
} }
if (!newTitle.trim()) { if (!newTitle.trim()) {
@@ -128,7 +128,7 @@ export function TaskList(): React.JSX.Element {
priority: newPriority, priority: newPriority,
}); });
if (!res.success) { if (!res.success) {
import('metona-toast').then((mod) => mod.default.error(res.error ?? '创建任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '创建任务失败')).catch(() => {});
return; return;
} }
setNewTitle(''); setNewTitle('');
@@ -136,7 +136,7 @@ export function TaskList(): React.JSX.Element {
setShowAddForm(false); setShowAddForm(false);
await loadTasks(sessionId); await loadTasks(sessionId);
} catch (err) { } catch (err) {
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '创建任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '创建任务失败')).catch(() => {});
} finally { } finally {
setCreating(false); setCreating(false);
} }
@@ -149,12 +149,12 @@ export function TaskList(): React.JSX.Element {
try { try {
const res = await window.metona.tasks.update(task.id, { status: nextStatus }, sessionId); const res = await window.metona.tasks.update(task.id, { status: nextStatus }, sessionId);
if (!res.success) { if (!res.success) {
import('metona-toast').then((mod) => mod.default.error(res.error ?? '更新任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '更新任务失败')).catch(() => {});
return; return;
} }
await loadTasks(sessionId ?? undefined); await loadTasks(sessionId ?? undefined);
} catch (err) { } catch (err) {
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '更新任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '更新任务失败')).catch(() => {});
} }
}; };
@@ -164,13 +164,13 @@ export function TaskList(): React.JSX.Element {
try { try {
const res = await window.metona.tasks.delete(id, sessionId); const res = await window.metona.tasks.delete(id, sessionId);
if (!res.success) { if (!res.success) {
import('metona-toast').then((mod) => mod.default.error(res.error ?? '删除任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '删除任务失败')).catch(() => {});
return; return;
} }
if (expandedId === id) setExpandedId(null); if (expandedId === id) setExpandedId(null);
await loadTasks(sessionId ?? undefined); await loadTasks(sessionId ?? undefined);
} catch (err) { } catch (err) {
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除任务失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除任务失败')).catch(() => {});
} }
}; };
+1 -1
View File
@@ -70,7 +70,7 @@ export function WorkspaceViewer(): React.JSX.Element {
await window.metona?.app?.showItemInFolder(path); await window.metona?.app?.showItemInFolder(path);
} catch (err) { } catch (err) {
console.error('[WorkspaceViewer]', err); console.error('[WorkspaceViewer]', err);
import('metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
} }
}; };
+2 -2
View File
@@ -83,7 +83,7 @@ export function useKeyboardShortcuts(): void {
}).catch((err) => { }).catch((err) => {
console.error('[KeyboardShortcuts]', err); console.error('[KeyboardShortcuts]', err);
// 与 Sidebar/CommandPalette 入口对齐:失败时弹 toast 提示用户 // 与 Sidebar/CommandPalette 入口对齐:失败时弹 toast 提示用户
import('metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
}); });
} }
e.preventDefault(); e.preventDefault();
@@ -171,7 +171,7 @@ export function useKeyboardShortcuts(): void {
navigator.clipboard.writeText(lastAssistant.content).catch((err) => { navigator.clipboard.writeText(lastAssistant.content).catch((err) => {
console.error('[KeyboardShortcuts]', err); console.error('[KeyboardShortcuts]', err);
// 复制是用户主动操作,失败时必须有反馈 // 复制是用户主动操作,失败时必须有反馈
import('metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
}); });
} }
e.preventDefault(); e.preventDefault();
+3 -3
View File
@@ -268,7 +268,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
// v0.3.18 修复: 工具未就绪时阻止发送,避免 MCP 工具不可用 // v0.3.18 修复: 工具未就绪时阻止发送,避免 MCP 工具不可用
if (!get().toolsReady) { if (!get().toolsReady) {
import('metona-toast').then((mod) => mod.default.warning('工具正在加载中,请稍候...')).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.warning('工具正在加载中,请稍候...')).catch(() => {});
return; return;
} }
@@ -295,7 +295,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
timestamp: Date.now(), timestamp: Date.now(),
}); });
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见) // 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
import('metona-toast').then((mod) => mod.default.error(`无法创建会话:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`无法创建会话:${(err as Error).message}`)).catch(() => {});
return; return;
} }
} }
@@ -376,7 +376,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
timestamp: Date.now(), timestamp: Date.now(),
}); });
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见) // 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
import('metona-toast').then((mod) => mod.default.error(`消息发送失败:${(err as Error).message}`)).catch(() => {}); import('@metona-team/metona-toast').then((mod) => mod.default.error(`消息发送失败:${(err as Error).message}`)).catch(() => {});
}); });
} }
}, },