feat: typed error handling, DeleteSession, health check improvements#1
Merged
feat: typed error handling, DeleteSession, health check improvements#1
Conversation
…ervice - Update proto submodule to latest (DeleteSession RPC, command registry group/displayName/sessionId fields, SubagentService, NotificationService) - Regenerate all Dart protobuf code - Implement deleteSession() in SessionsNotifier with cache cleanup - Add ConfirmDeleteDialog widget with destructive styling - Wire delete flow in SessionsScreen with confirmation - Add deleteSession tests - Set default model in StartConversation to prevent relay "default" fallback - Update command palette for new proto fields - Add notification service plan doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add health check verification in GrpcLifecycleBridge.onResumed() to detect zombie channels after short backgrounds (< 5 min) - Catch UNIMPLEMENTED in healthCheckFn as defense-in-depth (proves connection is alive even if relay lacks betcode.v1.Health) - Add hasHealthCheck and healthCheck() to GrpcClientManager - Add tests for health check scenarios (failing, UNIMPLEMENTED, no check) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ty banner - Add sealed AppException class with 8 typed subclasses (NetworkError, RelayUnavailableError, SessionNotFoundError, SessionInvalidError, AuthExpiredError, PermissionDeniedError, ServerError, RateLimitError) - Add mapGrpcError() function mapping gRPC status codes to AppExceptions with human-readable messages and context-sensitive session detection - Add ErrorMappingInterceptor as last in gRPC interceptor chain - Add global ConnectivityBanner widget in app.dart showing persistent network/relay status (red for offline, orange for relay unreachable) - Update ConversationNotifier to use typed exceptions for fatal error detection and human-readable error messages - Update SessionsScreen to catch typed exceptions with friendly messages and handle SessionNotFoundError on delete gracefully - Update ErrorDisplay widget to show AppException.message instead of raw toString() - Update AuthNotifier._isAuthError() to recognize typed exceptions - Add comprehensive tests (35 new test cases) - Add error handling plan doc Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When resuming a session whose history contained a fatal error (e.g. "Claude exited with error"), the event handler treated replayed errors as live ones, transitioning to ConversationError and making the session permanently unrecoverable. Also fixes stream leaks on retry. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…gging - Service providers now watch connectionStatusProvider so clients rebuild when the channel is replaced during reconnection (fixes rapid-fire "Unable to reach relay" errors from stale channel references) - Separate "Channel shutting down" from TLS errors in error mapping so transient reconnection errors don't show "relay unreachable" banner - Handle StatusCode.cancelled as retryable NetworkError instead of falling through to "Something went wrong" catch-all - LoggingInterceptor now logs streaming errors and completion (was silent) - ErrorMappingInterceptor logs original GrpcError code+message before mapping, and _handleStreamError logs the cause for diagnostics Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
container.read(machinesProvider.future) never resolved on a bare ProviderContainer before runApp(), even though the AsyncNotifier build completed successfully. Replace with container.listen + Completer pattern that reliably awaits async provider state transitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix failing tests: error_mapping (Channel shutting down -> NetworkError) and interceptors (LoggingInterceptor wraps stream) - Fix _loadHistory catching AppException in addition to GrpcError so error-mapped exceptions show soft banner instead of killing conversation - Move ConnectivityBanner inside MaterialApp.router builder for proper theme/directionality context - Make SessionNotFoundError.sessionId optional (was always empty string) - Remove duplicate debugPrint in ErrorMappingResponseStream - Remove redundant imports in ConversationEventHandler - Document best-effort health check design decision in GrpcClientManager - Add tests for optional sessionId and AppException history load path Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CI workflow with analyze, test, build-android, and build-ios jobs. Migrate iOS from AppDelegate-based window management to UIScene with SceneDelegate. Bump iOS deployment target from 13.0 to 16.0. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AppExceptionhierarchy withErrorMappingInterceptorthat converts rawGrpcErrorinto human-readable typed exceptions. GlobalConnectivityBannerfor persistent network/relay status. All UI error displays now show friendly messages instead of raw gRPC errors.GrpcLifecycleBridgeverifies channel health after short backgrounds to detect zombie TCP connections. Catches UNIMPLEMENTED as defense-in-depth.Commits
Test plan
flutter test)dart analyze lib/ test/— zero issues🤖 Generated with Claude Code