diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index f13ef1b..be29be0 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -3,6 +3,7 @@ import './index.css'; import { Sidebar } from './components/Sidebar'; import { ChatArea } from './components/ChatArea'; import { RightPanel } from './components/RightPanel'; +import { ErrorBoundary } from './components/ui/ErrorBoundary'; import { SettingsLayout } from './components/Settings/SettingsLayout'; import { AgentOnboardingWizard } from './components/AgentOnboardingWizard'; import { HandApprovalModal } from './components/HandApprovalModal'; @@ -458,7 +459,9 @@ function App() { {/* 主聊天区域 */}
- setShowDetailDrawer(true)} /> + 聊天区域加载失败
}> + setShowDetailDrawer(true)} /> + {/* 详情抽屉 - 简洁模式仅 状态/Agent/管家 */} @@ -467,7 +470,9 @@ function App() { onClose={() => setShowDetailDrawer(false)} title="详情" > - + 详情面板加载失败}> + + {/* Hand Approval Modal (global) */} @@ -502,7 +507,9 @@ function App() { /> {/* 聊天区域 */} - + 聊天区域加载失败,请刷新页面}> + + {/* 详情抽屉 - 按需显示 */} @@ -511,7 +518,9 @@ function App() { onClose={() => setShowDetailDrawer(false)} title="详情" > - + 详情面板加载失败}> + + {/* Hand Approval Modal (global) */} diff --git a/desktop/src/components/SaaS/SaaSStatus.tsx b/desktop/src/components/SaaS/SaaSStatus.tsx index d17d51b..8e94611 100644 --- a/desktop/src/components/SaaS/SaaSStatus.tsx +++ b/desktop/src/components/SaaS/SaaSStatus.tsx @@ -49,7 +49,8 @@ export function SaaSStatus({ isLoggedIn, account, saasUrl, onLogout, onLogin }: signal: AbortSignal.timeout(5000), }); setHealthOk(response.ok); - } catch { + } catch (e) { + console.warn('[SaaSStatus] Health check failed:', e); setHealthOk(false); } finally { setCheckingHealth(false); diff --git a/desktop/src/components/SaaS/TOTPSettings.tsx b/desktop/src/components/SaaS/TOTPSettings.tsx index 4489048..4ba947b 100644 --- a/desktop/src/components/SaaS/TOTPSettings.tsx +++ b/desktop/src/components/SaaS/TOTPSettings.tsx @@ -30,7 +30,8 @@ export function TOTPSettings() { setVerifyCode(''); try { await setupTotp(); - } catch { + } catch (e) { + console.warn('[TOTP] Setup failed:', e); // error already in store } }; @@ -43,7 +44,8 @@ export function TOTPSettings() { await verifyTotp(verifyCode); setVerifyCode(''); setSuccess('TOTP 已成功启用'); - } catch { + } catch (e) { + console.warn('[TOTP] Enable failed:', e); // error already in store } }; @@ -60,7 +62,8 @@ export function TOTPSettings() { setDisablePassword(''); setShowDisable(false); setSuccess('TOTP 已成功禁用'); - } catch { + } catch (e) { + console.warn('[TOTP] Disable failed:', e); // error already in store } }; diff --git a/desktop/src/components/Settings/MCPServices.tsx b/desktop/src/components/Settings/MCPServices.tsx index 9a01fc5..e8837a4 100644 --- a/desktop/src/components/Settings/MCPServices.tsx +++ b/desktop/src/components/Settings/MCPServices.tsx @@ -25,7 +25,8 @@ export function MCPServices() { try { const running = await listMcpServices(); setRunningServices(running); - } catch { + } catch (e) { + console.warn('[MCPServices] Failed to list services:', e); // MCP might not be available yet setRunningServices([]); } diff --git a/desktop/src/components/Settings/ModelsAPI.tsx b/desktop/src/components/Settings/ModelsAPI.tsx index e34ec8b..2d5bdf6 100644 --- a/desktop/src/components/Settings/ModelsAPI.tsx +++ b/desktop/src/components/Settings/ModelsAPI.tsx @@ -80,8 +80,8 @@ function loadEmbeddingConfigBase(): Omit & { apiKey: const parsed = JSON.parse(stored); return { ...parsed, apiKey: '' }; } - } catch { - // ignore + } catch (e) { + console.warn('[ModelsAPI] Failed to load embedding config:', e); } return { provider: 'local', @@ -99,8 +99,8 @@ function loadEmbeddingConfigBase(): Omit & { apiKey: function saveEmbeddingConfigBase(config: Omit): void { try { localStorage.setItem(EMBEDDING_STORAGE_KEY, JSON.stringify(config)); - } catch { - // ignore + } catch (e) { + console.warn('[ModelsAPI] Failed to save embedding config:', e); } } @@ -129,8 +129,8 @@ function loadCustomModelsBase(): CustomModel[] { if (stored) { return JSON.parse(stored); } - } catch { - // ignore + } catch (e) { + console.warn('[ModelsAPI] Failed to load model config:', e); } return []; } @@ -143,8 +143,8 @@ function saveCustomModelsBase(models: CustomModel[]): void { return rest; }); localStorage.setItem(STORAGE_KEY, JSON.stringify(sanitized)); - } catch { - // ignore + } catch (e) { + console.warn('[ModelsAPI] Failed to save model config:', e); } } diff --git a/desktop/src/components/Settings/SettingsLayout.tsx b/desktop/src/components/Settings/SettingsLayout.tsx index 96af5ab..f47c242 100644 --- a/desktop/src/components/Settings/SettingsLayout.tsx +++ b/desktop/src/components/Settings/SettingsLayout.tsx @@ -149,7 +149,14 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) { ); - case 'audit': return ; + case 'audit': return ( + 审计日志加载失败} + onError={(err, info) => console.error('[Settings] Audit page error:', err, info.componentStack)} + > + + + ); case 'tasks': return (

定时任务

@@ -159,11 +166,23 @@ export function SettingsLayout({ onBack }: SettingsLayoutProps) {
); case 'heartbeat': return ( -
- -
+ 心跳配置加载失败} + onError={(err, info) => console.error('[Settings] Heartbeat page error:', err, info.componentStack)} + > +
+ +
+
+ ); + case 'viking': return ( + 语义记忆加载失败} + onError={(err, info) => console.error('[Settings] Viking page error:', err, info.componentStack)} + > + + ); - case 'viking': return ; case 'feedback': return ; case 'about': return ; default: return ; diff --git a/desktop/src/components/VikingPanel.tsx b/desktop/src/components/VikingPanel.tsx index f44b748..3286d2e 100644 --- a/desktop/src/components/VikingPanel.tsx +++ b/desktop/src/components/VikingPanel.tsx @@ -50,7 +50,8 @@ export function VikingPanel() { try { const resources = await listVikingResources(''); setMemoryCount(resources.length); - } catch { + } catch (e) { + console.warn('[VikingPanel] Failed to list resources:', e); setMemoryCount(null); } } @@ -99,7 +100,8 @@ export function VikingPanel() { try { const fullContent = await readVikingResource(uri, 'L2'); setExpandedContent(fullContent); - } catch { + } catch (e) { + console.warn('[VikingPanel] Failed to read resource:', e); setExpandedContent(null); } finally { setIsLoadingL2(false);