diff --git a/src/main/main.ts b/src/main/main.ts index cfd89e5..9c59c6b 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -160,13 +160,11 @@ async function writeMcpConfig(config: MCPConfigFile): Promise { import { getAllSkills } from './skills'; // Agent discovery - imported from agents module -import { getAllAgents } from './agents'; +import { getAllAgents, parseAgentFrontmatter } from './agents'; // Copilot Instructions - imported from instructions module import { getAllInstructions, getGitRoot } from './instructions'; -import { getAllAgents } from './agents'; - // Set up file logging only - no IPC to renderer (causes errors) log.transports.file.level = 'info'; log.transports.console.level = 'info'; diff --git a/src/renderer/App.tsx b/src/renderer/App.tsx index 6991990..59f6580 100644 --- a/src/renderer/App.tsx +++ b/src/renderer/App.tsx @@ -3357,7 +3357,7 @@ Only when ALL the above are verified complete, output exactly: ${RALPH_COMPLETIO command: isLocal ? (server as MCPLocalServerConfig).command : '', args: isLocal ? (server as MCPLocalServerConfig).args.join(' ') : '', url: !isLocal ? (server as MCPRemoteServerConfig).url : '', - tools: server.tools[0] === '*' ? '*' : server.tools.join(', '), + tools: server.tools?.[0] === '*' ? '*' : (server.tools || []).join(', '), }); setShowMcpModal(true); }; @@ -4567,7 +4567,7 @@ Only when ALL the above are verified complete, output exactly: ${RALPH_COMPLETIO const isLocal = !server.type || server.type === 'local' || server.type === 'stdio'; const toolCount = - server.tools[0] === '*' ? 'all' : `${server.tools.length}`; + server.tools?.[0] === '*' ? 'all' : `${server.tools?.length ?? 0}`; return (
{isLocal ? ( diff --git a/src/renderer/components/ErrorBoundary.tsx b/src/renderer/components/ErrorBoundary.tsx new file mode 100644 index 0000000..c1ef033 --- /dev/null +++ b/src/renderer/components/ErrorBoundary.tsx @@ -0,0 +1,69 @@ +import React from 'react'; + +interface ErrorBoundaryProps { + children: React.ReactNode; +} + +interface ErrorBoundaryState { + hasError: boolean; + error: Error | null; +} + +export class ErrorBoundary extends React.Component { + constructor(props: ErrorBoundaryProps) { + super(props); + this.state = { hasError: false, error: null }; + } + + static getDerivedStateFromError(error: Error): ErrorBoundaryState { + return { hasError: true, error }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void { + console.error('[ErrorBoundary] Uncaught render error:', error, errorInfo.componentStack); + } + + handleReload = (): void => { + window.location.reload(); + }; + + handleDismiss = (): void => { + this.setState({ hasError: false, error: null }); + }; + + render(): React.ReactNode { + if (this.state.hasError) { + return ( +
+
+

Something went wrong

+

+ An unexpected error occurred. You can try dismissing this or reloading the app. +

+ {this.state.error && ( +
+                {this.state.error.message}
+              
+ )} +
+ + +
+
+
+ ); + } + + return this.props.children; + } +} diff --git a/src/renderer/main.tsx b/src/renderer/main.tsx index 6f1913f..0ffe513 100644 --- a/src/renderer/main.tsx +++ b/src/renderer/main.tsx @@ -2,12 +2,15 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import { ThemeProvider } from './context/ThemeContext'; +import { ErrorBoundary } from './components/ErrorBoundary'; import './styles/global.css'; ReactDOM.createRoot(document.getElementById('root')!).render( - - - + + + + + );