File size: 5,378 Bytes
6e62ad1 | 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 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | import { useState } from 'react'
interface TeachPanelProps {
onTeach: (question: string, answer: string) => Promise<any>
loading: boolean
}
interface TeachResult {
question: string
answer: string
tokensWritten: number
message: string
timestamp: number
}
export function TeachPanel({ onTeach, loading }: TeachPanelProps) {
const [question, setQuestion] = useState('')
const [answer, setAnswer] = useState('')
const [history, setHistory] = useState<TeachResult[]>([])
const handleTeach = async () => {
if (!question.trim() || !answer.trim() || loading) return
try {
const resp = await onTeach(question.trim(), answer.trim())
setHistory(prev => [{
question: question.trim(),
answer: answer.trim(),
tokensWritten: resp.tokens_written,
message: resp.message,
timestamp: Date.now(),
}, ...prev])
setQuestion('')
setAnswer('')
} catch {
setHistory(prev => [{
question: question.trim(),
answer: answer.trim(),
tokensWritten: 0,
message: 'Error: API not reachable',
timestamp: Date.now(),
}, ...prev])
}
}
return (
<div className="flex flex-col h-full glass-card overflow-hidden">
<div className="px-5 py-3 border-b border-pal-border">
<div className="flex items-center gap-2">
<span className="text-base">📚</span>
<h2 className="text-sm font-semibold text-pal-text">Teach</h2>
<span className="text-xs text-pal-muted">O(1) learning</span>
</div>
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-3">
{/* Input form */}
<div className="space-y-2">
<div>
<label className="text-[11px] text-pal-muted font-medium uppercase tracking-wide block mb-1">
Question
</label>
<input
type="text"
value={question}
onChange={e => setQuestion(e.target.value)}
onKeyDown={e => e.key === 'Enter' && !e.shiftKey && handleTeach()}
placeholder="what is the capital of france"
className="w-full bg-pal-surface border border-pal-border rounded-lg px-3 py-2 text-sm text-pal-text placeholder:text-pal-muted focus:outline-none focus:border-pal-green/50 transition-all"
/>
</div>
<div>
<label className="text-[11px] text-pal-muted font-medium uppercase tracking-wide block mb-1">
Answer
</label>
<input
type="text"
value={answer}
onChange={e => setAnswer(e.target.value)}
onKeyDown={e => e.key === 'Enter' && !e.shiftKey && handleTeach()}
placeholder="paris"
className="w-full bg-pal-surface border border-pal-border rounded-lg px-3 py-2 text-sm text-pal-text placeholder:text-pal-muted focus:outline-none focus:border-pal-green/50 transition-all"
/>
</div>
<button
onClick={handleTeach}
disabled={!question.trim() || !answer.trim() || loading}
className="w-full py-2 rounded-lg bg-gradient-to-r from-pal-green to-pal-accent2 text-white font-semibold text-sm transition-all hover:scale-[1.02] hover:shadow-lg hover:shadow-pal-green/20 disabled:opacity-30 disabled:cursor-not-allowed disabled:hover:scale-100"
>
{loading ? 'Teaching...' : '⚡ Teach Instantly'}
</button>
</div>
{/* History */}
{history.length > 0 && (
<div className="space-y-2 pt-2 border-t border-pal-border">
<span className="text-[11px] text-pal-muted font-medium uppercase tracking-wide">
Taught ({history.length})
</span>
{history.map((h, i) => (
<div
key={i}
className="p-2.5 rounded-lg bg-pal-surface/60 border border-pal-border/50 animate-slide-up"
>
<div className="flex items-start justify-between gap-2 mb-1">
<div className="flex-1 min-w-0">
<div className="text-xs text-pal-text font-medium truncate">
{h.question}
</div>
<div className="text-xs text-pal-green font-medium">
→ {h.answer}
</div>
</div>
{h.tokensWritten > 0 && (
<span className="text-[10px] px-1.5 py-0.5 rounded-full bg-pal-green/10 text-pal-green font-mono whitespace-nowrap">
+{h.tokensWritten} tok
</span>
)}
</div>
{h.message && (
<p className="text-[10px] text-pal-muted mt-1">{h.message}</p>
)}
</div>
))}
</div>
)}
{history.length === 0 && (
<div className="text-center py-8">
<div className="text-3xl mb-2 opacity-50">⚡</div>
<p className="text-xs text-pal-muted">
Teach PALIMPSESTE new facts.<br/>
Each fact is written to memory in O(1) —<br/>
instantly retrievable, never forgotten.
</p>
</div>
)}
</div>
</div>
)
}
|