Skip to content

Conversation

@ki3ani
Copy link
Contributor

@ki3ani ki3ani commented Aug 19, 2025

Summary

Implements #3244 - adds "Report a Failure" button with automated system info collection and GitHub Issues integration.

Users can now report failures directly within the app instead of manually navigating to GitHub. The modal automatically collects system information and opens pre-filled GitHub
Issues in the browser.

Screenshots

Before: Settings Help & Feedback Section

before

After: New "Report a Failure" Button Added

before-two

Report Failure Modal - System Info Auto-Collection

Screenshot from 2025-10-16 20-41-48

Success State After Submission

before-four

GitHub Issue Pre-filled in Browser

Screenshot from 2025-10-16 21-05-55

Implementation Details

  • ReportFailureModal component with form validation and automatic system info collection
  • GitHub integration opens pre-filled GitHub Issues in browser with proper formatting
  • Automatic data collection: Goose version, platform, architecture, extension count, provider type
  • SDK integration uses providers() API for reliable provider detection
  • Proper error handling with user feedback for all scenarios

Technical Changes

Frontend (ui/desktop/)

  • Added ReportFailureModal.tsx with system info collection using SDK providers API
  • Enhanced AppSettingsSection.tsx to include the new "Report a Failure" button
  • Extended preload.ts and main.ts to support opening GitHub URLs

Test Plan

  • Modal opens and automatically collects system information
  • Form validation prevents empty submissions
  • GitHub Issues opens in browser with pre-filled template
  • System info collection works across different platforms
  • Provider detection correctly identifies AWS Bedrock, Ollama, etc.
  • Success/error states provide appropriate user feedback

Notes

  • Opens GitHub Issues in browser with pre-filled bug report template
  • Provider detection uses SDK providers() API for reliable detection
  • Architecture detection exposed through Electron API

@ki3ani ki3ani changed the title Easy session failure reporting feat: Easy session failure reporting Aug 19, 2025
@jamadeo
Copy link
Collaborator

jamadeo commented Aug 20, 2025

Thanks @ki3ani this is a good feature. However I don't think we should dependon a github token set in goosed -- rather, you can do this more simply by opening the system web browser at something like

https://github.com/block/goose/issues/new?title=YOUR_TITLE&body=YOUR_BODY&labels=LABEL1,LABEL2&milestone=MILESTONE_NAME&assignees=ASSIGNEE1,ASSIGNEE2&template=TEMPLATE_NAME

@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from caa86fd to 2fd5de7 Compare August 21, 2025 08:07
@ki3ani
Copy link
Contributor Author

ki3ani commented Aug 21, 2025

Thanks @ki3ani this is a good feature. However I don't think we should dependon a github token set in goosed -- rather, you can do this more simply by opening the system web browser at something like

https://github.com/block/goose/issues/new?title=YOUR_TITLE&body=YOUR_BODY&labels=LABEL1,LABEL2&milestone=MILESTONE_NAME&assignees=ASSIGNEE1,ASSIGNEE2&template=TEMPLATE_NAME

That was well noted @jamadeo, ive refactored to open pre-filled GitHub URL in browser instead.

payload.system_info.goose_version,
payload.timestamp
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that it's a pre-filled github URL, I think you can just remove the "backend" component. No need to have it just to log.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, i have removed the backend feedback endpoint since it was just logging.

try {
// Get extension count from the API
const apiUrl = getApiUrl('/extension/list');
const secretKey = getSecretKey();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we do this in other places (we shouldn't) but we should avoid constructing the request like this an instead use the generated SDK:

export const getExtensions = <ThrowOnError extends boolean = false>(options?: Options<GetExtensionsData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).get<GetExtensionsResponses, GetExtensionsErrors, ThrowOnError>({
url: '/config/extensions',
...options
});
};

// For now, collect from browser console errors and any stored logs
const recentErrors: string[] = [];

const storedErrors = localStorage.getItem('goose_recent_errors');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a thing? do we write to goose_recent_errors anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, that wasn't actually used anywhere. Removed it.

@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from 2fd5de7 to 68f4069 Compare August 30, 2025 08:44

const collectRecentErrors = useCallback(async () => {
try {
// Recent errors are logged to the main process via ErrorBoundary
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still confused about the recentErrors bit - it looks like it's only ever set to an array of one constant string? what is this about main process error boundary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the mechanism for collecting recent errors. To keep this PR strictly in scope and prevent introducing complex dependencies, I removed the entire collectRecentErrors function and state

try {
const secretKey = getSecretKey();
const response = await getExtensions({
headers: secretKey ? { 'X-Secret-Key': secretKey } : {},
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should not to include the secret key here, as it's globally configured for the generated client sdk

Array.isArray(providerResponse.data) &&
providerResponse.data.length > 0
) {
info.providerType = providerResponse.data[0].name || 'Unknown Provider';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you want just the first provider.

The right thing to use here is probably the session metadata for the active session. #4648 adds that to the client API, so this might fit in better once that's merged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the old provider listing logic and refactored the code to use getSessionHistory from the merged #4648 to correctly retrieve the provider_name

@DOsinga
Copy link
Collaborator

DOsinga commented Oct 2, 2025

@ki3ani thanks for kicking this off, if you address @jamadeo 's comments, let's get this in!

@DOsinga DOsinga added the waiting label Oct 6, 2025
@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from 68f4069 to 0a6927f Compare October 7, 2025 13:22
@DOsinga
Copy link
Collaborator

DOsinga commented Oct 8, 2025

can you also do the DCO? and @jamadeo can you have another look?

@@ -0,0 +1,269 @@
import { useState, useEffect, useCallback } from 'react';
import { Button } from './ui/button';
import { Textarea } from './ui/textarea';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of these don't exist:

./ui/textarea
./Modal
getSessionHistory

does this run for you?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamadeo Yes it was running but some imports were broken which I hadn't noticed. Fixed now - replaced ./ui/textarea with native textarea, ./Modal with Dialog components, and
getSessionHistory with providers() SDK call. All working properly now.

@DOsinga
Copy link
Collaborator

DOsinga commented Oct 11, 2025

also can you look into the DCO thing?

@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from bbe7a25 to 5bf7acc Compare October 16, 2025 04:35
@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from 5bf7acc to 3fa79c1 Compare October 16, 2025 04:37
@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from 360b6cb to 7b83e17 Compare October 16, 2025 13:43
  - Remove session metadata fallback approach
  - Use providers() SDK call directly for reliable detection
  - Clean up unused imports

  Signed-off-by: Kenneth Mungai <[email protected]>

Signed-off-by: ki3ani <[email protected]>
@ki3ani ki3ani force-pushed the easy-session-failure-reporting branch from 5fa67e5 to f81a3b0 Compare October 16, 2025 17:55
@ki3ani
Copy link
Contributor Author

ki3ani commented Oct 16, 2025

also can you look into the DCO thing?

Done

Copy link
Collaborator

@jamadeo jamadeo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better! Only real issue is that it picks the wrong provider. Also consider the text truncation, if we must truncate because it's too much for the URL, we should limit the text area so the user doesn't unexpectedly lose what they wrote

if (providersResponse.data && Array.isArray(providersResponse.data)) {
const providersList = providersResponse.data;
if (providersList.length > 0) {
info.providerType = providersList[0].name || 'Unknown';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this isn't the right one to use. You can use useModelAndProvider to get the current model and provider

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

er, looks like the extension count is also wrong. When I tried it, it shows 0 extensions installed, but I have several


try {
const issueTitle = encodeURIComponent(
`[FAILURE REPORT] ${description.substring(0, 60)}${description.length > 60 ? '...' : ''}`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

60 characters seems quite small for what someone might type into this box. If we're limited by url length, you could leave out the txt entry and have the user type in the opened github window. You'd still have the collected system info

>
<AlertCircle size={16} />
Report a Failure
</Button>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that this is now next to a "report a bug" button. I think your button is better because it collects system info, so I'd say go ahead and remove the other "report a bug" button so we don't have two very similar actions

@DOsinga
Copy link
Collaborator

DOsinga commented Oct 28, 2025

closing this since there has been no activity on it. can always reopen

@DOsinga DOsinga closed this Oct 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants