Add OpenAI API integration for error analysis with settings UI

Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-19 18:59:19 +00:00
parent 8192bdce0c
commit 1e1a978472
4 changed files with 192 additions and 16 deletions

View File

@@ -32,7 +32,7 @@ jobs:
run: npm ci
- name: Build Next.js
run: npm run build -- --webpack
run: npm run build
env:
BUILD_STATIC: 'true'
NEXT_PUBLIC_FLASK_BACKEND_URL: ${{ vars.NEXT_PUBLIC_FLASK_BACKEND_URL || '' }}

View File

@@ -8,6 +8,7 @@ import { StorageBackendCard } from '@/components/settings/StorageBackendCard';
import { DatabaseStatsCard } from '@/components/settings/DatabaseStatsCard';
import { StorageInfoCard } from '@/components/settings/StorageInfoCard';
import { DatabaseActionsCard } from '@/components/settings/DatabaseActionsCard';
import { OpenAISettingsCard } from '@/components/settings/OpenAISettingsCard';
import { useSettingsState } from '@/hooks/useSettingsState';
import { PageLayout } from '../PageLayout';
@@ -50,6 +51,8 @@ export default function SettingsPage() {
</div>
<div className="grid gap-6 max-w-3xl">
<OpenAISettingsCard />
<PersistenceSettings />
<SchemaHealthCard

View File

@@ -3,23 +3,89 @@ export async function analyzeErrorWithAI(
errorStack?: string,
context?: string
): Promise<string> {
// Simple error analysis without AI - just return helpful debugging info
const lines = ['## Error Analysis\n'];
// Check if OpenAI API key is configured
const apiKey = localStorage.getItem('openai_api_key');
lines.push('**Error Message:**');
lines.push(`\`${errorMessage}\`\n`);
if (context) {
lines.push('**Context:**');
lines.push(`${context}\n`);
}
if (errorStack) {
lines.push('**Possible Solutions:**');
if (!apiKey) {
// Fallback to simple error analysis if no API key
const lines = ['## Error Analysis\n'];
lines.push('**Error Message:**');
lines.push(`\`${errorMessage}\`\n`);
if (context) {
lines.push('**Context:**');
lines.push(`${context}\n`);
}
lines.push('**Note:** Configure your OpenAI API key in Settings to enable AI-powered error analysis.\n');
lines.push('**Basic Troubleshooting:**');
lines.push('1. Check the browser console for more details');
lines.push('2. Try refreshing the page');
lines.push('3. Clear your browser cache and local storage\n');
lines.push('3. Clear your browser cache and local storage');
return lines.join('\n');
}
// Use OpenAI API for advanced error analysis
try {
const contextInfo = context ? `\n\nContext: ${context}` : '';
const stackInfo = errorStack ? `\n\nStack trace: ${errorStack}` : '';
const prompt = `You are a helpful debugging assistant for a code snippet manager app. Analyze this error and provide:
1. A clear explanation of what went wrong (in plain language)
2. Why this error likely occurred
3. 2-3 specific actionable steps to fix it
Error message: ${errorMessage}${contextInfo}${stackInfo}
Keep your response concise, friendly, and focused on practical solutions. Format your response with clear sections using markdown.`;
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`,
},
body: JSON.stringify({
model: 'gpt-4o-mini',
messages: [
{
role: 'system',
content: 'You are a helpful debugging assistant for a code snippet manager app.',
},
{
role: 'user',
content: prompt,
},
],
temperature: 0.7,
max_tokens: 500,
}),
});
if (!response.ok) {
throw new Error(`OpenAI API error: ${response.status} ${response.statusText}`);
}
const data = await response.json();
return data.choices[0]?.message?.content || 'Unable to analyze error.';
} catch (err) {
console.error('Error calling OpenAI API:', err);
// Fallback to simple analysis if API call fails
return `## Error Analysis
**Error Message:**
\`${errorMessage}\`
**Note:** Failed to get AI analysis. ${err instanceof Error ? err.message : 'Unknown error'}
**Basic Troubleshooting:**
1. Check the browser console for more details
2. Try refreshing the page
3. Verify your OpenAI API key in Settings`;
}
return lines.join('\n');
}

View File

@@ -0,0 +1,107 @@
'use client';
import { useState, useEffect } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Label } from '@/components/ui/label';
import { Eye, EyeClosed, Key } from '@phosphor-icons/react';
export function OpenAISettingsCard() {
const [apiKey, setApiKey] = useState('');
const [showKey, setShowKey] = useState(false);
const [saved, setSaved] = useState(false);
useEffect(() => {
// Load the API key from localStorage on mount
const storedKey = localStorage.getItem('openai_api_key');
if (storedKey) {
setApiKey(storedKey);
}
}, []);
const handleSave = () => {
if (apiKey.trim()) {
localStorage.setItem('openai_api_key', apiKey.trim());
setSaved(true);
setTimeout(() => setSaved(false), 2000);
} else {
localStorage.removeItem('openai_api_key');
setSaved(true);
setTimeout(() => setSaved(false), 2000);
}
};
const handleClear = () => {
setApiKey('');
localStorage.removeItem('openai_api_key');
setSaved(true);
setTimeout(() => setSaved(false), 2000);
};
return (
<Card>
<CardHeader>
<div className="flex items-center gap-2">
<Key className="h-5 w-5 text-primary" weight="duotone" />
<CardTitle>OpenAI API Settings</CardTitle>
</div>
<CardDescription>
Configure your OpenAI API key for AI-powered error analysis. Your key is stored locally in your browser.
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="openai-key">OpenAI API Key</Label>
<div className="flex gap-2">
<div className="relative flex-1">
<Input
id="openai-key"
type={showKey ? 'text' : 'password'}
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
placeholder="sk-..."
className="pr-10"
/>
<button
type="button"
onClick={() => setShowKey(!showKey)}
className="absolute right-2 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground"
>
{showKey ? <EyeClosed size={18} /> : <Eye size={18} />}
</button>
</div>
</div>
<p className="text-xs text-muted-foreground">
Get your API key from{' '}
<a
href="https://platform.openai.com/api-keys"
target="_blank"
rel="noopener noreferrer"
className="text-primary hover:underline"
>
OpenAI Platform
</a>
</p>
</div>
<div className="flex gap-2">
<Button onClick={handleSave} disabled={!apiKey.trim()}>
{saved ? 'Saved!' : 'Save API Key'}
</Button>
{apiKey && (
<Button onClick={handleClear} variant="outline">
Clear
</Button>
)}
</div>
{apiKey && (
<div className="text-sm text-muted-foreground bg-muted/50 p-3 rounded-md">
API key is configured. Error analysis will use OpenAI GPT-4.
</div>
)}
</CardContent>
</Card>
);
}