@@ -22,6 +22,7 @@ import { AccountView } from "./components/account/AccountView"
2222import { useAddNonInteractiveClickListener } from "./components/ui/hooks/useNonInteractiveClick"
2323import { TooltipProvider } from "./components/ui/tooltip"
2424import { STANDARD_TOOLTIP_DELAY } from "./components/ui/standard-tooltip"
25+ import { ErrorBoundary } from "./components/common/ErrorBoundary"
2526
2627type Tab = "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
2728
@@ -169,60 +170,86 @@ const App = () => {
169170 // Do not conditionally load ChatView, it's expensive and there's state we
170171 // don't want to lose (user input, disableInput, askResponse promise, etc.)
171172 return showWelcome ? (
172- < WelcomeView />
173+ < ErrorBoundary componentName = "WelcomeView" >
174+ < WelcomeView />
175+ </ ErrorBoundary >
173176 ) : (
174177 < >
175- { tab === "modes" && < ModesView onDone = { ( ) => switchTab ( "chat" ) } /> }
176- { tab === "mcp" && < McpView onDone = { ( ) => switchTab ( "chat" ) } /> }
177- { tab === "history" && < HistoryView onDone = { ( ) => switchTab ( "chat" ) } /> }
178+ { tab === "modes" && (
179+ < ErrorBoundary componentName = "ModesView" >
180+ < ModesView onDone = { ( ) => switchTab ( "chat" ) } />
181+ </ ErrorBoundary >
182+ ) }
183+ { tab === "mcp" && (
184+ < ErrorBoundary componentName = "McpView" >
185+ < McpView onDone = { ( ) => switchTab ( "chat" ) } />
186+ </ ErrorBoundary >
187+ ) }
188+ { tab === "history" && (
189+ < ErrorBoundary componentName = "HistoryView" >
190+ < HistoryView onDone = { ( ) => switchTab ( "chat" ) } />
191+ </ ErrorBoundary >
192+ ) }
178193 { tab === "settings" && (
179- < SettingsView ref = { settingsRef } onDone = { ( ) => setTab ( "chat" ) } targetSection = { currentSection } />
194+ < ErrorBoundary componentName = "SettingsView" >
195+ < SettingsView ref = { settingsRef } onDone = { ( ) => setTab ( "chat" ) } targetSection = { currentSection } />
196+ </ ErrorBoundary >
180197 ) }
181198 { tab === "marketplace" && (
182- < MarketplaceView
183- stateManager = { marketplaceStateManager }
184- onDone = { ( ) => switchTab ( "chat" ) }
185- targetTab = { currentMarketplaceTab as "mcp" | "mode" | undefined }
186- />
199+ < ErrorBoundary componentName = "MarketplaceView" >
200+ < MarketplaceView
201+ stateManager = { marketplaceStateManager }
202+ onDone = { ( ) => switchTab ( "chat" ) }
203+ targetTab = { currentMarketplaceTab as "mcp" | "mode" | undefined }
204+ />
205+ </ ErrorBoundary >
187206 ) }
188207 { tab === "account" && (
189- < AccountView
190- userInfo = { cloudUserInfo }
191- isAuthenticated = { cloudIsAuthenticated }
192- cloudApiUrl = { cloudApiUrl }
193- onDone = { ( ) => switchTab ( "chat" ) }
194- />
208+ < ErrorBoundary componentName = "AccountView" >
209+ < AccountView
210+ userInfo = { cloudUserInfo }
211+ isAuthenticated = { cloudIsAuthenticated }
212+ cloudApiUrl = { cloudApiUrl }
213+ onDone = { ( ) => switchTab ( "chat" ) }
214+ />
215+ </ ErrorBoundary >
195216 ) }
196- < ChatView
197- ref = { chatViewRef }
198- isHidden = { tab !== "chat" }
199- showAnnouncement = { showAnnouncement }
200- hideAnnouncement = { ( ) => setShowAnnouncement ( false ) }
201- />
202- < HumanRelayDialog
203- isOpen = { humanRelayDialogState . isOpen }
204- requestId = { humanRelayDialogState . requestId }
205- promptText = { humanRelayDialogState . promptText }
206- onClose = { ( ) => setHumanRelayDialogState ( ( prev ) => ( { ...prev , isOpen : false } ) ) }
207- onSubmit = { ( requestId , text ) => vscode . postMessage ( { type : "humanRelayResponse" , requestId, text } ) }
208- onCancel = { ( requestId ) => vscode . postMessage ( { type : "humanRelayCancel" , requestId } ) }
209- />
217+ < ErrorBoundary componentName = "ChatView" >
218+ < ChatView
219+ ref = { chatViewRef }
220+ isHidden = { tab !== "chat" }
221+ showAnnouncement = { showAnnouncement }
222+ hideAnnouncement = { ( ) => setShowAnnouncement ( false ) }
223+ />
224+ </ ErrorBoundary >
225+ < ErrorBoundary componentName = "HumanRelayDialog" >
226+ < HumanRelayDialog
227+ isOpen = { humanRelayDialogState . isOpen }
228+ requestId = { humanRelayDialogState . requestId }
229+ promptText = { humanRelayDialogState . promptText }
230+ onClose = { ( ) => setHumanRelayDialogState ( ( prev ) => ( { ...prev , isOpen : false } ) ) }
231+ onSubmit = { ( requestId , text ) => vscode . postMessage ( { type : "humanRelayResponse" , requestId, text } ) }
232+ onCancel = { ( requestId ) => vscode . postMessage ( { type : "humanRelayCancel" , requestId } ) }
233+ />
234+ </ ErrorBoundary >
210235 </ >
211236 )
212237}
213238
214239const queryClient = new QueryClient ( )
215240
216241const AppWithProviders = ( ) => (
217- < ExtensionStateContextProvider >
218- < TranslationProvider >
219- < QueryClientProvider client = { queryClient } >
220- < TooltipProvider delayDuration = { STANDARD_TOOLTIP_DELAY } >
221- < App />
222- </ TooltipProvider >
223- </ QueryClientProvider >
224- </ TranslationProvider >
225- </ ExtensionStateContextProvider >
242+ < ErrorBoundary componentName = "App" >
243+ < ExtensionStateContextProvider >
244+ < TranslationProvider >
245+ < QueryClientProvider client = { queryClient } >
246+ < TooltipProvider delayDuration = { STANDARD_TOOLTIP_DELAY } >
247+ < App />
248+ </ TooltipProvider >
249+ </ QueryClientProvider >
250+ </ TranslationProvider >
251+ </ ExtensionStateContextProvider >
252+ </ ErrorBoundary >
226253)
227254
228255export default AppWithProviders
0 commit comments