Skip to content

General improvements #35

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions electron/ConfigHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,20 +297,16 @@ export class ConfigHelper extends EventEmitter {
} catch (error: any) {
console.error('OpenAI API key test failed:', error);

// Determine the specific error type for better error messages
let errorMessage = 'Unknown error validating OpenAI API key';

// Return error without showing dialog
if (error.status === 401) {
errorMessage = 'Invalid API key. Please check your OpenAI key and try again.';
return { valid: false, error: 'Invalid API key' };
} else if (error.status === 429) {
errorMessage = 'Rate limit exceeded. Your OpenAI API key has reached its request limit or has insufficient quota.';
return { valid: false, error: 'Rate limit exceeded' };
} else if (error.status === 500) {
errorMessage = 'OpenAI server error. Please try again later.';
} else if (error.message) {
errorMessage = `Error: ${error.message}`;
return { valid: false, error: 'OpenAI server error' };
} else {
return { valid: false, error: error.message || 'Unknown error' };
Copy link
Collaborator

Choose a reason for hiding this comment

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

These are added to bypass the dialog box I believe? Could you explain the diff please?
I think we can make them more meaningful either way!

}

return { valid: false, error: errorMessage };
}
}

Expand Down
154 changes: 85 additions & 69 deletions electron/ProcessingHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ export class ProcessingHelper {
}
}

// Default fallback
return "python";
// Default to auto instead of python
return "auto";
} catch (error) {
console.error("Error getting language:", error)
return "python"
return "auto"
}
}

Expand Down Expand Up @@ -201,15 +201,6 @@ export class ProcessingHelper {
if (!screenshotQueue || screenshotQueue.length === 0) {
console.log("No screenshots found in queue");
mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS);

// Show dialog if no screenshots
dialog.showMessageBox(mainWindow, {
type: 'info',
title: 'No Screenshots Detected',
message: 'No screenshots were found to process.',
detail: 'Please take a screenshot first using Ctrl+H (or Cmd+H on Mac). Make sure your screenshot contains the coding problem you want to solve.',
buttons: ['OK']
});
return;
}

Expand All @@ -218,15 +209,6 @@ export class ProcessingHelper {
if (existingScreenshots.length === 0) {
console.log("Screenshot files don't exist on disk");
mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS);

// Show error dialog
dialog.showMessageBox(mainWindow, {
type: 'warning',
title: 'Screenshot Files Missing',
message: 'The screenshot files were not found on disk.',
detail: 'Try taking a new screenshot with Ctrl+H (or Cmd+H on Mac).',
buttons: ['OK']
});
return;
}

Expand Down Expand Up @@ -317,15 +299,6 @@ export class ProcessingHelper {
if (!extraScreenshotQueue || extraScreenshotQueue.length === 0) {
console.log("No extra screenshots found in queue");
mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS);

// Show dialog if no screenshots
dialog.showMessageBox(mainWindow, {
type: 'info',
title: 'No Debug Screenshots',
message: 'No screenshots were found for debugging.',
detail: 'Please take screenshots of your code/errors with Ctrl+H before debugging.',
buttons: ['OK']
});
return;
}

Expand All @@ -334,14 +307,6 @@ export class ProcessingHelper {
if (existingExtraScreenshots.length === 0) {
console.log("Extra screenshot files don't exist on disk");
mainWindow.webContents.send(this.deps.PROCESSING_EVENTS.NO_SCREENSHOTS);

dialog.showMessageBox(mainWindow, {
Copy link
Collaborator

Choose a reason for hiding this comment

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

The removal lgtm.
What we could do is to add console logging just to be on the safe side of receiving meaningful feedback

type: 'warning',
title: 'Screenshot Files Missing',
message: 'The debug screenshot files were not found.',
detail: 'Try taking a new screenshot with Ctrl+H (or Cmd+H on Mac).',
buttons: ['OK']
});
return;
}

Expand Down Expand Up @@ -430,48 +395,47 @@ export class ProcessingHelper {
signal: AbortSignal
) {
try {
const config = configHelper.loadConfig();
const language = await this.getLanguage();
const config = configHelper.loadConfig();
const mainWindow = this.deps.getMainWindow();

// Step 1: Extract problem info using AI Vision API (OpenAI or Gemini)
const imageDataList = screenshots.map(screenshot => screenshot.data);

// Update the user on progress
// Create base64 image data array
const imageDataList = screenshots.map(s => s.data);

if (mainWindow) {
mainWindow.webContents.send("processing-status", {
message: "Analyzing problem from screenshots...",
progress: 20
message: "Analyzing screenshots...",
progress: 30
});
}

let problemInfo;
let responseContent;

if (config.apiProvider === "openai") {
// Verify OpenAI client
// OpenAI processing
if (!this.openaiClient) {
this.initializeAIClient(); // Try to reinitialize

if (!this.openaiClient) {
return {
success: false,
error: "OpenAI API key not configured or invalid. Please check your settings."
};
}
return {
success: false,
error: "OpenAI API key not configured. Please check your settings."
};
}

// Use OpenAI for processing
// Create OpenAI message structure
const messages = [
{
role: "system" as const,
content: "You are a coding challenge interpreter. Analyze the screenshot of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text."
role: "system" as const,
content: language === 'auto' ?
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem, identify the programming language being used, and extract all relevant information. Return the information in JSON format with these fields: problem_statement (which must include the identified programming language), constraints, example_input, example_output. Just return the structured JSON without any other text." :
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text."
Copy link
Collaborator

Choose a reason for hiding this comment

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

Intended repetition?

Copy link
Author

Choose a reason for hiding this comment

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

just modifed some prompts, If auto is slected it instructs the LLM to autodetect the language and try to provied the answer in that lanugage. in case of multiple languges test etc

Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh cool, I get it now. Sorry for the misunderstanding.

},
{
role: "user" as const,
content: [
{
type: "text" as const,
text: `Extract the coding problem details from these screenshots. Return in JSON format. Preferred coding language we gonna use for this problem is ${language}.`
type: "text" as const,
text: language === 'auto' ?
"Analyze the screenshots, identify the programming language being used or required, and extract all relevant information. Make sure to include the identified programming language in the problem statement." :
`Preferred coding language we gonna use for this problem is ${language}.`
},
...imageDataList.map(data => ({
type: "image_url" as const,
Expand All @@ -494,7 +458,7 @@ export class ProcessingHelper {
const responseText = extractionResponse.choices[0].message.content;
// Handle when OpenAI might wrap the JSON in markdown code blocks
const jsonText = responseText.replace(/```json|```/g, '').trim();
problemInfo = JSON.parse(jsonText);
responseContent = JSON.parse(jsonText);
} catch (error) {
console.error("Error parsing OpenAI response:", error);
return {
Expand All @@ -518,7 +482,9 @@ export class ProcessingHelper {
role: "user",
parts: [
{
text: `You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text. Preferred coding language we gonna use for this problem is ${language}.`
text: language === 'auto' ?
"You are a coding challenge interpreter. Analyze the screenshots of the coding problem, identify the programming language being used, and extract all relevant information. Return the information in JSON format with these fields: problem_statement (which must include the identified programming language), constraints, example_input, example_output. Just return the structured JSON without any other text." :
`You are a coding challenge interpreter. Analyze the screenshots of the coding problem and extract all relevant information. Return the information in JSON format with these fields: problem_statement, constraints, example_input, example_output. Just return the structured JSON without any other text. Preferred coding language we gonna use for this problem is ${language}.`
},
...imageDataList.map(data => ({
inlineData: {
Expand Down Expand Up @@ -553,7 +519,7 @@ export class ProcessingHelper {

// Handle when Gemini might wrap the JSON in markdown code blocks
const jsonText = responseText.replace(/```json|```/g, '').trim();
problemInfo = JSON.parse(jsonText);
responseContent = JSON.parse(jsonText);
} catch (error) {
console.error("Error using Gemini API:", error);
return {
Expand All @@ -572,13 +538,13 @@ export class ProcessingHelper {
}

// Store problem info in AppState
this.deps.setProblemInfo(problemInfo);
this.deps.setProblemInfo(responseContent);

// Send first success event
if (mainWindow) {
mainWindow.webContents.send(
this.deps.PROCESSING_EVENTS.PROBLEM_EXTRACTED,
problemInfo
responseContent
);

// Generate solutions after successful extraction
Expand Down Expand Up @@ -661,7 +627,31 @@ export class ProcessingHelper {
}

// Create prompt for solution generation
const promptText = `
const promptText = language === 'auto' ? `
Copy link
Collaborator

Choose a reason for hiding this comment

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

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

Copy link
Owner

Choose a reason for hiding this comment

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

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

@bhaumikmaan, thanks for the heads-up! I don't have enough time to do a deep dive today, but I'll definitely check it out later. In the meantime, if you get a chance, feel free to give it a look yourself and share any insights. You know what they say ...two pairs of eyes are better than one! 😄

Choose a reason for hiding this comment

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

@Ornithopter-pilot Need a deep review on this since it is the heart of the code

@bhaumikmaan, thanks for the heads-up! I don't have enough time to do a deep dive today, but I'll definitely check it out later. In the meantime, if you get a chance, feel free to give it a look yourself and share any insights. You know what they say ...two pairs of eyes are better than one! 😄

any update? if this pull would be merged or not codebase seems solid to me except the mouse Handeling thing we need to come up with the different approach to make sure mouse tracking doesn't happen when cursor leaves the browser which is happening currently

Copy link
Collaborator

Choose a reason for hiding this comment

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

Not tracking what you are referring to here. Is it a new issue, if so please make an issue for it. If it is for this PR, it still needs changes

Generate a detailed solution for the following coding problem. First analyze the problem statement, constraints, and examples to identify the most appropriate programming language, then provide the solution in that language:

PROBLEM STATEMENT:
${problemInfo.problem_statement}

CONSTRAINTS:
${problemInfo.constraints || "No specific constraints provided."}

EXAMPLE INPUT:
${problemInfo.example_input || "No example input provided."}

EXAMPLE OUTPUT:
${problemInfo.example_output || "No example output provided."}

I need the response in the following format:
1. Code: A clean, optimized implementation in the most appropriate programming language (based on the problem and examples)
2. Your Thoughts: A list of key insights and reasoning behind your approach
3. Time complexity: O(X) with a detailed explanation (at least 2 sentences)
4. Space complexity: O(X) with a detailed explanation (at least 2 sentences)

For complexity explanations, please be thorough. For example: "Time complexity: O(n) because we iterate through the array only once. This is optimal as we need to examine each element at least once to find the solution." or "Space complexity: O(n) because in the worst case, we store all elements in the hashmap. The additional space scales linearly with the input size."

Your solution should be efficient, well-commented, and handle edge cases.
` : `
Generate a detailed solution for the following coding problem:

PROBLEM STATEMENT:
Expand Down Expand Up @@ -895,7 +885,27 @@ Your solution should be efficient, well-commented, and handle edge cases.
const messages = [
{
role: "system" as const,
content: `You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases, and provide detailed debugging help.
content: language === 'auto' ?
`You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases. First identify the programming language from the code, then provide detailed debugging help in that language.

Your response MUST follow this exact structure with these section headers (use ### for headers):
### Issues Identified
- List each issue as a bullet point with clear explanation

### Specific Improvements and Corrections
- List specific code changes needed as bullet points

### Optimizations
- List any performance optimizations if applicable

### Explanation of Changes Needed
Here provide a clear explanation of why the changes are needed

### Key Points
- Summary bullet points of the most important takeaways

If you include code examples, use proper markdown code blocks with the appropriate language specification.` :
`You are a coding interview assistant helping debug and improve solutions. Analyze these screenshots which include either error messages, incorrect outputs, or test cases, and provide detailed debugging help.

Your response MUST follow this exact structure with these section headers (use ### for headers):
### Issues Identified
Expand All @@ -920,11 +930,17 @@ If you include code examples, use proper markdown code blocks with language spec
content: [
{
type: "text" as const,
text: `I'm solving this coding problem: "${problemInfo.problem_statement}" in ${language}. I need help with debugging or improving my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
text: language === 'auto' ?
`I'm solving this coding problem: "${problemInfo.problem_statement}". Analyze my code to identify the programming language being used, then help me debug or improve my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
1. What issues you found in my code
2. Specific improvements and corrections
3. Any optimizations that would make the solution better
4. A clear explanation of the changes needed` :
`I'm solving this coding problem: "${problemInfo.problem_statement}" in ${language}. I need help with debugging or improving my solution. Here are screenshots of my code, the errors or test cases. Please provide a detailed analysis with:
1. What issues you found in my code
2. Specific improvements and corrections
3. Any optimizations that would make the solution better
4. A clear explanation of the changes needed`
4. A clear explanation of the changes needed`
},
...imageDataList.map(data => ({
type: "image_url" as const,
Expand Down
2 changes: 1 addition & 1 deletion electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ function showMainWindow(): void {
...state.windowSize
});
}
state.mainWindow.setIgnoreMouseEvents(false);
state.mainWindow.setIgnoreMouseEvents(true, { forward: true });

Choose a reason for hiding this comment

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

I think this will prevent the user from interacting with the initial config screen (for example, setting the API key). If you already had the API key saved locally before this change, it's easy to overlook

Copy link
Author

Choose a reason for hiding this comment

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

you can interact it for the when you start... you will not be able interact it after you hide once and show it...

Choose a reason for hiding this comment

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

I don't think that's a good user experience.

Copy link
Author

Choose a reason for hiding this comment

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

on the other hand i think it is better..when you startm it is ineteractable...but after hiding and showing again it is not which will help you interact with other apps.

Choose a reason for hiding this comment

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

I guess this is more complicated than I thought, but Is it possible to have a different behavior for each screen? Interact with the settings screen/button but ignore the mouse for the rest?

state.mainWindow.setAlwaysOnTop(true, "screen-saver", 1);
state.mainWindow.setVisibleOnAllWorkspaces(true, {
visibleOnFullScreen: true
Expand Down
8 changes: 2 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,8 @@ function App() {
try {
const hasKey = await window.electronAPI.checkApiKey()
setHasApiKey(hasKey)

// If no API key is found, show the settings dialog after a short delay
if (!hasKey) {
setTimeout(() => {
setIsSettingsOpen(true)
}, 1000)
showToast("API Key Required", "Please set up your API key in settings to use the application.", "neutral")
}
} catch (error) {
console.error("Failed to check API key:", error)
Expand All @@ -104,7 +100,7 @@ function App() {
if (isInitialized) {
checkApiKey()
}
}, [isInitialized])
}, [isInitialized, showToast])

// Initialize dropdown handler
useEffect(() => {
Expand Down
2 changes: 2 additions & 0 deletions src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ interface HeaderProps {
const LANGUAGES = [
{ value: 'python', label: 'Python' },
{ value: 'javascript', label: 'JavaScript' },
{ value: 'react', label: 'React.js' },
{ value: 'auto', label: 'Auto (Detect from Screen)' },
{ value: 'java', label: 'Java' },
{ value: 'cpp', label: 'C++' },
{ value: 'csharp', label: 'C#' },
Expand Down
3 changes: 3 additions & 0 deletions src/components/Settings/SettingsDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,9 @@ export function SettingsDialog({ open: externalOpen, onOpenChange }: SettingsDia
window.electronAPI.openLink(url);
};

// Return null if not explicitly opened
if (!open) return null;

return (
<Dialog open={open} onOpenChange={handleOpenChange}>
<DialogContent
Expand Down
Loading