Delete src
Browse files- src/app.tsx +0 -133
src/app.tsx
DELETED
@@ -1,133 +0,0 @@
|
|
1 |
-
'use client'
|
2 |
-
|
3 |
-
import React, { useState, useEffect, useRef } from 'react'
|
4 |
-
import { Button } from "@/components/ui/button"
|
5 |
-
import { Input } from "@/components/ui/input"
|
6 |
-
import { Textarea } from "@/components/ui/textarea"
|
7 |
-
import { Card, CardContent } from "@/components/ui/card"
|
8 |
-
import { ChevronDown, ChevronUp, Send } from 'lucide-react'
|
9 |
-
|
10 |
-
export default function AIChat() {
|
11 |
-
const [messages, setMessages] = useState([])
|
12 |
-
const [input, setInput] = useState('')
|
13 |
-
const [apiKey, setApiKey] = useState('')
|
14 |
-
const [thinking, setThinking] = useState('')
|
15 |
-
const [isThinkingVisible, setIsThinkingVisible] = useState(false)
|
16 |
-
const chatEndRef = useRef(null)
|
17 |
-
|
18 |
-
useEffect(() => {
|
19 |
-
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' })
|
20 |
-
}, [messages])
|
21 |
-
|
22 |
-
const handleSubmit = async (e) => {
|
23 |
-
e.preventDefault()
|
24 |
-
if (!input.trim()) return
|
25 |
-
|
26 |
-
const newMessage = { role: 'user', content: input }
|
27 |
-
setMessages([...messages, newMessage])
|
28 |
-
setInput('')
|
29 |
-
|
30 |
-
try {
|
31 |
-
// Call /think endpoint
|
32 |
-
const thinkResponse = await fetch('/think', {
|
33 |
-
method: 'POST',
|
34 |
-
headers: { 'Content-Type': 'application/json' },
|
35 |
-
body: JSON.stringify({ messages: [...messages, newMessage], api_key: apiKey }),
|
36 |
-
})
|
37 |
-
|
38 |
-
if (!thinkResponse.ok) throw new Error('Think request failed')
|
39 |
-
|
40 |
-
const reader = thinkResponse.body.getReader()
|
41 |
-
let thinkingContent = ''
|
42 |
-
|
43 |
-
while (true) {
|
44 |
-
const { done, value } = await reader.read()
|
45 |
-
if (done) break
|
46 |
-
const chunk = new TextDecoder().decode(value)
|
47 |
-
thinkingContent += chunk
|
48 |
-
setThinking(thinkingContent)
|
49 |
-
}
|
50 |
-
|
51 |
-
// Call /chat endpoint with the thinking result
|
52 |
-
const chatResponse = await fetch('/chat', {
|
53 |
-
method: 'POST',
|
54 |
-
headers: { 'Content-Type': 'application/json' },
|
55 |
-
body: JSON.stringify({ messages: [...messages, newMessage, { role: 'assistant', content: thinkingContent }], api_key: apiKey }),
|
56 |
-
})
|
57 |
-
|
58 |
-
if (!chatResponse.ok) throw new Error('Chat request failed')
|
59 |
-
|
60 |
-
const chatReader = chatResponse.body.getReader()
|
61 |
-
let chatContent = ''
|
62 |
-
|
63 |
-
while (true) {
|
64 |
-
const { done, value } = await chatReader.read()
|
65 |
-
if (done) break
|
66 |
-
const chunk = new TextDecoder().decode(value)
|
67 |
-
chatContent += chunk
|
68 |
-
setMessages(prev => [...prev.slice(0, -1), { role: 'assistant', content: chatContent }])
|
69 |
-
}
|
70 |
-
} catch (error) {
|
71 |
-
console.error('Error:', error)
|
72 |
-
setMessages(prev => [...prev, { role: 'assistant', content: 'An error occurred. Please try again.' }])
|
73 |
-
}
|
74 |
-
}
|
75 |
-
|
76 |
-
return (
|
77 |
-
<div className="min-h-screen bg-gray-900 text-white p-4 flex flex-col">
|
78 |
-
<Card className="flex-grow overflow-auto mb-4 bg-gray-800 bg-opacity-50 backdrop-filter backdrop-blur-lg">
|
79 |
-
<CardContent className="p-4">
|
80 |
-
{messages.map((message, index) => (
|
81 |
-
<div key={index} className={`mb-4 ${message.role === 'user' ? 'text-right' : 'text-left'}`}>
|
82 |
-
<div className={`inline-block p-2 rounded-lg ${message.role === 'user' ? 'bg-blue-600' : 'bg-gray-700'}`}>
|
83 |
-
{message.content}
|
84 |
-
</div>
|
85 |
-
{message.role === 'assistant' && thinking && (
|
86 |
-
<div className="mt-2">
|
87 |
-
<Button
|
88 |
-
variant="ghost"
|
89 |
-
size="sm"
|
90 |
-
onClick={() => setIsThinkingVisible(!isThinkingVisible)}
|
91 |
-
className="text-xs text-gray-400"
|
92 |
-
>
|
93 |
-
{isThinkingVisible ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
94 |
-
Thinking Process
|
95 |
-
</Button>
|
96 |
-
{isThinkingVisible && (
|
97 |
-
<div className="mt-2 text-xs text-gray-400 bg-gray-800 p-2 rounded">
|
98 |
-
{thinking.split('\n').map((line, i) => {
|
99 |
-
if (line.startsWith('<thinking>') || line.startsWith('<step>')) {
|
100 |
-
return <p key={i}>{line.replace(/<\/?thinking>|<\/?step>/g, '')}</p>
|
101 |
-
}
|
102 |
-
return null
|
103 |
-
})}
|
104 |
-
</div>
|
105 |
-
)}
|
106 |
-
</div>
|
107 |
-
)}
|
108 |
-
</div>
|
109 |
-
))}
|
110 |
-
<div ref={chatEndRef} />
|
111 |
-
</CardContent>
|
112 |
-
</Card>
|
113 |
-
<form onSubmit={handleSubmit} className="flex gap-2">
|
114 |
-
<Input
|
115 |
-
type="text"
|
116 |
-
value={apiKey}
|
117 |
-
onChange={(e) => setApiKey(e.target.value)}
|
118 |
-
placeholder="Enter API Key (optional)"
|
119 |
-
className="flex-grow bg-gray-800 text-white"
|
120 |
-
/>
|
121 |
-
<Textarea
|
122 |
-
value={input}
|
123 |
-
onChange={(e) => setInput(e.target.value)}
|
124 |
-
placeholder="Type your message..."
|
125 |
-
className="flex-grow bg-gray-800 text-white"
|
126 |
-
/>
|
127 |
-
<Button type="submit" className="bg-blue-600 hover:bg-blue-700">
|
128 |
-
<Send className="h-4 w-4" />
|
129 |
-
</Button>
|
130 |
-
</form>
|
131 |
-
</div>
|
132 |
-
)
|
133 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|