Reubencf Claude commited on
Commit
8c79bdb
·
1 Parent(s): aea1786

fix: Update Gemini AI to use server-side API key and gemini-flash-latest model

Browse files

- Use process.env.GEMINI_API_KEY from server instead of client-side input
- Update model to gemini-flash-latest for both chat and transcribe routes
- Remove API key input UI from frontend
- Enable immediate user input without requiring API key entry

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>

app/api/gemini/chat/route.ts CHANGED
@@ -1,6 +1,6 @@
1
  import { NextRequest, NextResponse } from 'next/server'
2
 
3
- const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent'
4
  const GEMINI_API_KEY = process.env.GEMINI_API_KEY
5
 
6
  export async function POST(request: NextRequest) {
 
1
  import { NextRequest, NextResponse } from 'next/server'
2
 
3
+ const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent'
4
  const GEMINI_API_KEY = process.env.GEMINI_API_KEY
5
 
6
  export async function POST(request: NextRequest) {
app/api/gemini/transcribe/route.ts CHANGED
@@ -3,16 +3,17 @@ import { NextRequest, NextResponse } from 'next/server'
3
  // Note: For audio transcription, we'll use Gemini's multimodal capabilities
4
  // In production, you might want to use Google Cloud Speech-to-Text API for better accuracy
5
 
 
 
6
  export async function POST(request: NextRequest) {
7
  try {
8
  const formData = await request.formData()
9
  const audioFile = formData.get('audio') as File
10
- const apiKey = formData.get('apiKey') as string
11
 
12
- if (!apiKey) {
13
  return NextResponse.json(
14
- { error: 'API key is required' },
15
- { status: 400 }
16
  )
17
  }
18
 
@@ -30,7 +31,7 @@ export async function POST(request: NextRequest) {
30
 
31
  // Use Gemini API to transcribe
32
  // Note: Gemini 1.5 Pro supports audio, but Flash might have limitations
33
- const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent'
34
 
35
  const requestBody = {
36
  contents: [{
@@ -55,7 +56,7 @@ export async function POST(request: NextRequest) {
55
  }
56
  }
57
 
58
- const response = await fetch(`${GEMINI_API_URL}?key=${apiKey}`, {
59
  method: 'POST',
60
  headers: {
61
  'Content-Type': 'application/json',
 
3
  // Note: For audio transcription, we'll use Gemini's multimodal capabilities
4
  // In production, you might want to use Google Cloud Speech-to-Text API for better accuracy
5
 
6
+ const GEMINI_API_KEY = process.env.GEMINI_API_KEY
7
+
8
  export async function POST(request: NextRequest) {
9
  try {
10
  const formData = await request.formData()
11
  const audioFile = formData.get('audio') as File
 
12
 
13
+ if (!GEMINI_API_KEY) {
14
  return NextResponse.json(
15
+ { error: 'Gemini API key not configured on server. Please set GEMINI_API_KEY environment variable.' },
16
+ { status: 500 }
17
  )
18
  }
19
 
 
31
 
32
  // Use Gemini API to transcribe
33
  // Note: Gemini 1.5 Pro supports audio, but Flash might have limitations
34
+ const GEMINI_API_URL = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent'
35
 
36
  const requestBody = {
37
  contents: [{
 
56
  }
57
  }
58
 
59
+ const response = await fetch(`${GEMINI_API_URL}?key=${GEMINI_API_KEY}`, {
60
  method: 'POST',
61
  headers: {
62
  'Content-Type': 'application/json',
app/gemini/page.tsx CHANGED
@@ -19,8 +19,6 @@ export default function GeminiAIApp() {
19
  const [isRecording, setIsRecording] = useState(false)
20
  const [selectedImage, setSelectedImage] = useState<string | null>(null)
21
  const [activeTab, setActiveTab] = useState<'chat' | 'transcribe' | 'image'>('chat')
22
- const [apiKey, setApiKey] = useState('')
23
- const [showApiKeyInput, setShowApiKeyInput] = useState(true)
24
 
25
  const fileInputRef = useRef<HTMLInputElement>(null)
26
  const audioInputRef = useRef<HTMLInputElement>(null)
@@ -28,26 +26,10 @@ export default function GeminiAIApp() {
28
  const mediaRecorderRef = useRef<MediaRecorder | null>(null)
29
  const audioChunksRef = useRef<Blob[]>([])
30
 
31
- useEffect(() => {
32
- // Check for stored API key
33
- const storedKey = localStorage.getItem('gemini_api_key')
34
- if (storedKey) {
35
- setApiKey(storedKey)
36
- setShowApiKeyInput(false)
37
- }
38
- }, [])
39
-
40
  useEffect(() => {
41
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
42
  }, [messages])
43
 
44
- const saveApiKey = () => {
45
- if (apiKey.trim()) {
46
- localStorage.setItem('gemini_api_key', apiKey)
47
- setShowApiKeyInput(false)
48
- }
49
- }
50
-
51
  const handleSendMessage = async () => {
52
  if (!inputText.trim() && !selectedImage) return
53
 
@@ -72,7 +54,6 @@ export default function GeminiAIApp() {
72
  body: JSON.stringify({
73
  message: inputText,
74
  imageUrl: selectedImage,
75
- apiKey: apiKey,
76
  history: messages.slice(-10) // Send last 10 messages for context
77
  })
78
  })
@@ -154,7 +135,6 @@ export default function GeminiAIApp() {
154
  setIsLoading(true)
155
  const formData = new FormData()
156
  formData.append('audio', audioBlob, 'recording.wav')
157
- formData.append('apiKey', apiKey)
158
 
159
  try {
160
  const response = await fetch('/api/gemini/transcribe', {
@@ -194,30 +174,6 @@ export default function GeminiAIApp() {
194
  <p className="text-blue-100">Chat, Transcribe, and Analyze Images with AI</p>
195
  </div>
196
 
197
- {/* API Key Input */}
198
- {showApiKeyInput && (
199
- <div className="p-4 bg-yellow-50 border-b border-yellow-200">
200
- <div className="flex gap-2">
201
- <input
202
- type="password"
203
- placeholder="Enter your Gemini API Key"
204
- value={apiKey}
205
- onChange={(e) => setApiKey(e.target.value)}
206
- className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
207
- />
208
- <button
209
- onClick={saveApiKey}
210
- className="px-6 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
211
- >
212
- Save Key
213
- </button>
214
- </div>
215
- <p className="text-sm text-gray-600 mt-2">
216
- Get your API key from <a href="https://makersuite.google.com/app/apikey" target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:underline">Google AI Studio</a>
217
- </p>
218
- </div>
219
- )}
220
-
221
  {/* Tabs */}
222
  <div className="flex border-b border-gray-200">
223
  <button
 
19
  const [isRecording, setIsRecording] = useState(false)
20
  const [selectedImage, setSelectedImage] = useState<string | null>(null)
21
  const [activeTab, setActiveTab] = useState<'chat' | 'transcribe' | 'image'>('chat')
 
 
22
 
23
  const fileInputRef = useRef<HTMLInputElement>(null)
24
  const audioInputRef = useRef<HTMLInputElement>(null)
 
26
  const mediaRecorderRef = useRef<MediaRecorder | null>(null)
27
  const audioChunksRef = useRef<Blob[]>([])
28
 
 
 
 
 
 
 
 
 
 
29
  useEffect(() => {
30
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
31
  }, [messages])
32
 
 
 
 
 
 
 
 
33
  const handleSendMessage = async () => {
34
  if (!inputText.trim() && !selectedImage) return
35
 
 
54
  body: JSON.stringify({
55
  message: inputText,
56
  imageUrl: selectedImage,
 
57
  history: messages.slice(-10) // Send last 10 messages for context
58
  })
59
  })
 
135
  setIsLoading(true)
136
  const formData = new FormData()
137
  formData.append('audio', audioBlob, 'recording.wav')
 
138
 
139
  try {
140
  const response = await fetch('/api/gemini/transcribe', {
 
174
  <p className="text-blue-100">Chat, Transcribe, and Analyze Images with AI</p>
175
  </div>
176
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  {/* Tabs */}
178
  <div className="flex border-b border-gray-200">
179
  <button