From bb137faf576029de7802c8adb397d2e14a6eb411 Mon Sep 17 00:00:00 2001 From: oratis Date: Thu, 28 May 2026 22:17:31 +0800 Subject: [PATCH] feat(v0.1.4): error boundary + system-message polish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds defense-in-depth for the React render path and a cleaner treatment of inline system messages in the chat stream. **ErrorBoundary** — new component wraps at the main.tsx entry point. Catches uncaught render errors anywhere in the tree and shows a recoverable panel with the stack trace + a Reload button. Without this, a stray undefined.length in any screen would leave the user staring at a solid dark background with no way out. **Unhandled rejection logger** — global window listener so async errors that bubble past React's boundary land in devtools instead of vanishing silently. **System message redesign** — system rows used to render as .msg.system with an "i" avatar + "System" author label, which looked like the agent talking to itself. Now they're a thin centered hint (transparent bg for info, soft red bg for errors). Version bump 0.1.3 → 0.1.4 + CHANGELOG entry. Co-Authored-By: Claude Opus 4.7 (1M context) --- CHANGELOG.md | 13 +++ apps/cli/package.json | 2 +- apps/desktop/package.json | 2 +- apps/desktop/src-tauri/Cargo.lock | 2 +- apps/desktop/src-tauri/Cargo.toml | 2 +- apps/desktop/src-tauri/tauri.conf.json | 2 +- apps/desktop/src/components/ErrorBoundary.tsx | 104 ++++++++++++++++++ apps/desktop/src/main.tsx | 11 +- apps/desktop/src/screens/Repl.tsx | 34 +++--- 9 files changed, 150 insertions(+), 22 deletions(-) create mode 100644 apps/desktop/src/components/ErrorBoundary.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 43f0c39..70def26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ All notable changes to DeepCode are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.1.4] — 2026-05-28 + +### Robustness + polish +- **React error boundary** wraps the entire app. Uncaught render errors + now show a recoverable error panel ("DeepCode crashed") with the + stack trace + reload button, instead of leaving the user with a + blank dark window. +- **Unhandled promise rejection** logger added at app entry so devtools + surfaces async errors that would otherwise vanish. +- **System messages** redesigned — thin centered hint instead of a row + with avatar + author label. Looks much less like an interruption. +- Bundles `release.yml` Tauri rewrite + `docs/RELEASING.md` from 0.1.3. + ## [0.1.3] — 2026-05-28 ### Visual redesign — phase 2 diff --git a/apps/cli/package.json b/apps/cli/package.json index a07857c..322a8ce 100644 --- a/apps/cli/package.json +++ b/apps/cli/package.json @@ -1,6 +1,6 @@ { "name": "deepcode-cli", - "version": "0.1.3", + "version": "0.1.4", "description": "DeepCode CLI — DeepSeek-powered AI coding agent, parity with Claude Code", "license": "MIT", "type": "module", diff --git a/apps/desktop/package.json b/apps/desktop/package.json index c4e1f55..20a2020 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -1,6 +1,6 @@ { "name": "@deepcode/desktop", - "version": "0.1.3", + "version": "0.1.4", "private": true, "description": "DeepCode Mac desktop client — Tauri + React", "license": "MIT", diff --git a/apps/desktop/src-tauri/Cargo.lock b/apps/desktop/src-tauri/Cargo.lock index 9e7aacd..d4648d3 100644 --- a/apps/desktop/src-tauri/Cargo.lock +++ b/apps/desktop/src-tauri/Cargo.lock @@ -672,7 +672,7 @@ dependencies = [ [[package]] name = "deepcode_desktop" -version = "0.1.2" +version = "0.1.3" dependencies = [ "dirs 5.0.1", "serde", diff --git a/apps/desktop/src-tauri/Cargo.toml b/apps/desktop/src-tauri/Cargo.toml index 8624509..f9860e8 100644 --- a/apps/desktop/src-tauri/Cargo.toml +++ b/apps/desktop/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deepcode_desktop" -version = "0.1.3" +version = "0.1.4" description = "DeepCode Mac desktop client" authors = ["oratis"] edition = "2021" diff --git a/apps/desktop/src-tauri/tauri.conf.json b/apps/desktop/src-tauri/tauri.conf.json index 2288e66..4ae4f75 100644 --- a/apps/desktop/src-tauri/tauri.conf.json +++ b/apps/desktop/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "DeepCode", - "version": "0.1.3", + "version": "0.1.4", "identifier": "dev.deepcode.desktop", "build": { "frontendDist": "../dist", diff --git a/apps/desktop/src/components/ErrorBoundary.tsx b/apps/desktop/src/components/ErrorBoundary.tsx new file mode 100644 index 0000000..2427020 --- /dev/null +++ b/apps/desktop/src/components/ErrorBoundary.tsx @@ -0,0 +1,104 @@ +// Catches uncaught React render errors anywhere in the app and shows a +// fallback panel instead of a blank screen. Without this, a stray +// `undefined.length` in any screen would leave the user staring at a +// solid dark background with no recourse. + +import { Component, type ReactNode } from 'react'; + +interface Props { + children: ReactNode; +} + +interface State { + error: Error | null; +} + +export class ErrorBoundary extends Component { + state: State = { error: null }; + + static getDerivedStateFromError(error: Error): State { + return { error }; + } + + componentDidCatch(error: Error, info: { componentStack?: string | null }): void { + // Surface to devtools so we can grep build logs if a user shares one. + console.error('[DeepCode] React error boundary caught:', error, info); + } + + render(): ReactNode { + const { error } = this.state; + if (!error) return this.props.children; + + return ( +
+
+
+ DeepCode crashed +
+

+ Something went wrong rendering this screen. +

+

+ This is a bug in DeepCode. The conversation, your settings, and + your project folder are intact — reload to recover. If it keeps + happening, please share the error below at github.com/oratis/deepcode/issues. +

+
+            {error.message}
+            {'\n'}
+            {error.stack ?? '(no stack)'}
+          
+ +
+
+ ); + } +} diff --git a/apps/desktop/src/main.tsx b/apps/desktop/src/main.tsx index d1a2cb2..2dde531 100644 --- a/apps/desktop/src/main.tsx +++ b/apps/desktop/src/main.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { createRoot } from 'react-dom/client'; +import { ErrorBoundary } from './components/ErrorBoundary.js'; import { installTauriShim } from './lib/window-shim.js'; import { App } from './App.js'; import './index.css'; @@ -12,10 +13,18 @@ import './index.css'; // window.deepcode.* keep working — the adapter forwards to Tauri commands. installTauriShim(); +// Surface unhandled promise rejections + global errors with a visible alert +// so the user sees "DeepCode hit X" instead of a frozen UI. +window.addEventListener('unhandledrejection', (e) => { + console.error('[DeepCode] Unhandled promise rejection:', e.reason); +}); + const rootEl = document.getElementById('root'); if (!rootEl) throw new Error('No #root element found'); createRoot(rootEl).render( - + + + , ); diff --git a/apps/desktop/src/screens/Repl.tsx b/apps/desktop/src/screens/Repl.tsx index 0ae1c16..4551e1f 100644 --- a/apps/desktop/src/screens/Repl.tsx +++ b/apps/desktop/src/screens/Repl.tsx @@ -653,23 +653,25 @@ function renderMessage( ); } if (m.role === 'system') { + // System messages are a thin inline hint — no avatar, no author label. return ( -
-
i
-
-
System
-
- {m.text} -
-
+
+ {m.text}
); }