Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 1x 9x 9x 1x 8x 7x 7x 7x 7x 1x 6x 6x 1x 6x 6x 1x 6x 6x 6x 1x 5x 1x 4x 4x 13x 1x 12x 3x 1x 2x | import { GoogleGenAI } from '@google/genai'
import { VocabularyItem, isVocabularyItem } from '@/core/domain/VocabularyItem'
import { IVocabularyRepository } from '@/core/application/interfaces/IVocabularyRepository'
/**
* GeminiVocabularyRepository
* Infrastructure implementation of IVocabularyRepository using Google's Gemini AI.
*/
export class GeminiVocabularyRepository implements IVocabularyRepository {
private readonly ai: GoogleGenAI
constructor(apiKey: string) {
if (!apiKey) {
throw new Error('GEMINI_API_KEY is required')
}
this.ai = new GoogleGenAI({ apiKey })
}
/**
* Fetches vocabulary items from Gemini AI
*/
async getVocabularyItems(count: number = 5): Promise<VocabularyItem[]> {
const prompt = `Elabore ${count} palavras distintas, comuns e não comuns e seus respectivos significados e um exemplo de uso. Retorne um JSON estrito no formato [{"word": "", "description": "", "useCase": ""}]. Seja criativo na escolha das palavras. Não adicione quebras de linhas ou crases de markdown. \`word\` em inglês, \`description\` em português e \`useCase\` em português`
const response = await this.ai.models.generateContent({
model: 'gemini-3-flash-preview',
contents: prompt,
config: {
systemInstruction: 'Responda somente questões relacionadas ao ensino de inglês. Retorne apenas JSON válido.',
},
})
const text = response.text
// console.log(text)
if (!text) {
throw new Error('Empty response from Gemini AI')
}
// Clean the response text (remove potential markdown code blocks)
let cleanedText = text.trim()
if (cleanedText.startsWith('```json')) {
cleanedText = cleanedText.slice(7)
}
Iif (cleanedText.startsWith('```')) {
cleanedText = cleanedText.slice(3)
}
if (cleanedText.endsWith('```')) {
cleanedText = cleanedText.slice(0, -3)
}
cleanedText = cleanedText.trim()
let parsed: unknown
try {
parsed = JSON.parse(cleanedText)
} catch {
throw new Error('Failed to parse Gemini response as JSON')
}
if (!Array.isArray(parsed)) {
throw new Error('Gemini response is not an array')
}
const items: VocabularyItem[] = []
for (const item of parsed) {
if (!isVocabularyItem(item)) {
throw new Error('Invalid vocabulary item structure in response')
}
items.push(item)
}
if (items.length !== count) {
throw new Error(`Expected ${count} items but received ${items.length}`)
}
return items
}
}
|