-
Notifications
You must be signed in to change notification settings - Fork 2.3k
feat: add grouped extension loading notification #5529
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add grouped extension loading notification #5529
Conversation
e9bcd0c to
629b81a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements grouped extension loading notifications to improve user experience during extension initialization. Instead of showing individual toasts for each extension, it consolidates them into a single collapsible toast that updates in real-time.
Key changes:
- Introduces a new
GroupedExtensionLoadingToastcomponent with expandable/collapsible UI - Adds
extensionLoading()method toToastServicefor managing grouped toast updates - Updates
initializeSystem()to track extension loading status and display grouped notifications
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ui/desktop/src/components/GroupedExtensionLoadingToast.tsx | New React component implementing collapsible toast with extension loading status display |
| ui/desktop/src/components/tests/GroupedExtensionLoadingToast.test.tsx | Test suite covering various loading states and scenarios |
| ui/desktop/src/toasts.tsx | Adds extensionLoading() method and exports ExtensionLoadingStatus type |
| ui/desktop/src/utils/providerUtils.ts | Implements status tracking and grouped notification updates during extension initialization |
| ui/desktop/src/components/settings/extensions/extension-manager.ts | Makes individual extension toasts silent and re-throws errors for grouped notification handling |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // Always show individual error toasts (they have action buttons and detailed info) | ||
| toastService.configure({ silent: false }); | ||
| toastService.error({ | ||
| title: extensionConfig.name, | ||
| msg: 'Extension failed to start and will retry on a new session.', | ||
| traceback: finalError instanceof Error ? finalError.message : String(finalError), | ||
| }); | ||
| // Re-throw so the grouped notification can catch and display it | ||
| throw finalError; |
Copilot
AI
Nov 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment on line 114 states 'Always show individual error toasts' but this creates duplicate error notifications - one individual error toast here and another in the grouped notification. Consider removing the individual toast and only showing the grouped notification, or add a flag to control this behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i understand that the individual toasts have more info on the error, but I did find it confusing to see the extension status in both the grouped toasts and the individual toast
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@angiejones ah yeah, was playing around with putting the info into the collapsible one but have to think about it some more 😓 I'm mostly confused why this specific extension always throws two individual ones to begin with
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i had a 2 for 1 for another extension too. there were two different messages on them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@angiejones I think this looks better! Kept the same logic with either "Ask Goose" button or copy error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
b0f2470 to
354f728
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| isComplete={isComplete} | ||
| />, | ||
| { | ||
| ...commonToastOptions, |
Copilot
AI
Nov 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commonToastOptions includes closeOnClick: true (line 144), but this is explicitly overridden to false on line 112. The spread operator on line 108 applies commonToastOptions first, making the override on line 112 take precedence. However, this could be confusing. Consider creating a variant of commonToastOptions without closeOnClick, or add a comment explaining why the override is necessary for this specific toast type.
354f728 to
e616bf2
Compare
Replace multiple individual toast notifications with a single collapsible notification during extension loading at startup. Changes: - Created GroupedExtensionLoadingToast component with real-time status updates - Shows summary with loading progress and error count - Expandable to view individual extension statuses with icons - Error details shown with 'Ask goose' or 'Copy error' buttons - Auto-dismisses after 5 seconds when loading completes - Dismissible during loading for better UX - Added comprehensive unit tests covering all states - Extracted shared error handling utilities to extensionErrorUtils.ts - Optimized toast updates to avoid redundant array creation Benefits: - Reduces notification clutter (10+ toasts → 1 grouped notification) - Provides better visibility into loading progress - Maintains full error visibility with actionable buttons - Improves startup experience for users with many extensions - Better code maintainability with shared utilities Technical details: - Uses Radix UI Collapsible for accessible expand/collapse - Implements toast.update() for real-time progress tracking - Handles mixed states (loading, success, error) simultaneously - Robust error message extraction and display - Clickable notification for easy expand/collapse - Shared constants (MAX_ERROR_MESSAGE_LENGTH) across components Signed-off-by: jom-sq <[email protected]>
e616bf2 to
802805d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const errMsg = errorMessage(error); | ||
| const recoverHints = createExtensionRecoverHints(errMsg); | ||
| const msg = formatExtensionErrorMessage(errMsg, 'Failed to add extension'); | ||
| toastService.error({ | ||
| title: extensionName, | ||
| msg: msg, | ||
| traceback: errMsg, | ||
| recoverHints, | ||
| }); |
Copilot
AI
Nov 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The variable msg could have a more descriptive name like formattedMsg or displayMsg to better distinguish it from the raw errMsg and improve code clarity about which message is being used where.
* 'main' of github.com:block/goose: Sessions required (#5548) feat: add grouped extension loading notification (#5529) we should run this on main and also test open models at least via ope… (#5556) info: print location of sessions.db via goose info (#5557) chore: remove yarn usage from documentation (#5555) cli: adjust default theme to address #1905 (#5552)
* main: (85 commits) improve linux tray icon support (#5425) feat: log rotation (#5561) use app.isPackaged instead of checking for node env development (#5465) disable RPM build-ID generation to prevent package conflicts (#5563) Add Diagnostics Info to Q&A and Bug Report Templates (#5565) fix: improve server error messages to include HTTP status code (#5532) improvement: add useful error message when attempting to use unauthenticated cursor-agent (#5300) fix: unblock acp via databricks (#5562) feat: add --output-format json flag to goose run command (#5525) Sessions required (#5548) feat: add grouped extension loading notification (#5529) we should run this on main and also test open models at least via ope… (#5556) info: print location of sessions.db via goose info (#5557) chore: remove yarn usage from documentation (#5555) cli: adjust default theme to address #1905 (#5552) Manual compaction counting fix + cli cleanup (#5480) chore(deps): bump prismjs and react-syntax-highlighter in /ui/desktop (#5549) fix: remove qwen3-coder from provider/mcp smoke tests (#5551) fix: do not build unsigned desktop app bundles on every PR in ci. add manual option. (#5550) fix: update Husky prepare script to v9 format (#5522) ...
* main: (54 commits) add clippy warning for string_slice (#5422) improve linux tray icon support (#5425) feat: log rotation (#5561) use app.isPackaged instead of checking for node env development (#5465) disable RPM build-ID generation to prevent package conflicts (#5563) Add Diagnostics Info to Q&A and Bug Report Templates (#5565) fix: improve server error messages to include HTTP status code (#5532) improvement: add useful error message when attempting to use unauthenticated cursor-agent (#5300) fix: unblock acp via databricks (#5562) feat: add --output-format json flag to goose run command (#5525) Sessions required (#5548) feat: add grouped extension loading notification (#5529) we should run this on main and also test open models at least via ope… (#5556) info: print location of sessions.db via goose info (#5557) chore: remove yarn usage from documentation (#5555) cli: adjust default theme to address #1905 (#5552) Manual compaction counting fix + cli cleanup (#5480) chore(deps): bump prismjs and react-syntax-highlighter in /ui/desktop (#5549) fix: remove qwen3-coder from provider/mcp smoke tests (#5551) fix: do not build unsigned desktop app bundles on every PR in ci. add manual option. (#5550) ...
Signed-off-by: jom-sq <[email protected]> Signed-off-by: fbalicchia <[email protected]>
Signed-off-by: jom-sq <[email protected]> Signed-off-by: Blair Allan <[email protected]>
Summary
Replaces multiple individual extension loading toast notifications with a single, grouped, collapsible notification. When starting Goose with 10+ extensions enabled, users previously saw 10+ stacked toast notifications. This PR consolidates them into one notification that shows real-time loading progress, displays success/error counts, and can be expanded to view individual extension statuses.
Key improvements:
Type of Change
Testing
Unit Tests:
GroupedExtensionLoadingToast.test.tsxManual Testing:
CI Checks:
Related Issues
N/A
Screenshots/Demos (for UX changes)
Note that I don't know why my Square MCP server gives two failure toasts, I'll be exploring that in a later Issue where this extension is causing multiple issues 😅
Before:
before.mp4
After
My.Movie.mp4