Fix: graceful handling of StartAsync failures after PR #118#119
Merged
Fix: graceful handling of StartAsync failures after PR #118#119
Conversation
… return early to avoid later 'Service not initialized'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When StartAsync fails (e.g., persistent server down + no system copilot binary), the catch blocks now dispose the failed CopilotClient and set _client = null. This prevents a stale broken client reference that would cause NullReferenceException on subsequent operations, and ensures the 'Service not initialized' guard checks work correctly. Also fixes comment indentation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validates the premise of the InitializeAsync/ReconnectAsync try/catch fix: CopilotClient.StartAsync() throws when connecting to a non-existent server, confirming the error handling path is defending against a real failure mode. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n tests - Extract IChatDatabase, IServerManager, IWsBridgeClient, IDemoService interfaces - Concrete classes implement their respective interfaces - CopilotService constructor accepts interfaces (internal ctor for test injection) - DI registration forwards interfaces to concrete singletons - Add TestStubs.cs with stub implementations for all interfaces - Add CopilotServiceInitializationTests.cs with 15 integration tests covering: - Pre-initialization guard checks (CreateSession/ResumeSession throw) - Demo mode initialization and session creation - Embedded mode failure → NeedsConfiguration - Persistent mode failure → NeedsConfiguration - Mode transitions (Demo → Embedded) - OnStateChanged event firing - Session cleanup on reconnect All 316 tests pass. MAUI build succeeds. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
4ce0d5d to
5ada2f3
Compare
…stubs - Add Debug log message in ReconnectAsync catch block to match InitializeAsync pattern - Add #pragma warning disable/restore CS0067 around stub classes with unused events Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Root cause: SaveActiveSessionsToDisk() overwrites active-sessions.json with only the currently in-memory sessions. During mode switches, sessions that fail to restore (or haven't been restored yet) were permanently lost from the file. If the app was killed mid-restore, the same data loss occurred. Fix: SaveActiveSessionsToDisk now merges — it reads the existing file and preserves entries whose session directory still exists on disk, even if they aren't currently loaded in memory. This makes the operation safe to call at any point during startup, restore, or mode switching. Additional changes: - Skip SaveActiveSessionsToDisk during restore (IsRestoring guard) to avoid unnecessary disk I/O per session - Skip SessionStartEvent save during restore for same reason - Track explicitly closed session IDs so merge doesn't re-add them - Add LoadOrganization + ReconcileOrganization in ReconnectAsync (was missing vs InitializeAsync) - Add detailed debug logging in RestorePreviousSessionsAsync - Add 7 mode-switch integration tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- SetMode() in Settings.razor now calls settings.Save() immediately so the user's mode choice persists even if the app is killed before clicking Save & Reconnect (fixes mode reverting to Embedded on restart) - Add FallbackNotice property to CopilotService — when persistent server can't start and we fall back to Embedded, a dismissable warning banner is shown on the Dashboard with a link to Settings - Add 'Report Bug' button in the sidebar footer that expands inline to collect a description and auto-attach debug info (mode, session count, platform, crash log tail), then submits via gh CLI to PureWeen/PolyPilot - Remove duplicate UiState/ActiveSessionEntry classes from test project (now compiled in via Compile Include from CopilotService.cs) - Add tests for FallbackNotice, ClearFallbackNotice, mode persistence Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add 7 new unit tests: CliSource default, switching, independence from mode, serialization round-trip, mode switch preserving CliSource, ResolveBundledCliPath safety, and unique scenario IDs validation - Add 3 new UI scenarios: CLI source switch persistence, mode persists without Save & Reconnect, bug report button visibility - Add scenario cross-reference tests for new scenarios - Update copilot-instructions.md: - Fix default mode (Persistent, not Embedded) for desktop - Document mode switching & merge-based session persistence - Document test safety rules (never call Save/Load, use Demo mode) - Add new test files to coverage section Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Report Bug: creates a GitHub issue via gh CLI with debug info attached. Fix/Feature: creates a worktree on a new branch, writes a prompt file with the bug description + debug info + coding conventions, then launches copilot CLI in a new Terminal.app window pointed at the worktree. The prompt instructs copilot to fix the issue, add tests and scenarios, then create a PR. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ng issues The osascript -e '...' approach with UseShellExecute mangled the quotes. Now writes both the shell script and AppleScript to temp files, which osascript reads directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
osascript-spawned Terminal inherits the MAUI app's sandbox restrictions, causing 'Permission denied' errors for the copilot CLI. Using 'open -a Terminal' launches Terminal.app as a fully independent process with no sandbox. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Without --yolo, copilot CLI tries to prompt for directory/tool permissions and fails with 'Permission denied and could not request permission from user' when launched non-interactively in a new worktree. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Shows a yellow hint bar below the mode cards when the user switches between Embedded/Persistent, with a Reconnect Now button. Hint disappears after successful reconnect. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds --resume flag so copilot stays interactive after processing the initial prompt. User can follow up, provide more context, or guide the fix directly in the terminal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
-p is non-interactive and exits after completion. -i starts interactive mode, executes the prompt, then keeps the session open for follow-up conversation in the terminal. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.
Problem
After PR #118, users with Persistent mode saved in settings but no running server get stuck with "⚠ Service not initialized. Call InitializeAsync first." because:
_client.StartAsync()throws (no system copilot installed)IsInitializedstaysfalse— user is stuck foreverFix
StartAsyncin try/catch in bothInitializeAsyncandReconnectAsync_client = null, setNeedsConfiguration = trueTest
StartAsync_WithUnreachableServer_Throwstest proving the SDK throws on unreachable servers (validates the premise of the fix)