Skip to content

Commit f9a6d1b

Browse files
vilpessoaclaude
andauthored
fix: troca modelo para gemini-2.0-flash e melhora repasse de erros (#87)
- gemini-2.5-flash não disponível no tier gratuito padrão; gemini-2.0-flash é estável e gratuito (15 RPM, 1500 RPD) - Proxy agora extrai a mensagem real do erro Gemini e repassa ao frontend em vez de retornar genérico 'Gemini 4xx' - Toast de erro desconhecido exibe a descrição técnica do servidor para facilitar diagnóstico Co-authored-by: Claude <noreply@anthropic.com>
1 parent 986df17 commit f9a6d1b

3 files changed

Lines changed: 14 additions & 6 deletions

File tree

api/gemini.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export default async function handler(req: Request): Promise<Response> {
4747
});
4848
}
4949

50-
const model = body.model ?? 'gemini-2.5-flash';
50+
const model = body.model ?? 'gemini-2.0-flash';
5151
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
5252

5353
const contents = [
@@ -79,9 +79,9 @@ export default async function handler(req: Request): Promise<Response> {
7979
}
8080

8181
if (!upstream.ok) {
82+
const errorText = await upstream.text();
8283
if (upstream.status === 429) {
83-
const text = await upstream.text();
84-
const scope = /per day|daily/i.test(text) ? 'daily' : 'minute';
84+
const scope = /per day|daily/i.test(errorText) ? 'daily' : 'minute';
8585
return new Response(JSON.stringify({ error: 'Rate limited' }), {
8686
status: 429,
8787
headers: { ...cors, 'Content-Type': 'application/json', 'X-Quota-Scope': scope },
@@ -93,7 +93,13 @@ export default async function handler(req: Request): Promise<Response> {
9393
headers: { ...cors, 'Content-Type': 'application/json' },
9494
});
9595
}
96-
return new Response(JSON.stringify({ error: `Gemini API retornou ${upstream.status}` }), {
96+
// Repassa o erro real da Gemini para facilitar diagnóstico
97+
let geminiMessage = `Gemini ${upstream.status}`;
98+
try {
99+
const parsed = JSON.parse(errorText);
100+
if (parsed?.error?.message) geminiMessage = parsed.error.message;
101+
} catch { /* mantém fallback */ }
102+
return new Response(JSON.stringify({ error: geminiMessage }), {
97103
status: 502,
98104
headers: { ...cors, 'Content-Type': 'application/json' },
99105
});

src/components/ai/AIAssistantDropdown.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ export function AIAssistantDropdown({ code, onApply }: AIAssistantDropdownProps)
7272
if (kind === 'empty') {
7373
toast.message(ERROR_COPY.empty);
7474
} else {
75-
toast.error(ERROR_COPY[kind] ?? ERROR_COPY.unknown);
75+
const msg = ERROR_COPY[kind] ?? ERROR_COPY.unknown;
76+
const detail = kind === 'unknown' ? (err as { message?: string })?.message : undefined;
77+
toast.error(msg, detail ? { description: detail } : undefined);
7678
}
7779
} finally {
7880
setLoading(null);

src/services/geminiService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export async function runAiAction(opts: RunAiActionOptions): Promise<string> {
5959
history: history ?? [],
6060
systemInstruction: promptText,
6161
actionContext: ACTION_CONTEXT[action],
62-
model: 'gemini-2.5-flash',
62+
model: 'gemini-2.0-flash',
6363
}),
6464
signal: controller.signal,
6565
});

0 commit comments

Comments
 (0)