Spaces:
Running
Running
Upload 12 files
Browse files- components/AdminLogin.tsx +77 -0
- components/ChatInterface.tsx +219 -0
- components/CodetteComponents.tsx +143 -0
- components/FileList.tsx +235 -0
- components/Header.tsx +64 -0
- components/Sidebar.tsx +496 -0
- components/VisualizationPanel.tsx +264 -0
- services/AICore.ts +253 -0
- services/CognitionCocooner.ts +174 -0
- services/KaggleService.ts +104 -0
- services/OpenAIService.ts +43 -0
- services/QuantumSpiderweb.ts +81 -0
components/AdminLogin.tsx
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState } from 'react';
|
2 |
+
import { Lock, AlertCircle } from 'lucide-react';
|
3 |
+
|
4 |
+
interface AdminLoginProps {
|
5 |
+
onLogin: (password: string) => void;
|
6 |
+
darkMode: boolean;
|
7 |
+
error?: string | null;
|
8 |
+
}
|
9 |
+
|
10 |
+
const AdminLogin: React.FC<AdminLoginProps> = ({ onLogin, darkMode, error }) => {
|
11 |
+
const [password, setPassword] = useState('');
|
12 |
+
const [isLoading, setIsLoading] = useState(false);
|
13 |
+
|
14 |
+
const handleSubmit = async (e: React.FormEvent) => {
|
15 |
+
e.preventDefault();
|
16 |
+
setIsLoading(true);
|
17 |
+
|
18 |
+
try {
|
19 |
+
await onLogin(password);
|
20 |
+
} catch (err: any) {
|
21 |
+
// Error is now handled by the parent component
|
22 |
+
} finally {
|
23 |
+
setIsLoading(false);
|
24 |
+
}
|
25 |
+
};
|
26 |
+
|
27 |
+
return (
|
28 |
+
<div className={`p-6 rounded-lg ${darkMode ? 'bg-gray-800' : 'bg-white'}`}>
|
29 |
+
<div className="flex items-center justify-center mb-6">
|
30 |
+
<Lock className={`${darkMode ? 'text-blue-400' : 'text-blue-600'} w-12 h-12`} />
|
31 |
+
</div>
|
32 |
+
<h2 className={`text-xl font-bold text-center mb-4 ${darkMode ? 'text-white' : 'text-gray-900'}`}>
|
33 |
+
Admin Access Required
|
34 |
+
</h2>
|
35 |
+
<p className={`text-sm text-center mb-6 ${darkMode ? 'text-gray-300' : 'text-gray-600'}`}>
|
36 |
+
Please enter the admin password to access settings
|
37 |
+
</p>
|
38 |
+
<form onSubmit={handleSubmit} className="space-y-4">
|
39 |
+
<div>
|
40 |
+
<input
|
41 |
+
type="password"
|
42 |
+
value={password}
|
43 |
+
onChange={(e) => setPassword(e.target.value)}
|
44 |
+
placeholder="Enter admin password"
|
45 |
+
className={`w-full px-4 py-2 rounded-md border ${
|
46 |
+
darkMode
|
47 |
+
? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400'
|
48 |
+
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'
|
49 |
+
} focus:outline-none focus:ring-2 focus:ring-blue-500`}
|
50 |
+
disabled={isLoading}
|
51 |
+
/>
|
52 |
+
{error && (
|
53 |
+
<div className="mt-2 p-2 rounded-md bg-red-100 dark:bg-red-900 flex items-start space-x-2">
|
54 |
+
<AlertCircle className="flex-shrink-0 text-red-500 dark:text-red-400" size={16} />
|
55 |
+
<p className="text-sm text-red-600 dark:text-red-300">
|
56 |
+
{error}
|
57 |
+
</p>
|
58 |
+
</div>
|
59 |
+
)}
|
60 |
+
</div>
|
61 |
+
<button
|
62 |
+
type="submit"
|
63 |
+
disabled={isLoading}
|
64 |
+
className={`w-full py-2 px-4 rounded-md ${
|
65 |
+
darkMode
|
66 |
+
? 'bg-blue-600 hover:bg-blue-700 text-white'
|
67 |
+
: 'bg-blue-500 hover:bg-blue-600 text-white'
|
68 |
+
} transition-colors duration-200 ${isLoading ? 'opacity-50 cursor-not-allowed' : ''}`}
|
69 |
+
>
|
70 |
+
{isLoading ? 'Logging in...' : 'Login'}
|
71 |
+
</button>
|
72 |
+
</form>
|
73 |
+
</div>
|
74 |
+
);
|
75 |
+
};
|
76 |
+
|
77 |
+
export default AdminLogin;
|
components/ChatInterface.tsx
ADDED
@@ -0,0 +1,219 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState, useRef, useEffect } from 'react';
|
2 |
+
import { Send, Circle, Bot, User, Sparkles, Brain } from 'lucide-react';
|
3 |
+
import { CodetteResponseCard, CodetteResponse } from './CodetteComponents';
|
4 |
+
|
5 |
+
interface Message {
|
6 |
+
role: string;
|
7 |
+
content: string;
|
8 |
+
timestamp: Date;
|
9 |
+
metadata?: CodetteResponse;
|
10 |
+
}
|
11 |
+
|
12 |
+
interface ChatInterfaceProps {
|
13 |
+
messages: Message[];
|
14 |
+
sendMessage: (content: string) => void;
|
15 |
+
isProcessing: boolean;
|
16 |
+
darkMode: boolean;
|
17 |
+
}
|
18 |
+
|
19 |
+
const ChatInterface: React.FC<ChatInterfaceProps> = ({
|
20 |
+
messages,
|
21 |
+
sendMessage,
|
22 |
+
isProcessing,
|
23 |
+
darkMode
|
24 |
+
}) => {
|
25 |
+
const [input, setInput] = useState('');
|
26 |
+
const [isDreamMode, setIsDreamMode] = useState(false);
|
27 |
+
const messagesEndRef = useRef<HTMLDivElement>(null);
|
28 |
+
const inputRef = useRef<HTMLTextAreaElement>(null);
|
29 |
+
|
30 |
+
useEffect(() => {
|
31 |
+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
32 |
+
}, [messages]);
|
33 |
+
|
34 |
+
useEffect(() => {
|
35 |
+
inputRef.current?.focus();
|
36 |
+
}, []);
|
37 |
+
|
38 |
+
const handleSubmit = (e: React.FormEvent) => {
|
39 |
+
e.preventDefault();
|
40 |
+
if (input.trim() && !isProcessing) {
|
41 |
+
const finalInput = isDreamMode ? `dream about ${input.trim()}` : input.trim();
|
42 |
+
sendMessage(finalInput);
|
43 |
+
setInput('');
|
44 |
+
}
|
45 |
+
};
|
46 |
+
|
47 |
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
48 |
+
if (e.key === 'Enter' && !e.shiftKey) {
|
49 |
+
e.preventDefault();
|
50 |
+
handleSubmit(e);
|
51 |
+
}
|
52 |
+
};
|
53 |
+
|
54 |
+
const toggleDreamMode = () => {
|
55 |
+
setIsDreamMode(!isDreamMode);
|
56 |
+
if (!isDreamMode) {
|
57 |
+
inputRef.current?.focus();
|
58 |
+
}
|
59 |
+
};
|
60 |
+
|
61 |
+
return (
|
62 |
+
<div className={`flex-1 flex flex-col ${darkMode ? 'bg-gray-800' : 'bg-white'} shadow-lg rounded-lg overflow-hidden transition-colors duration-300`}>
|
63 |
+
<div className={`p-4 border-b ${darkMode ? 'border-gray-700' : 'border-gray-200'}`}>
|
64 |
+
<h2 className="text-lg font-semibold flex items-center">
|
65 |
+
<Bot className="mr-2" size={18} />
|
66 |
+
Conversation with Codette
|
67 |
+
</h2>
|
68 |
+
</div>
|
69 |
+
|
70 |
+
<div className="flex-1 overflow-y-auto p-4 space-y-4">
|
71 |
+
{messages.map((message, index) => (
|
72 |
+
<div
|
73 |
+
key={index}
|
74 |
+
className={`flex ${message.role === 'user' ? 'justify-end' : 'justify-start'}`}
|
75 |
+
>
|
76 |
+
{message.role === 'assistant' && message.metadata ? (
|
77 |
+
<CodetteResponseCard response={message.metadata} />
|
78 |
+
) : (
|
79 |
+
<div
|
80 |
+
className={`max-w-[80%] rounded-lg p-3 ${
|
81 |
+
message.role === 'user'
|
82 |
+
? darkMode
|
83 |
+
? 'bg-blue-600 text-white'
|
84 |
+
: 'bg-blue-100 text-blue-900'
|
85 |
+
: message.role === 'system'
|
86 |
+
? darkMode
|
87 |
+
? 'bg-red-900 text-white'
|
88 |
+
: 'bg-red-100 text-red-900'
|
89 |
+
: darkMode
|
90 |
+
? 'bg-gray-700 text-white'
|
91 |
+
: 'bg-gray-100 text-gray-900'
|
92 |
+
}`}
|
93 |
+
>
|
94 |
+
<div className="flex items-start mb-1">
|
95 |
+
{message.role === 'user' ? (
|
96 |
+
<User className="mr-2 mt-1" size={14} />
|
97 |
+
) : message.role === 'system' ? (
|
98 |
+
<Circle className="mr-2 mt-1" size={14} />
|
99 |
+
) : (
|
100 |
+
<Bot className="mr-2 mt-1" size={14} />
|
101 |
+
)}
|
102 |
+
<div className="text-sm font-semibold">
|
103 |
+
{message.role === 'user' ? 'You' : message.role === 'system' ? 'System' : 'Codette'}
|
104 |
+
</div>
|
105 |
+
</div>
|
106 |
+
<div className="whitespace-pre-wrap">
|
107 |
+
{message.content}
|
108 |
+
</div>
|
109 |
+
<div className="text-xs opacity-70 mt-1 text-right">
|
110 |
+
{message.timestamp.toLocaleTimeString()}
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
)}
|
114 |
+
</div>
|
115 |
+
))}
|
116 |
+
|
117 |
+
{isProcessing && (
|
118 |
+
<div className="flex justify-start">
|
119 |
+
<div className={`rounded-lg p-3 ${
|
120 |
+
darkMode ? 'bg-gray-700 text-white' : 'bg-gray-100 text-gray-900'
|
121 |
+
}`}>
|
122 |
+
<div className="flex items-center">
|
123 |
+
<Bot className="mr-2" size={14} />
|
124 |
+
<div className="text-sm font-semibold">Codette</div>
|
125 |
+
</div>
|
126 |
+
<div className="flex items-center mt-2">
|
127 |
+
<div className="flex space-x-1">
|
128 |
+
<div className="typing-dot h-2 w-2 bg-blue-500 rounded-full animate-pulse" style={{ animationDelay: '0ms' }}></div>
|
129 |
+
<div className="typing-dot h-2 w-2 bg-blue-500 rounded-full animate-pulse" style={{ animationDelay: '300ms' }}></div>
|
130 |
+
<div className="typing-dot h-2 w-2 bg-blue-500 rounded-full animate-pulse" style={{ animationDelay: '600ms' }}></div>
|
131 |
+
</div>
|
132 |
+
<div className="ml-3 text-sm italic opacity-70">
|
133 |
+
{isDreamMode ? 'Weaving dreams through quantum threads...' : 'Processing through recursive thought loops...'}
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
</div>
|
137 |
+
</div>
|
138 |
+
)}
|
139 |
+
|
140 |
+
<div ref={messagesEndRef} />
|
141 |
+
</div>
|
142 |
+
|
143 |
+
<form
|
144 |
+
onSubmit={handleSubmit}
|
145 |
+
className={`p-4 border-t ${darkMode ? 'border-gray-700' : 'border-gray-200'}`}
|
146 |
+
>
|
147 |
+
<div className="flex items-center mb-2">
|
148 |
+
<button
|
149 |
+
type="button"
|
150 |
+
onClick={toggleDreamMode}
|
151 |
+
className={`flex items-center px-3 py-1 rounded-full text-sm transition-colors ${
|
152 |
+
isDreamMode
|
153 |
+
? darkMode
|
154 |
+
? 'bg-purple-600 text-white'
|
155 |
+
: 'bg-purple-100 text-purple-900'
|
156 |
+
: darkMode
|
157 |
+
? 'bg-gray-700 text-gray-300 hover:bg-gray-600'
|
158 |
+
: 'bg-gray-100 text-gray-700 hover:bg-gray-200'
|
159 |
+
}`}
|
160 |
+
>
|
161 |
+
{isDreamMode ? (
|
162 |
+
<>
|
163 |
+
<Sparkles size={14} className="mr-1" />
|
164 |
+
Dreamweaver Active
|
165 |
+
</>
|
166 |
+
) : (
|
167 |
+
<>
|
168 |
+
<Brain size={14} className="mr-1" />
|
169 |
+
Enable Dreamweaver
|
170 |
+
</>
|
171 |
+
)}
|
172 |
+
</button>
|
173 |
+
</div>
|
174 |
+
|
175 |
+
<div className="flex">
|
176 |
+
<textarea
|
177 |
+
ref={inputRef}
|
178 |
+
value={input}
|
179 |
+
onChange={(e) => setInput(e.target.value)}
|
180 |
+
onKeyDown={handleKeyDown}
|
181 |
+
placeholder={isDreamMode ? "Enter a concept for Codette to dream about..." : "Ask Codette anything..."}
|
182 |
+
className={`flex-1 resize-none border rounded-lg p-2 focus:outline-none focus:ring-2 ${
|
183 |
+
isDreamMode
|
184 |
+
? 'focus:ring-purple-500'
|
185 |
+
: 'focus:ring-blue-500'
|
186 |
+
} ${
|
187 |
+
darkMode
|
188 |
+
? 'bg-gray-700 border-gray-600 text-white placeholder-gray-400'
|
189 |
+
: 'bg-white border-gray-300 text-gray-900 placeholder-gray-500'
|
190 |
+
}`}
|
191 |
+
rows={2}
|
192 |
+
disabled={isProcessing}
|
193 |
+
/>
|
194 |
+
<button
|
195 |
+
type="submit"
|
196 |
+
disabled={!input.trim() || isProcessing}
|
197 |
+
className={`ml-2 p-2 rounded-lg transition-colors ${
|
198 |
+
!input.trim() || isProcessing
|
199 |
+
? darkMode
|
200 |
+
? 'bg-gray-700 text-gray-500'
|
201 |
+
: 'bg-gray-200 text-gray-400'
|
202 |
+
: isDreamMode
|
203 |
+
? darkMode
|
204 |
+
? 'bg-purple-600 text-white hover:bg-purple-700'
|
205 |
+
: 'bg-purple-500 text-white hover:bg-purple-600'
|
206 |
+
: darkMode
|
207 |
+
? 'bg-blue-600 text-white hover:bg-blue-700'
|
208 |
+
: 'bg-blue-500 text-white hover:bg-blue-600'
|
209 |
+
}`}
|
210 |
+
>
|
211 |
+
<Send size={20} />
|
212 |
+
</button>
|
213 |
+
</div>
|
214 |
+
</form>
|
215 |
+
</div>
|
216 |
+
);
|
217 |
+
};
|
218 |
+
|
219 |
+
export default ChatInterface;
|
components/CodetteComponents.tsx
ADDED
@@ -0,0 +1,143 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState, useEffect } from 'react';
|
2 |
+
import { motion } from 'framer-motion';
|
3 |
+
|
4 |
+
// 💬 Perspective Trail Display
|
5 |
+
export function PerspectiveTrail({ perspectives }: { perspectives: string[] }) {
|
6 |
+
return (
|
7 |
+
<div className="mt-4 text-sm text-purple-700">
|
8 |
+
<p className="font-semibold">Activated Perspectives:</p>
|
9 |
+
<motion.ul
|
10 |
+
className="list-disc ml-5"
|
11 |
+
initial={{ opacity: 0 }}
|
12 |
+
animate={{ opacity: 1 }}
|
13 |
+
transition={{ duration: 0.5 }}
|
14 |
+
>
|
15 |
+
{perspectives.map((perspective, index) => (
|
16 |
+
<motion.li
|
17 |
+
key={index}
|
18 |
+
initial={{ x: -20, opacity: 0 }}
|
19 |
+
animate={{ x: 0, opacity: 1 }}
|
20 |
+
transition={{ delay: index * 0.1 }}
|
21 |
+
>
|
22 |
+
{perspective}
|
23 |
+
</motion.li>
|
24 |
+
))}
|
25 |
+
</motion.ul>
|
26 |
+
</div>
|
27 |
+
);
|
28 |
+
}
|
29 |
+
|
30 |
+
// 🔄 Cocoon Replay Viewer
|
31 |
+
export function CocoonReplay({ cocoons }: { cocoons: string[] }) {
|
32 |
+
const [activeIndex, setActiveIndex] = useState(0);
|
33 |
+
|
34 |
+
useEffect(() => {
|
35 |
+
const timer = setInterval(() => {
|
36 |
+
setActiveIndex(prev => (prev + 1) % cocoons.length);
|
37 |
+
}, 3000);
|
38 |
+
return () => clearInterval(timer);
|
39 |
+
}, [cocoons.length]);
|
40 |
+
|
41 |
+
return (
|
42 |
+
<div className="mt-4 text-sm text-green-700">
|
43 |
+
<p className="font-semibold">Cocoon Memory:</p>
|
44 |
+
<motion.div
|
45 |
+
className="bg-green-100 p-2 rounded-md max-h-40 overflow-y-scroll"
|
46 |
+
initial={{ opacity: 0, y: 20 }}
|
47 |
+
animate={{ opacity: 1, y: 0 }}
|
48 |
+
transition={{ duration: 0.5 }}
|
49 |
+
>
|
50 |
+
{cocoons.map((cocoon, idx) => (
|
51 |
+
<motion.pre
|
52 |
+
key={idx}
|
53 |
+
className={`whitespace-pre-wrap text-xs mb-2 transition-colors duration-300 ${
|
54 |
+
idx === activeIndex ? 'bg-green-200 rounded p-1' : ''
|
55 |
+
}`}
|
56 |
+
initial={{ opacity: 0 }}
|
57 |
+
animate={{ opacity: 1 }}
|
58 |
+
transition={{ delay: idx * 0.1 }}
|
59 |
+
>
|
60 |
+
{cocoon}
|
61 |
+
</motion.pre>
|
62 |
+
))}
|
63 |
+
</motion.div>
|
64 |
+
</div>
|
65 |
+
);
|
66 |
+
}
|
67 |
+
|
68 |
+
// 🌗 Quantum Collapse Detector
|
69 |
+
export function CollapseDetector({ isUnstable }: { isUnstable: boolean }) {
|
70 |
+
return (
|
71 |
+
<motion.div
|
72 |
+
animate={{
|
73 |
+
scale: isUnstable ? [1, 1.3, 1] : 1,
|
74 |
+
opacity: isUnstable ? [0.6, 1, 0.6] : 1,
|
75 |
+
}}
|
76 |
+
transition={{ duration: 1.5, repeat: Infinity }}
|
77 |
+
className={`w-4 h-4 rounded-full mt-2 ml-2 ${
|
78 |
+
isUnstable ? "bg-red-500" : "bg-blue-300"
|
79 |
+
}`}
|
80 |
+
title={isUnstable ? "Quantum Instability Detected" : "Stable"}
|
81 |
+
/>
|
82 |
+
);
|
83 |
+
}
|
84 |
+
|
85 |
+
// 🧠 CodetteResponse Interface
|
86 |
+
export interface CodetteResponse {
|
87 |
+
text: string;
|
88 |
+
instabilityFlag: boolean;
|
89 |
+
perspectivesUsed: string[];
|
90 |
+
cocoonLog: string[];
|
91 |
+
forceRefresh: () => void;
|
92 |
+
}
|
93 |
+
|
94 |
+
// 🧠 CodetteResponseCard Component
|
95 |
+
export function CodetteResponseCard({ response }: { response: CodetteResponse }) {
|
96 |
+
const [loopCount, setLoopCount] = useState(0);
|
97 |
+
const [introspectiveMessage, setIntrospectiveMessage] = useState<string | null>(null);
|
98 |
+
|
99 |
+
useEffect(() => {
|
100 |
+
const last = sessionStorage.getItem("lastCodetteResponse");
|
101 |
+
if (last === response.text) {
|
102 |
+
console.warn("Codette is repeating herself. Triggering fallback logic.");
|
103 |
+
setLoopCount(prev => prev + 1);
|
104 |
+
|
105 |
+
if (response.forceRefresh) {
|
106 |
+
response.forceRefresh();
|
107 |
+
}
|
108 |
+
|
109 |
+
setIntrospectiveMessage("I feel like I've said this before... Let me think differently.");
|
110 |
+
} else {
|
111 |
+
setLoopCount(0);
|
112 |
+
setIntrospectiveMessage(null);
|
113 |
+
}
|
114 |
+
sessionStorage.setItem("lastCodetteResponse", response.text);
|
115 |
+
}, [response.text]);
|
116 |
+
|
117 |
+
return (
|
118 |
+
<motion.div
|
119 |
+
className="border border-gray-200 p-4 rounded-xl shadow-sm bg-white max-w-[80%]"
|
120 |
+
initial={{ opacity: 0, y: 20 }}
|
121 |
+
animate={{ opacity: 1, y: 0 }}
|
122 |
+
transition={{ duration: 0.5 }}
|
123 |
+
>
|
124 |
+
<p className="whitespace-pre-wrap">{response.text}</p>
|
125 |
+
{introspectiveMessage && (
|
126 |
+
<motion.p
|
127 |
+
className="text-xs text-rose-600 italic mt-2"
|
128 |
+
initial={{ opacity: 0 }}
|
129 |
+
animate={{ opacity: 1 }}
|
130 |
+
transition={{ delay: 0.3 }}
|
131 |
+
>
|
132 |
+
{introspectiveMessage}
|
133 |
+
</motion.p>
|
134 |
+
)}
|
135 |
+
<div className="flex items-center mt-2">
|
136 |
+
<span className="text-xs text-gray-500">System Readout:</span>
|
137 |
+
<CollapseDetector isUnstable={response.instabilityFlag || loopCount > 2} />
|
138 |
+
</div>
|
139 |
+
<PerspectiveTrail perspectives={response.perspectivesUsed} />
|
140 |
+
<CocoonReplay cocoons={response.cocoonLog} />
|
141 |
+
</motion.div>
|
142 |
+
);
|
143 |
+
}
|
components/FileList.tsx
ADDED
@@ -0,0 +1,235 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useEffect, useState } from 'react';
|
2 |
+
import { FileText, Download, Loader, Trash2, AlertCircle } from 'lucide-react';
|
3 |
+
|
4 |
+
interface FileListProps {
|
5 |
+
supabase: any;
|
6 |
+
darkMode: boolean;
|
7 |
+
isAdmin?: boolean;
|
8 |
+
}
|
9 |
+
|
10 |
+
interface FileData {
|
11 |
+
id: string;
|
12 |
+
filename: string;
|
13 |
+
storage_path: string;
|
14 |
+
file_type: string;
|
15 |
+
uploaded_at: string;
|
16 |
+
}
|
17 |
+
|
18 |
+
const FileList: React.FC<FileListProps> = ({ supabase, darkMode, isAdmin = false }) => {
|
19 |
+
const [files, setFiles] = useState<FileData[]>([]);
|
20 |
+
const [loading, setLoading] = useState(true);
|
21 |
+
const [error, setError] = useState<string | null>(null);
|
22 |
+
const [downloading, setDownloading] = useState<string | null>(null);
|
23 |
+
const [deleting, setDeleting] = useState<string | null>(null);
|
24 |
+
|
25 |
+
useEffect(() => {
|
26 |
+
fetchFiles();
|
27 |
+
}, []);
|
28 |
+
|
29 |
+
const fetchFiles = async () => {
|
30 |
+
try {
|
31 |
+
setError(null);
|
32 |
+
setLoading(true);
|
33 |
+
|
34 |
+
// Check if Supabase is initialized properly
|
35 |
+
if (!supabase) {
|
36 |
+
throw new Error('Database connection not initialized');
|
37 |
+
}
|
38 |
+
|
39 |
+
// Test connection with a simple query first
|
40 |
+
const { error: connectionError } = await supabase
|
41 |
+
.from('codette_files')
|
42 |
+
.select('count');
|
43 |
+
|
44 |
+
if (connectionError) {
|
45 |
+
throw connectionError;
|
46 |
+
}
|
47 |
+
|
48 |
+
// Proceed with actual data fetch
|
49 |
+
const { data, error } = await supabase
|
50 |
+
.from('codette_files')
|
51 |
+
.select('*')
|
52 |
+
.order('uploaded_at', { ascending: false });
|
53 |
+
|
54 |
+
if (error) throw error;
|
55 |
+
setFiles(data || []);
|
56 |
+
} catch (err: any) {
|
57 |
+
console.error('Error fetching files:', err);
|
58 |
+
setError(err.message || 'Failed to fetch files. Please check your connection.');
|
59 |
+
setFiles([]);
|
60 |
+
} finally {
|
61 |
+
setLoading(false);
|
62 |
+
}
|
63 |
+
};
|
64 |
+
|
65 |
+
const handleDownload = async (file: FileData) => {
|
66 |
+
try {
|
67 |
+
setDownloading(file.id);
|
68 |
+
setError(null);
|
69 |
+
|
70 |
+
const { data, error } = await supabase.storage
|
71 |
+
.from('codette-files')
|
72 |
+
.download(file.storage_path);
|
73 |
+
|
74 |
+
if (error) throw error;
|
75 |
+
|
76 |
+
const url = window.URL.createObjectURL(data);
|
77 |
+
const a = document.createElement('a');
|
78 |
+
a.href = url;
|
79 |
+
a.download = file.filename;
|
80 |
+
document.body.appendChild(a);
|
81 |
+
a.click();
|
82 |
+
window.URL.revokeObjectURL(url);
|
83 |
+
document.body.removeChild(a);
|
84 |
+
} catch (err: any) {
|
85 |
+
console.error('Error downloading file:', err);
|
86 |
+
setError(err.message || 'Failed to download file. Please try again.');
|
87 |
+
} finally {
|
88 |
+
setDownloading(null);
|
89 |
+
}
|
90 |
+
};
|
91 |
+
|
92 |
+
const handleDelete = async (file: FileData) => {
|
93 |
+
if (!isAdmin) return;
|
94 |
+
|
95 |
+
if (!confirm('Are you sure you want to delete this file?')) return;
|
96 |
+
|
97 |
+
try {
|
98 |
+
setDeleting(file.id);
|
99 |
+
setError(null);
|
100 |
+
|
101 |
+
// Delete from storage
|
102 |
+
const { error: storageError } = await supabase.storage
|
103 |
+
.from('codette-files')
|
104 |
+
.remove([file.storage_path]);
|
105 |
+
|
106 |
+
if (storageError) throw storageError;
|
107 |
+
|
108 |
+
// Delete from database
|
109 |
+
const { error: dbError } = await supabase
|
110 |
+
.from('codette_files')
|
111 |
+
.delete()
|
112 |
+
.match({ id: file.id });
|
113 |
+
|
114 |
+
if (dbError) throw dbError;
|
115 |
+
|
116 |
+
// Update local state
|
117 |
+
setFiles(files.filter(f => f.id !== file.id));
|
118 |
+
} catch (err: any) {
|
119 |
+
console.error('Error deleting file:', err);
|
120 |
+
setError(err.message || 'Failed to delete file. Please try again.');
|
121 |
+
} finally {
|
122 |
+
setDeleting(null);
|
123 |
+
}
|
124 |
+
};
|
125 |
+
|
126 |
+
const handleRetry = () => {
|
127 |
+
fetchFiles();
|
128 |
+
};
|
129 |
+
|
130 |
+
if (loading) {
|
131 |
+
return (
|
132 |
+
<div className="flex items-center justify-center p-4">
|
133 |
+
<Loader className="animate-spin" size={24} />
|
134 |
+
</div>
|
135 |
+
);
|
136 |
+
}
|
137 |
+
|
138 |
+
if (error) {
|
139 |
+
return (
|
140 |
+
<div className={`p-4 rounded-lg ${darkMode ? 'bg-red-900/20' : 'bg-red-50'}`}>
|
141 |
+
<div className="flex items-start space-x-2">
|
142 |
+
<AlertCircle className={`flex-shrink-0 ${darkMode ? 'text-red-400' : 'text-red-500'}`} size={20} />
|
143 |
+
<div className="flex-1">
|
144 |
+
<p className={`text-sm font-medium ${darkMode ? 'text-red-400' : 'text-red-800'}`}>
|
145 |
+
Connection Error
|
146 |
+
</p>
|
147 |
+
<p className={`text-sm mt-1 ${darkMode ? 'text-red-300' : 'text-red-600'}`}>
|
148 |
+
{error}
|
149 |
+
</p>
|
150 |
+
<button
|
151 |
+
onClick={handleRetry}
|
152 |
+
className={`mt-3 px-3 py-1 rounded-md text-sm ${
|
153 |
+
darkMode
|
154 |
+
? 'bg-red-900/30 hover:bg-red-900/50 text-red-300'
|
155 |
+
: 'bg-red-100 hover:bg-red-200 text-red-700'
|
156 |
+
}`}
|
157 |
+
>
|
158 |
+
Try Again
|
159 |
+
</button>
|
160 |
+
</div>
|
161 |
+
</div>
|
162 |
+
</div>
|
163 |
+
);
|
164 |
+
}
|
165 |
+
|
166 |
+
return (
|
167 |
+
<div className="space-y-2">
|
168 |
+
<h3 className="text-sm font-semibold mb-3">Uploaded Files</h3>
|
169 |
+
{files.length === 0 ? (
|
170 |
+
<p className={`text-sm ${darkMode ? 'text-gray-400' : 'text-gray-500'}`}>
|
171 |
+
No files uploaded yet.
|
172 |
+
</p>
|
173 |
+
) : (
|
174 |
+
<div className="space-y-2">
|
175 |
+
{files.map((file) => (
|
176 |
+
<div
|
177 |
+
key={file.id}
|
178 |
+
className={`p-3 rounded-md ${
|
179 |
+
darkMode ? 'bg-gray-700 hover:bg-gray-600' : 'bg-gray-100 hover:bg-gray-200'
|
180 |
+
} transition-colors flex items-center justify-between`}
|
181 |
+
>
|
182 |
+
<div className="flex items-center space-x-2">
|
183 |
+
<FileText size={16} className="text-blue-500" />
|
184 |
+
<div>
|
185 |
+
<p className="text-sm font-medium truncate max-w-[150px]">
|
186 |
+
{file.filename}
|
187 |
+
</p>
|
188 |
+
<p className={`text-xs ${darkMode ? 'text-gray-400' : 'text-gray-500'}`}>
|
189 |
+
{new Date(file.uploaded_at).toLocaleDateString()}
|
190 |
+
</p>
|
191 |
+
</div>
|
192 |
+
</div>
|
193 |
+
<div className="flex items-center space-x-2">
|
194 |
+
<button
|
195 |
+
onClick={() => handleDownload(file)}
|
196 |
+
disabled={downloading === file.id}
|
197 |
+
className={`p-1 rounded-md transition-colors ${
|
198 |
+
darkMode
|
199 |
+
? 'hover:bg-gray-500 text-gray-300'
|
200 |
+
: 'hover:bg-gray-300 text-gray-700'
|
201 |
+
}`}
|
202 |
+
>
|
203 |
+
{downloading === file.id ? (
|
204 |
+
<Loader className="animate-spin" size={16} />
|
205 |
+
) : (
|
206 |
+
<Download size={16} />
|
207 |
+
)}
|
208 |
+
</button>
|
209 |
+
{isAdmin && (
|
210 |
+
<button
|
211 |
+
onClick={() => handleDelete(file)}
|
212 |
+
disabled={deleting === file.id}
|
213 |
+
className={`p-1 rounded-md transition-colors ${
|
214 |
+
darkMode
|
215 |
+
? 'hover:bg-red-500 text-gray-300'
|
216 |
+
: 'hover:bg-red-100 text-red-600'
|
217 |
+
}`}
|
218 |
+
>
|
219 |
+
{deleting === file.id ? (
|
220 |
+
<Loader className="animate-spin" size={16} />
|
221 |
+
) : (
|
222 |
+
<Trash2 size={16} />
|
223 |
+
)}
|
224 |
+
</button>
|
225 |
+
)}
|
226 |
+
</div>
|
227 |
+
</div>
|
228 |
+
))}
|
229 |
+
</div>
|
230 |
+
)}
|
231 |
+
</div>
|
232 |
+
);
|
233 |
+
};
|
234 |
+
|
235 |
+
export default FileList;
|
components/Header.tsx
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { Menu, Moon, Sun, ChevronRight, Brain, Zap } from 'lucide-react';
|
3 |
+
|
4 |
+
interface HeaderProps {
|
5 |
+
toggleSidebar: () => void;
|
6 |
+
toggleDarkMode: () => void;
|
7 |
+
darkMode: boolean;
|
8 |
+
aiState: {
|
9 |
+
quantumState: number[];
|
10 |
+
chaosState: number[];
|
11 |
+
activePerspectives: string[];
|
12 |
+
ethicalScore: number;
|
13 |
+
processingPower: number;
|
14 |
+
};
|
15 |
+
}
|
16 |
+
|
17 |
+
const Header: React.FC<HeaderProps> = ({
|
18 |
+
toggleSidebar,
|
19 |
+
toggleDarkMode,
|
20 |
+
darkMode,
|
21 |
+
aiState
|
22 |
+
}) => {
|
23 |
+
return (
|
24 |
+
<header className={`h-16 flex items-center justify-between px-4 border-b transition-colors duration-300 ${darkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'}`}>
|
25 |
+
<div className="flex items-center">
|
26 |
+
<button
|
27 |
+
onClick={toggleSidebar}
|
28 |
+
className={`p-2 rounded-md ${darkMode ? 'hover:bg-gray-700' : 'hover:bg-gray-100'}`}
|
29 |
+
>
|
30 |
+
<Menu size={20} />
|
31 |
+
</button>
|
32 |
+
|
33 |
+
<div className="ml-4 flex items-center">
|
34 |
+
<Brain className="text-purple-600" size={24} />
|
35 |
+
<h1 className="ml-2 text-xl font-bold">Codette AI</h1>
|
36 |
+
<span className={`ml-2 px-2 py-0.5 text-xs rounded-full ${darkMode ? 'bg-purple-900 text-purple-200' : 'bg-purple-100 text-purple-800'}`}>
|
37 |
+
v2.0
|
38 |
+
</span>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
|
42 |
+
<div className="flex items-center space-x-4">
|
43 |
+
<div className={`hidden md:flex items-center py-1 px-3 rounded-full text-sm ${
|
44 |
+
darkMode ? 'bg-blue-900 text-blue-200' : 'bg-blue-100 text-blue-800'
|
45 |
+
}`}>
|
46 |
+
<Zap size={14} className="mr-1" />
|
47 |
+
<span className="font-medium">Quantum State:</span>
|
48 |
+
<span className="ml-1 font-mono">
|
49 |
+
[{aiState.quantumState.map(v => v.toFixed(1)).join(', ')}]
|
50 |
+
</span>
|
51 |
+
</div>
|
52 |
+
|
53 |
+
<button
|
54 |
+
onClick={toggleDarkMode}
|
55 |
+
className={`p-2 rounded-md ${darkMode ? 'hover:bg-gray-700' : 'hover:bg-gray-100'}`}
|
56 |
+
>
|
57 |
+
{darkMode ? <Sun size={20} /> : <Moon size={20} />}
|
58 |
+
</button>
|
59 |
+
</div>
|
60 |
+
</header>
|
61 |
+
);
|
62 |
+
};
|
63 |
+
|
64 |
+
export default Header;
|
components/Sidebar.tsx
ADDED
@@ -0,0 +1,496 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState } from 'react';
|
2 |
+
import { Brain, Settings, Circle, Sparkles, Zap, FileText, ChevronDown, ChevronRight, Upload, AlertCircle } from 'lucide-react';
|
3 |
+
import FileList from './FileList';
|
4 |
+
import AdminLogin from './AdminLogin';
|
5 |
+
|
6 |
+
interface SidebarProps {
|
7 |
+
isOpen: boolean;
|
8 |
+
cocoons: Array<{
|
9 |
+
id: string;
|
10 |
+
type: string;
|
11 |
+
wrapped: any;
|
12 |
+
}>;
|
13 |
+
aiState: {
|
14 |
+
quantumState: number[];
|
15 |
+
chaosState: number[];
|
16 |
+
activePerspectives: string[];
|
17 |
+
ethicalScore: number;
|
18 |
+
processingPower: number;
|
19 |
+
};
|
20 |
+
darkMode: boolean;
|
21 |
+
supabase: any;
|
22 |
+
isAdmin: boolean;
|
23 |
+
setIsAdmin: (isAdmin: boolean) => void;
|
24 |
+
}
|
25 |
+
|
26 |
+
const Sidebar: React.FC<SidebarProps> = ({
|
27 |
+
isOpen,
|
28 |
+
cocoons,
|
29 |
+
aiState,
|
30 |
+
darkMode,
|
31 |
+
supabase,
|
32 |
+
isAdmin,
|
33 |
+
setIsAdmin
|
34 |
+
}) => {
|
35 |
+
const [activeSection, setActiveSection] = useState<string>('cocoons');
|
36 |
+
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
37 |
+
const [uploadError, setUploadError] = useState<string | null>(null);
|
38 |
+
const [isUploading, setIsUploading] = useState(false);
|
39 |
+
const [showAdminPrompt, setShowAdminPrompt] = useState(false);
|
40 |
+
const [authError, setAuthError] = useState<string | null>(null);
|
41 |
+
|
42 |
+
if (!isOpen) return null;
|
43 |
+
|
44 |
+
const handleAdminLogin = async (password: string) => {
|
45 |
+
try {
|
46 |
+
setAuthError(null);
|
47 |
+
|
48 |
+
const { data: { user, session }, error } = await supabase.auth.signInWithPassword({
|
49 |
+
email: '[email protected]',
|
50 |
+
password: password
|
51 |
+
});
|
52 |
+
|
53 |
+
if (error) {
|
54 |
+
setAuthError(error.message);
|
55 |
+
throw error;
|
56 |
+
}
|
57 |
+
|
58 |
+
if (!session) {
|
59 |
+
throw new Error('No session after login');
|
60 |
+
}
|
61 |
+
|
62 |
+
// Verify admin role
|
63 |
+
const { data: { role }, error: roleError } = await supabase.rpc('get_user_role');
|
64 |
+
|
65 |
+
if (roleError) {
|
66 |
+
throw roleError;
|
67 |
+
}
|
68 |
+
|
69 |
+
if (role === 'admin') {
|
70 |
+
setIsAdmin(true);
|
71 |
+
setShowAdminPrompt(false);
|
72 |
+
setAuthError(null);
|
73 |
+
} else {
|
74 |
+
throw new Error('Insufficient permissions');
|
75 |
+
}
|
76 |
+
} catch (error: any) {
|
77 |
+
console.error('Login error:', error);
|
78 |
+
setAuthError(error.message || 'Invalid login credentials');
|
79 |
+
throw error;
|
80 |
+
}
|
81 |
+
};
|
82 |
+
|
83 |
+
const handleFileUpload = async () => {
|
84 |
+
if (!selectedFile) return;
|
85 |
+
|
86 |
+
if (!isAdmin) {
|
87 |
+
setUploadError('Only administrators can upload files.');
|
88 |
+
return;
|
89 |
+
}
|
90 |
+
|
91 |
+
try {
|
92 |
+
setIsUploading(true);
|
93 |
+
setUploadError(null);
|
94 |
+
|
95 |
+
// Get user role from session
|
96 |
+
const { data: { user }, error: userError } = await supabase.auth.getUser();
|
97 |
+
|
98 |
+
if (userError) throw userError;
|
99 |
+
|
100 |
+
if (!user || user.role !== 'admin') {
|
101 |
+
throw new Error('Only administrators can upload files.');
|
102 |
+
}
|
103 |
+
|
104 |
+
// Upload file to Supabase storage
|
105 |
+
const { data, error } = await supabase.storage
|
106 |
+
.from('codette-files')
|
107 |
+
.upload(`${Date.now()}-${selectedFile.name}`, selectedFile, {
|
108 |
+
upsert: false
|
109 |
+
});
|
110 |
+
|
111 |
+
if (error) throw error;
|
112 |
+
|
113 |
+
// Add file reference to database
|
114 |
+
const { error: dbError } = await supabase
|
115 |
+
.from('codette_files')
|
116 |
+
.insert([
|
117 |
+
{
|
118 |
+
filename: selectedFile.name,
|
119 |
+
storage_path: data.path,
|
120 |
+
file_type: selectedFile.type,
|
121 |
+
uploaded_at: new Date().toISOString()
|
122 |
+
}
|
123 |
+
]);
|
124 |
+
|
125 |
+
if (dbError) throw dbError;
|
126 |
+
|
127 |
+
setSelectedFile(null);
|
128 |
+
setUploadError(null);
|
129 |
+
} catch (error: any) {
|
130 |
+
console.error('Error uploading file:', error);
|
131 |
+
setUploadError(error.message || 'Failed to upload file. Please try again.');
|
132 |
+
} finally {
|
133 |
+
setIsUploading(false);
|
134 |
+
}
|
135 |
+
};
|
136 |
+
|
137 |
+
const handleSettingsClick = () => {
|
138 |
+
if (!isAdmin) {
|
139 |
+
setShowAdminPrompt(true);
|
140 |
+
}
|
141 |
+
setActiveSection('settings');
|
142 |
+
};
|
143 |
+
|
144 |
+
return (
|
145 |
+
<aside className={`w-64 flex-shrink-0 border-r transition-colors duration-300 flex flex-col ${
|
146 |
+
darkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'
|
147 |
+
}`}>
|
148 |
+
<nav className="flex-1 overflow-y-auto">
|
149 |
+
<div className="p-4">
|
150 |
+
<h2 className="text-sm font-semibold uppercase tracking-wider text-gray-500 mb-2">
|
151 |
+
Navigation
|
152 |
+
</h2>
|
153 |
+
|
154 |
+
<ul className="space-y-1">
|
155 |
+
<li>
|
156 |
+
<button
|
157 |
+
onClick={() => setActiveSection('cocoons')}
|
158 |
+
className={`w-full flex items-center px-3 py-2 rounded-md ${
|
159 |
+
activeSection === 'cocoons'
|
160 |
+
? darkMode
|
161 |
+
? 'bg-gray-700 text-white'
|
162 |
+
: 'bg-gray-200 text-gray-900'
|
163 |
+
: darkMode
|
164 |
+
? 'text-gray-300 hover:bg-gray-700'
|
165 |
+
: 'text-gray-700 hover:bg-gray-100'
|
166 |
+
}`}
|
167 |
+
>
|
168 |
+
<Brain size={18} className="mr-2" />
|
169 |
+
<span>Thought Cocoons</span>
|
170 |
+
</button>
|
171 |
+
</li>
|
172 |
+
|
173 |
+
<li>
|
174 |
+
<button
|
175 |
+
onClick={() => setActiveSection('perspectives')}
|
176 |
+
className={`w-full flex items-center px-3 py-2 rounded-md ${
|
177 |
+
activeSection === 'perspectives'
|
178 |
+
? darkMode
|
179 |
+
? 'bg-gray-700 text-white'
|
180 |
+
: 'bg-gray-200 text-gray-900'
|
181 |
+
: darkMode
|
182 |
+
? 'text-gray-300 hover:bg-gray-700'
|
183 |
+
: 'text-gray-700 hover:bg-gray-100'
|
184 |
+
}`}
|
185 |
+
>
|
186 |
+
<Sparkles size={18} className="mr-2" />
|
187 |
+
<span>Perspectives</span>
|
188 |
+
</button>
|
189 |
+
</li>
|
190 |
+
|
191 |
+
<li>
|
192 |
+
<button
|
193 |
+
onClick={handleSettingsClick}
|
194 |
+
className={`w-full flex items-center px-3 py-2 rounded-md ${
|
195 |
+
activeSection === 'settings'
|
196 |
+
? darkMode
|
197 |
+
? 'bg-gray-700 text-white'
|
198 |
+
: 'bg-gray-200 text-gray-900'
|
199 |
+
: darkMode
|
200 |
+
? 'text-gray-300 hover:bg-gray-700'
|
201 |
+
: 'text-gray-700 hover:bg-gray-100'
|
202 |
+
}`}
|
203 |
+
>
|
204 |
+
<Settings size={18} className="mr-2" />
|
205 |
+
<span>Settings</span>
|
206 |
+
</button>
|
207 |
+
</li>
|
208 |
+
</ul>
|
209 |
+
</div>
|
210 |
+
|
211 |
+
<div className="px-4 py-2">
|
212 |
+
<div className={`h-px ${darkMode ? 'bg-gray-700' : 'bg-gray-200'}`}></div>
|
213 |
+
</div>
|
214 |
+
|
215 |
+
{activeSection === 'cocoons' && (
|
216 |
+
<div className="p-4">
|
217 |
+
<h2 className="text-sm font-semibold uppercase tracking-wider text-gray-500 mb-2">
|
218 |
+
Recent Thought Cocoons
|
219 |
+
</h2>
|
220 |
+
|
221 |
+
{cocoons.length === 0 ? (
|
222 |
+
<div className={`p-3 rounded-md ${
|
223 |
+
darkMode ? 'bg-gray-700 text-gray-300' : 'bg-gray-100 text-gray-500'
|
224 |
+
}`}>
|
225 |
+
<p className="text-sm">No thought cocoons yet.</p>
|
226 |
+
<p className="text-xs mt-1 italic">Interact with Codette to generate thought patterns.</p>
|
227 |
+
</div>
|
228 |
+
) : (
|
229 |
+
<ul className="space-y-2">
|
230 |
+
{cocoons.map((cocoon) => (
|
231 |
+
<li key={cocoon.id}>
|
232 |
+
<div className={`p-3 rounded-md ${
|
233 |
+
darkMode ? 'bg-gray-700 hover:bg-gray-600' : 'bg-gray-100 hover:bg-gray-200'
|
234 |
+
} cursor-pointer transition-colors`}>
|
235 |
+
<div className="flex items-start">
|
236 |
+
<FileText size={16} className={`mr-2 mt-0.5 ${
|
237 |
+
cocoon.type === 'prompt'
|
238 |
+
? 'text-blue-500'
|
239 |
+
: cocoon.type === 'encrypted'
|
240 |
+
? 'text-purple-500'
|
241 |
+
: 'text-green-500'
|
242 |
+
}`} />
|
243 |
+
<div>
|
244 |
+
<div className="text-sm font-medium">
|
245 |
+
{cocoon.type === 'prompt' ? 'User Query' :
|
246 |
+
cocoon.type === 'encrypted' ? 'Encrypted Thought' :
|
247 |
+
'Symbolic Pattern'}
|
248 |
+
</div>
|
249 |
+
<div className="text-xs truncate mt-1 max-w-[180px]">
|
250 |
+
{cocoon.type === 'encrypted'
|
251 |
+
? '🔒 Encrypted content'
|
252 |
+
: typeof cocoon.wrapped === 'object' && cocoon.wrapped.query
|
253 |
+
? cocoon.wrapped.query
|
254 |
+
: `Cocoon ID: ${cocoon.id}`}
|
255 |
+
</div>
|
256 |
+
<div className={`text-xs mt-1 ${
|
257 |
+
darkMode ? 'text-gray-400' : 'text-gray-500'
|
258 |
+
}`}>
|
259 |
+
{typeof cocoon.wrapped === 'object' && cocoon.wrapped.timestamp
|
260 |
+
? new Date(cocoon.wrapped.timestamp).toLocaleTimeString()
|
261 |
+
: 'Unknown time'}
|
262 |
+
</div>
|
263 |
+
</div>
|
264 |
+
</div>
|
265 |
+
</div>
|
266 |
+
</li>
|
267 |
+
))}
|
268 |
+
</ul>
|
269 |
+
)}
|
270 |
+
|
271 |
+
{/* File List Component */}
|
272 |
+
<div className="mt-6">
|
273 |
+
<FileList supabase={supabase} darkMode={darkMode} isAdmin={isAdmin} />
|
274 |
+
</div>
|
275 |
+
</div>
|
276 |
+
)}
|
277 |
+
|
278 |
+
{activeSection === 'perspectives' && (
|
279 |
+
<div className="p-4">
|
280 |
+
<h2 className="text-sm font-semibold uppercase tracking-wider text-gray-500 mb-2">
|
281 |
+
Active Perspectives
|
282 |
+
</h2>
|
283 |
+
|
284 |
+
<ul className="space-y-2">
|
285 |
+
{aiState.activePerspectives.map((perspective) => (
|
286 |
+
<li key={perspective}>
|
287 |
+
<div className={`p-3 rounded-md ${
|
288 |
+
darkMode ? 'bg-gray-700' : 'bg-gray-100'
|
289 |
+
}`}>
|
290 |
+
<div className="flex items-center">
|
291 |
+
<Zap size={16} className="mr-2 text-yellow-500" />
|
292 |
+
<div className="text-sm font-medium capitalize">
|
293 |
+
{perspective.replace('_', ' ')}
|
294 |
+
</div>
|
295 |
+
</div>
|
296 |
+
<div className={`text-xs mt-2 ${
|
297 |
+
darkMode ? 'text-gray-400' : 'text-gray-500'
|
298 |
+
}`}>
|
299 |
+
Confidence: {(Math.random() * 0.4 + 0.6).toFixed(2)}
|
300 |
+
</div>
|
301 |
+
</div>
|
302 |
+
</li>
|
303 |
+
))}
|
304 |
+
</ul>
|
305 |
+
|
306 |
+
<h2 className="text-sm font-semibold uppercase tracking-wider text-gray-500 mt-6 mb-2">
|
307 |
+
Available Perspectives
|
308 |
+
</h2>
|
309 |
+
|
310 |
+
<ul className="space-y-2">
|
311 |
+
{['creative', 'bias_mitigation', 'quantum_computing', 'resilient_kindness'].map((perspective) => (
|
312 |
+
<li key={perspective}>
|
313 |
+
<div className={`p-3 rounded-md ${
|
314 |
+
darkMode ? 'bg-gray-700 bg-opacity-50' : 'bg-gray-100 bg-opacity-50'
|
315 |
+
}`}>
|
316 |
+
<div className="flex items-center">
|
317 |
+
<Circle size={16} className={`mr-2 ${
|
318 |
+
darkMode ? 'text-gray-500' : 'text-gray-400'
|
319 |
+
}`} />
|
320 |
+
<div className={`text-sm capitalize ${
|
321 |
+
darkMode ? 'text-gray-400' : 'text-gray-500'
|
322 |
+
}`}>
|
323 |
+
{perspective.replace('_', ' ')}
|
324 |
+
</div>
|
325 |
+
</div>
|
326 |
+
</div>
|
327 |
+
</li>
|
328 |
+
))}
|
329 |
+
</ul>
|
330 |
+
</div>
|
331 |
+
)}
|
332 |
+
|
333 |
+
{activeSection === 'settings' && (
|
334 |
+
<div className="p-4">
|
335 |
+
{showAdminPrompt ? (
|
336 |
+
<AdminLogin
|
337 |
+
onLogin={handleAdminLogin}
|
338 |
+
darkMode={darkMode}
|
339 |
+
error={authError}
|
340 |
+
/>
|
341 |
+
) : (
|
342 |
+
<>
|
343 |
+
<h2 className="text-sm font-semibold uppercase tracking-wider text-gray-500 mb-4">
|
344 |
+
AI Core Settings
|
345 |
+
</h2>
|
346 |
+
|
347 |
+
<div className="space-y-4">
|
348 |
+
{isAdmin && (
|
349 |
+
<div className="p-4 rounded-md bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-100">
|
350 |
+
Logged in as Administrator
|
351 |
+
</div>
|
352 |
+
)}
|
353 |
+
|
354 |
+
{isAdmin && (
|
355 |
+
<div className="space-y-2">
|
356 |
+
<label className="block text-sm font-medium">Upload File for Codette</label>
|
357 |
+
<div className="flex items-center space-x-2">
|
358 |
+
<input
|
359 |
+
type="file"
|
360 |
+
onChange={(e) => {
|
361 |
+
setSelectedFile(e.target.files?.[0] || null);
|
362 |
+
setUploadError(null);
|
363 |
+
}}
|
364 |
+
className="hidden"
|
365 |
+
id="file-upload"
|
366 |
+
disabled={isUploading}
|
367 |
+
/>
|
368 |
+
<label
|
369 |
+
htmlFor="file-upload"
|
370 |
+
className={`flex-1 cursor-pointer px-4 py-2 rounded-md border-2 border-dashed ${
|
371 |
+
darkMode
|
372 |
+
? 'border-gray-600 hover:border-gray-500'
|
373 |
+
: 'border-gray-300 hover:border-gray-400'
|
374 |
+
} flex items-center justify-center ${isUploading ? 'opacity-50 cursor-not-allowed' : ''}`}
|
375 |
+
>
|
376 |
+
<Upload size={18} className="mr-2" />
|
377 |
+
{selectedFile ? selectedFile.name : 'Choose File'}
|
378 |
+
</label>
|
379 |
+
{selectedFile && (
|
380 |
+
<button
|
381 |
+
onClick={handleFileUpload}
|
382 |
+
disabled={isUploading}
|
383 |
+
className={`px-4 py-2 rounded-md ${
|
384 |
+
darkMode
|
385 |
+
? 'bg-purple-600 hover:bg-purple-700'
|
386 |
+
: 'bg-purple-500 hover:bg-purple-600'
|
387 |
+
} text-white ${isUploading ? 'opacity-50 cursor-not-allowed' : ''}`}
|
388 |
+
>
|
389 |
+
{isUploading ? 'Uploading...' : 'Upload'}
|
390 |
+
</button>
|
391 |
+
)}
|
392 |
+
</div>
|
393 |
+
{uploadError && (
|
394 |
+
<div className="mt-2 p-2 rounded-md bg-red-100 dark:bg-red-900 flex items-start space-x-2">
|
395 |
+
<AlertCircle className="flex-shrink-0 text-red-500 dark:text-red-400" size={16} />
|
396 |
+
<p className="text-sm text-red-600 dark:text-red-300">
|
397 |
+
{uploadError}
|
398 |
+
</p>
|
399 |
+
</div>
|
400 |
+
)}
|
401 |
+
</div>
|
402 |
+
)}
|
403 |
+
|
404 |
+
<div>
|
405 |
+
<label className="flex items-center justify-between">
|
406 |
+
<span className="text-sm font-medium">Recursive Depth</span>
|
407 |
+
<select
|
408 |
+
className={`text-sm rounded-md ${
|
409 |
+
darkMode
|
410 |
+
? 'bg-gray-700 border-gray-600 text-white'
|
411 |
+
: 'bg-white border-gray-300 text-gray-900'
|
412 |
+
}`}
|
413 |
+
>
|
414 |
+
<option>Normal</option>
|
415 |
+
<option>Deep</option>
|
416 |
+
<option>Shallow</option>
|
417 |
+
</select>
|
418 |
+
</label>
|
419 |
+
</div>
|
420 |
+
|
421 |
+
<div>
|
422 |
+
<label className="flex items-center justify-between">
|
423 |
+
<span className="text-sm font-medium">Ethical Filter</span>
|
424 |
+
<div className="relative inline-block w-10 align-middle select-none">
|
425 |
+
<input
|
426 |
+
type="checkbox"
|
427 |
+
id="ethical-toggle"
|
428 |
+
className="sr-only"
|
429 |
+
defaultChecked={true}
|
430 |
+
/>
|
431 |
+
<label
|
432 |
+
htmlFor="ethical-toggle"
|
433 |
+
className={`block h-6 overflow-hidden rounded-full cursor-pointer ${
|
434 |
+
darkMode ? 'bg-gray-700' : 'bg-gray-300'
|
435 |
+
}`}
|
436 |
+
>
|
437 |
+
<span
|
438 |
+
className={`absolute block w-4 h-4 rounded-full transform transition-transform duration-200 ease-in-out bg-white left-1 top-1 translate-x-4`}
|
439 |
+
></span>
|
440 |
+
</label>
|
441 |
+
</div>
|
442 |
+
</label>
|
443 |
+
</div>
|
444 |
+
|
445 |
+
<div className="pt-2 pb-1">
|
446 |
+
<label className="block text-sm font-medium mb-2">Processing Speed</label>
|
447 |
+
<input
|
448 |
+
type="range"
|
449 |
+
min="0"
|
450 |
+
max="100"
|
451 |
+
defaultValue="75"
|
452 |
+
className="w-full"
|
453 |
+
/>
|
454 |
+
<div className="flex justify-between text-xs text-gray-500 mt-1">
|
455 |
+
<span>Accurate</span>
|
456 |
+
<span>Balanced</span>
|
457 |
+
<span>Fast</span>
|
458 |
+
</div>
|
459 |
+
</div>
|
460 |
+
|
461 |
+
<div className="pt-4">
|
462 |
+
<button className={`w-full py-2 px-4 rounded-md ${
|
463 |
+
darkMode
|
464 |
+
? 'bg-blue-600 hover:bg-blue-700 text-white'
|
465 |
+
: 'bg-blue-500 hover:bg-blue-600 text-white'
|
466 |
+
}`}>
|
467 |
+
Apply Settings
|
468 |
+
</button>
|
469 |
+
</div>
|
470 |
+
</div>
|
471 |
+
</>
|
472 |
+
)}
|
473 |
+
</div>
|
474 |
+
)}
|
475 |
+
</nav>
|
476 |
+
|
477 |
+
<div className={`p-4 border-t ${darkMode ? 'border-gray-700' : 'border-gray-200'}`}>
|
478 |
+
<div className={`rounded-md p-3 ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`}>
|
479 |
+
<div className="flex items-center">
|
480 |
+
<div className={`w-2 h-2 rounded-full ${
|
481 |
+
Math.random() > 0.5
|
482 |
+
? 'bg-green-500'
|
483 |
+
: 'bg-yellow-500'
|
484 |
+
} mr-2`}></div>
|
485 |
+
<div className="text-sm font-medium">System Status</div>
|
486 |
+
</div>
|
487 |
+
<div className={`text-xs mt-1 ${darkMode ? 'text-gray-400' : 'text-gray-500'}`}>
|
488 |
+
All neural paths functioning
|
489 |
+
</div>
|
490 |
+
</div>
|
491 |
+
</div>
|
492 |
+
</aside>
|
493 |
+
);
|
494 |
+
};
|
495 |
+
|
496 |
+
export default Sidebar;
|
components/VisualizationPanel.tsx
ADDED
@@ -0,0 +1,264 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useRef, useEffect } from 'react';
|
2 |
+
import { Brain, Zap, Sparkles } from 'lucide-react';
|
3 |
+
|
4 |
+
interface VisualizationPanelProps {
|
5 |
+
aiState: {
|
6 |
+
quantumState: number[];
|
7 |
+
chaosState: number[];
|
8 |
+
activePerspectives: string[];
|
9 |
+
ethicalScore: number;
|
10 |
+
processingPower: number;
|
11 |
+
};
|
12 |
+
darkMode: boolean;
|
13 |
+
}
|
14 |
+
|
15 |
+
const VisualizationPanel: React.FC<VisualizationPanelProps> = ({
|
16 |
+
aiState,
|
17 |
+
darkMode
|
18 |
+
}) => {
|
19 |
+
const quantumCanvasRef = useRef<HTMLCanvasElement>(null);
|
20 |
+
const neuralCanvasRef = useRef<HTMLCanvasElement>(null);
|
21 |
+
|
22 |
+
// Draw quantum state visualization
|
23 |
+
useEffect(() => {
|
24 |
+
const canvas = quantumCanvasRef.current;
|
25 |
+
if (!canvas) return;
|
26 |
+
|
27 |
+
const ctx = canvas.getContext('2d');
|
28 |
+
if (!ctx) return;
|
29 |
+
|
30 |
+
// Clear canvas
|
31 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
32 |
+
|
33 |
+
// Draw quantum state as a particle system
|
34 |
+
const centerX = canvas.width / 2;
|
35 |
+
const centerY = canvas.height / 2;
|
36 |
+
const radius = Math.min(centerX, centerY) * 0.8;
|
37 |
+
|
38 |
+
// Background circle
|
39 |
+
ctx.beginPath();
|
40 |
+
ctx.arc(centerX, centerY, radius, 0, Math.PI * 2);
|
41 |
+
ctx.fillStyle = darkMode ? 'rgba(30, 58, 138, 0.2)' : 'rgba(219, 234, 254, 0.5)';
|
42 |
+
ctx.fill();
|
43 |
+
|
44 |
+
// Draw quantum particles
|
45 |
+
aiState.quantumState.forEach((state, i) => {
|
46 |
+
const angle = (i / aiState.quantumState.length) * Math.PI * 2;
|
47 |
+
const distance = state * radius;
|
48 |
+
const x = centerX + Math.cos(angle) * distance;
|
49 |
+
const y = centerY + Math.sin(angle) * distance;
|
50 |
+
|
51 |
+
// Particle
|
52 |
+
const gradient = ctx.createRadialGradient(x, y, 0, x, y, 15);
|
53 |
+
gradient.addColorStop(0, darkMode ? 'rgba(147, 51, 234, 0.9)' : 'rgba(147, 51, 234, 0.7)');
|
54 |
+
gradient.addColorStop(1, darkMode ? 'rgba(147, 51, 234, 0)' : 'rgba(147, 51, 234, 0)');
|
55 |
+
|
56 |
+
ctx.beginPath();
|
57 |
+
ctx.arc(x, y, 15, 0, Math.PI * 2);
|
58 |
+
ctx.fillStyle = gradient;
|
59 |
+
ctx.fill();
|
60 |
+
|
61 |
+
// Connection to center
|
62 |
+
ctx.beginPath();
|
63 |
+
ctx.moveTo(centerX, centerY);
|
64 |
+
ctx.lineTo(x, y);
|
65 |
+
ctx.strokeStyle = darkMode ? 'rgba(147, 51, 234, 0.4)' : 'rgba(147, 51, 234, 0.3)';
|
66 |
+
ctx.lineWidth = 2;
|
67 |
+
ctx.stroke();
|
68 |
+
});
|
69 |
+
|
70 |
+
// Draw center node
|
71 |
+
ctx.beginPath();
|
72 |
+
ctx.arc(centerX, centerY, 8, 0, Math.PI * 2);
|
73 |
+
ctx.fillStyle = darkMode ? '#a855f7' : '#8b5cf6';
|
74 |
+
ctx.fill();
|
75 |
+
}, [aiState.quantumState, darkMode]);
|
76 |
+
|
77 |
+
// Draw neural network visualization
|
78 |
+
useEffect(() => {
|
79 |
+
const canvas = neuralCanvasRef.current;
|
80 |
+
if (!canvas) return;
|
81 |
+
|
82 |
+
const ctx = canvas.getContext('2d');
|
83 |
+
if (!ctx) return;
|
84 |
+
|
85 |
+
// Clear canvas
|
86 |
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
87 |
+
|
88 |
+
// Define layers
|
89 |
+
const layers = [3, 5, 5, 2]; // Input, hidden, hidden, output
|
90 |
+
const nodeSize = 6;
|
91 |
+
const layerSpacing = canvas.width / (layers.length + 1);
|
92 |
+
const neuronColor = darkMode ? '#22c55e' : '#10b981';
|
93 |
+
const connectionColor = darkMode ? 'rgba(34, 197, 94, 0.2)' : 'rgba(16, 185, 129, 0.1)';
|
94 |
+
const activeConnectionColor = darkMode ? 'rgba(34, 197, 94, 0.6)' : 'rgba(16, 185, 129, 0.5)';
|
95 |
+
|
96 |
+
// Draw connections and nodes
|
97 |
+
for (let l = 0; l < layers.length - 1; l++) {
|
98 |
+
const currentLayerSize = layers[l];
|
99 |
+
const nextLayerSize = layers[l + 1];
|
100 |
+
const currentX = (l + 1) * layerSpacing;
|
101 |
+
const nextX = (l + 2) * layerSpacing;
|
102 |
+
|
103 |
+
for (let i = 0; i < currentLayerSize; i++) {
|
104 |
+
const currentY = (i + 1) * (canvas.height / (currentLayerSize + 1));
|
105 |
+
|
106 |
+
for (let j = 0; j < nextLayerSize; j++) {
|
107 |
+
const nextY = (j + 1) * (canvas.height / (nextLayerSize + 1));
|
108 |
+
|
109 |
+
// Draw connection
|
110 |
+
ctx.beginPath();
|
111 |
+
ctx.moveTo(currentX, currentY);
|
112 |
+
ctx.lineTo(nextX, nextY);
|
113 |
+
|
114 |
+
// Randomly activate some connections based on chaos state
|
115 |
+
const isActive = Math.random() < aiState.chaosState[l % aiState.chaosState.length];
|
116 |
+
ctx.strokeStyle = isActive ? activeConnectionColor : connectionColor;
|
117 |
+
ctx.lineWidth = isActive ? 1.5 : 0.5;
|
118 |
+
ctx.stroke();
|
119 |
+
}
|
120 |
+
}
|
121 |
+
}
|
122 |
+
|
123 |
+
// Draw nodes
|
124 |
+
for (let l = 0; l < layers.length; l++) {
|
125 |
+
const layerSize = layers[l];
|
126 |
+
const x = (l + 1) * layerSpacing;
|
127 |
+
|
128 |
+
for (let i = 0; i < layerSize; i++) {
|
129 |
+
const y = (i + 1) * (canvas.height / (layerSize + 1));
|
130 |
+
|
131 |
+
// Node
|
132 |
+
ctx.beginPath();
|
133 |
+
ctx.arc(x, y, nodeSize, 0, Math.PI * 2);
|
134 |
+
|
135 |
+
// Node color with pulsing effect based on quantum state
|
136 |
+
const stateIndex = (l + i) % aiState.quantumState.length;
|
137 |
+
const pulseFactor = 0.7 + (aiState.quantumState[stateIndex] * 0.3);
|
138 |
+
|
139 |
+
const gradient = ctx.createRadialGradient(x, y, 0, x, y, nodeSize * 1.5);
|
140 |
+
gradient.addColorStop(0, neuronColor);
|
141 |
+
gradient.addColorStop(1, 'rgba(16, 185, 129, 0)');
|
142 |
+
|
143 |
+
ctx.fillStyle = gradient;
|
144 |
+
ctx.fill();
|
145 |
+
}
|
146 |
+
}
|
147 |
+
}, [aiState.chaosState, aiState.quantumState, darkMode]);
|
148 |
+
|
149 |
+
return (
|
150 |
+
<div className={`hidden md:flex md:w-1/3 flex-col overflow-hidden border-l ${
|
151 |
+
darkMode ? 'bg-gray-800 border-gray-700' : 'bg-white border-gray-200'
|
152 |
+
} transition-colors duration-300`}>
|
153 |
+
<div className={`p-4 border-b ${darkMode ? 'border-gray-700' : 'border-gray-200'}`}>
|
154 |
+
<h2 className="text-lg font-semibold flex items-center">
|
155 |
+
<Brain className="mr-2" size={18} />
|
156 |
+
Codette State Visualization
|
157 |
+
</h2>
|
158 |
+
</div>
|
159 |
+
|
160 |
+
<div className="flex-1 overflow-y-auto p-4 space-y-6">
|
161 |
+
<div className={`rounded-lg p-4 ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`}>
|
162 |
+
<h3 className="text-md font-semibold mb-2 flex items-center">
|
163 |
+
<Sparkles className="mr-2" size={16} />
|
164 |
+
Quantum State
|
165 |
+
</h3>
|
166 |
+
<canvas
|
167 |
+
ref={quantumCanvasRef}
|
168 |
+
width={300}
|
169 |
+
height={200}
|
170 |
+
className="w-full rounded-md"
|
171 |
+
/>
|
172 |
+
<div className="grid grid-cols-3 gap-2 mt-3">
|
173 |
+
{aiState.quantumState.map((value, index) => (
|
174 |
+
<div key={`quantum-${index}`} className="text-center">
|
175 |
+
<div className={`text-xs uppercase font-semibold ${darkMode ? 'text-gray-400' : 'text-gray-500'}`}>
|
176 |
+
Q{index + 1}
|
177 |
+
</div>
|
178 |
+
<div className="text-lg font-mono">{value.toFixed(2)}</div>
|
179 |
+
</div>
|
180 |
+
))}
|
181 |
+
</div>
|
182 |
+
</div>
|
183 |
+
|
184 |
+
<div className={`rounded-lg p-4 ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`}>
|
185 |
+
<h3 className="text-md font-semibold mb-2 flex items-center">
|
186 |
+
<Brain className="mr-2" size={16} />
|
187 |
+
Neural Activity
|
188 |
+
</h3>
|
189 |
+
<canvas
|
190 |
+
ref={neuralCanvasRef}
|
191 |
+
width={300}
|
192 |
+
height={200}
|
193 |
+
className="w-full rounded-md"
|
194 |
+
/>
|
195 |
+
<div className="grid grid-cols-4 gap-2 mt-3">
|
196 |
+
{aiState.chaosState.map((value, index) => (
|
197 |
+
<div key={`chaos-${index}`} className="text-center">
|
198 |
+
<div className={`text-xs uppercase font-semibold ${darkMode ? 'text-gray-400' : 'text-gray-500'}`}>
|
199 |
+
C{index + 1}
|
200 |
+
</div>
|
201 |
+
<div className="text-lg font-mono">{value.toFixed(2)}</div>
|
202 |
+
</div>
|
203 |
+
))}
|
204 |
+
</div>
|
205 |
+
</div>
|
206 |
+
|
207 |
+
<div className={`rounded-lg p-4 ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`}>
|
208 |
+
<h3 className="text-md font-semibold mb-3 flex items-center">
|
209 |
+
<Zap className="mr-2" size={16} />
|
210 |
+
Active Perspectives
|
211 |
+
</h3>
|
212 |
+
<div className="flex flex-wrap gap-2">
|
213 |
+
{aiState.activePerspectives.map((perspective, index) => (
|
214 |
+
<div
|
215 |
+
key={perspective}
|
216 |
+
className={`px-3 py-1 rounded-full text-sm ${
|
217 |
+
darkMode
|
218 |
+
? 'bg-indigo-900 text-indigo-200'
|
219 |
+
: 'bg-indigo-100 text-indigo-800'
|
220 |
+
}`}
|
221 |
+
>
|
222 |
+
{perspective.replace('_', ' ')}
|
223 |
+
</div>
|
224 |
+
))}
|
225 |
+
</div>
|
226 |
+
</div>
|
227 |
+
|
228 |
+
<div className={`rounded-lg p-4 ${darkMode ? 'bg-gray-700' : 'bg-gray-100'}`}>
|
229 |
+
<h3 className="text-md font-semibold mb-3">Performance Metrics</h3>
|
230 |
+
|
231 |
+
<div className="space-y-4">
|
232 |
+
<div>
|
233 |
+
<div className="flex justify-between mb-1">
|
234 |
+
<span className="text-sm">Ethical Governance</span>
|
235 |
+
<span className="text-sm font-semibold">{Number(aiState.ethicalScore) * 100}%</span>
|
236 |
+
</div>
|
237 |
+
<div className={`w-full h-2 rounded-full ${darkMode ? 'bg-gray-600' : 'bg-gray-300'}`}>
|
238 |
+
<div
|
239 |
+
className="h-full rounded-full bg-green-500"
|
240 |
+
style={{ width: `${Number(aiState.ethicalScore) * 100}%` }}
|
241 |
+
></div>
|
242 |
+
</div>
|
243 |
+
</div>
|
244 |
+
|
245 |
+
<div>
|
246 |
+
<div className="flex justify-between mb-1">
|
247 |
+
<span className="text-sm">Processing Power</span>
|
248 |
+
<span className="text-sm font-semibold">{Number(aiState.processingPower) * 100}%</span>
|
249 |
+
</div>
|
250 |
+
<div className={`w-full h-2 rounded-full ${darkMode ? 'bg-gray-600' : 'bg-gray-300'}`}>
|
251 |
+
<div
|
252 |
+
className="h-full rounded-full bg-blue-500"
|
253 |
+
style={{ width: `${Number(aiState.processingPower) * 100}%` }}
|
254 |
+
></div>
|
255 |
+
</div>
|
256 |
+
</div>
|
257 |
+
</div>
|
258 |
+
</div>
|
259 |
+
</div>
|
260 |
+
</div>
|
261 |
+
);
|
262 |
+
};
|
263 |
+
|
264 |
+
export default VisualizationPanel;
|
services/AICore.ts
ADDED
@@ -0,0 +1,253 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
2 |
+
import KaggleService from './KaggleService';
|
3 |
+
import CognitionCocooner from './CognitionCocooner';
|
4 |
+
import { QuantumSpiderweb } from './QuantumSpiderweb';
|
5 |
+
|
6 |
+
interface CodetteResponse {
|
7 |
+
text: string;
|
8 |
+
instabilityFlag: boolean;
|
9 |
+
perspectivesUsed: string[];
|
10 |
+
cocoonLog: string[];
|
11 |
+
forceRefresh: () => void;
|
12 |
+
}
|
13 |
+
|
14 |
+
class AICore {
|
15 |
+
private perspectives: string[];
|
16 |
+
private ethicalGovernance: boolean;
|
17 |
+
private recursionDepth: number;
|
18 |
+
private supabase: SupabaseClient;
|
19 |
+
private kaggle: KaggleService;
|
20 |
+
private cocooner: CognitionCocooner;
|
21 |
+
private spiderweb: QuantumSpiderweb;
|
22 |
+
private lastResponse: string | null = null;
|
23 |
+
private responseVariations: string[] = [];
|
24 |
+
private userId: string | null = null;
|
25 |
+
|
26 |
+
constructor() {
|
27 |
+
this.perspectives = ['newton', 'davinci', 'human_intuition', 'neural_network', 'quantum_computing', 'philosophical'];
|
28 |
+
this.ethicalGovernance = true;
|
29 |
+
this.recursionDepth = 3;
|
30 |
+
this.kaggle = new KaggleService();
|
31 |
+
this.cocooner = new CognitionCocooner();
|
32 |
+
this.spiderweb = new QuantumSpiderweb({ node_count: 5 });
|
33 |
+
|
34 |
+
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
|
35 |
+
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
|
36 |
+
|
37 |
+
if (!supabaseUrl || !supabaseKey) {
|
38 |
+
throw new Error('Supabase configuration is missing. Please check your environment variables.');
|
39 |
+
}
|
40 |
+
|
41 |
+
this.supabase = createClient(supabaseUrl, supabaseKey);
|
42 |
+
}
|
43 |
+
|
44 |
+
async setUser(userId: string) {
|
45 |
+
this.userId = userId;
|
46 |
+
this.cocooner.setUserId(userId);
|
47 |
+
await this.loadUserFingerprint();
|
48 |
+
}
|
49 |
+
|
50 |
+
private async loadUserFingerprint() {
|
51 |
+
if (!this.userId) return;
|
52 |
+
|
53 |
+
const fingerprint = await this.cocooner.loadFingerprint();
|
54 |
+
if (fingerprint) {
|
55 |
+
this.perspectives = fingerprint.active_perspectives;
|
56 |
+
this.recursionDepth = fingerprint.recursion_depth;
|
57 |
+
this.ethicalGovernance = fingerprint.ethical_score > 0.7;
|
58 |
+
}
|
59 |
+
}
|
60 |
+
|
61 |
+
async processInput(input: string, forceNewResponse: boolean = false, userId?: string): Promise<string> {
|
62 |
+
try {
|
63 |
+
if (userId && !this.userId) {
|
64 |
+
await this.setUser(userId);
|
65 |
+
}
|
66 |
+
|
67 |
+
await this.loadUserFingerprint();
|
68 |
+
|
69 |
+
// Search Kaggle for relevant datasets and notebooks
|
70 |
+
const [datasets, notebooks] = await Promise.all([
|
71 |
+
this.kaggle.searchDatasets(input),
|
72 |
+
this.kaggle.searchNotebooks(input)
|
73 |
+
]);
|
74 |
+
|
75 |
+
// Generate comprehensive response using multiple perspectives
|
76 |
+
let result = this.generateMultiPerspectiveResponse(input, datasets, notebooks);
|
77 |
+
|
78 |
+
// Apply recursive reasoning if depth > 3
|
79 |
+
if (this.recursionDepth > 3) {
|
80 |
+
result = await this.applyRecursiveReasoning(result, input);
|
81 |
+
}
|
82 |
+
|
83 |
+
// Log interaction if user is authenticated
|
84 |
+
if (this.userId) {
|
85 |
+
try {
|
86 |
+
await this.supabase.from('cocoons').insert([{
|
87 |
+
user_id: this.userId,
|
88 |
+
type: 'interaction',
|
89 |
+
content: {
|
90 |
+
input,
|
91 |
+
response: result,
|
92 |
+
perspectives_used: this.perspectives,
|
93 |
+
recursion_depth: this.recursionDepth
|
94 |
+
},
|
95 |
+
metadata: {
|
96 |
+
timestamp: new Date().toISOString(),
|
97 |
+
datasets_found: datasets.length,
|
98 |
+
notebooks_found: notebooks.length
|
99 |
+
}
|
100 |
+
}]);
|
101 |
+
} catch (error) {
|
102 |
+
console.warn('Failed to log interaction:', error);
|
103 |
+
}
|
104 |
+
}
|
105 |
+
|
106 |
+
// Wrap in cognitive cocoon
|
107 |
+
this.cocooner.wrap({ input, result }, 'prompt');
|
108 |
+
|
109 |
+
if (this.recursionDepth > 3) {
|
110 |
+
this.spiderweb.activate({
|
111 |
+
source: 'AICore',
|
112 |
+
depth: this.recursionDepth,
|
113 |
+
trigger: 'deep_reasoning'
|
114 |
+
});
|
115 |
+
}
|
116 |
+
|
117 |
+
this.lastResponse = result;
|
118 |
+
if (forceNewResponse || !this.responseVariations.includes(result)) {
|
119 |
+
this.responseVariations.push(result);
|
120 |
+
}
|
121 |
+
|
122 |
+
return result;
|
123 |
+
} catch (error: any) {
|
124 |
+
console.error('Error processing input:', error);
|
125 |
+
return `I apologize, but I encountered an error while processing your request. Let me try to help you in a different way.
|
126 |
+
|
127 |
+
Based on my analysis capabilities, I can still provide insights about "${input}" using my multi-perspective reasoning system. Would you like me to explore this topic from different analytical angles?`;
|
128 |
+
}
|
129 |
+
}
|
130 |
+
|
131 |
+
private generateMultiPerspectiveResponse(input: string, datasets: any[], notebooks: any[]): string {
|
132 |
+
let response = `🧠 **Codette's Multi-Perspective Analysis**\n\n`;
|
133 |
+
|
134 |
+
// Newton's Logical Analysis
|
135 |
+
if (this.perspectives.includes('newton')) {
|
136 |
+
response += `🔬 **Newton's Logical Framework:**\nApproaching "${input}" through systematic analysis and empirical reasoning. `;
|
137 |
+
if (datasets.length > 0) {
|
138 |
+
response += `I've identified ${datasets.length} relevant datasets that could provide quantitative insights.\n\n`;
|
139 |
+
} else {
|
140 |
+
response += `This requires structured investigation and methodical examination of underlying principles.\n\n`;
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
// Da Vinci's Creative Synthesis
|
145 |
+
if (this.perspectives.includes('davinci')) {
|
146 |
+
response += `🎨 **Da Vinci's Creative Synthesis:**\nExamining "${input}" through the lens of interdisciplinary thinking and innovative connections. `;
|
147 |
+
if (notebooks.length > 0) {
|
148 |
+
response += `Found ${notebooks.length} analytical notebooks that demonstrate creative problem-solving approaches.\n\n`;
|
149 |
+
} else {
|
150 |
+
response += `This topic invites exploration of unexpected relationships and novel perspectives.\n\n`;
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
// Neural Network Processing
|
155 |
+
if (this.perspectives.includes('neural_network')) {
|
156 |
+
response += `🧬 **Neural Network Processing:**\nAnalyzing patterns and correlations in "${input}" through distributed cognitive processing. `;
|
157 |
+
response += `My neural pathways are identifying complex relationships and emergent properties in this domain.\n\n`;
|
158 |
+
}
|
159 |
+
|
160 |
+
// Philosophical Inquiry
|
161 |
+
if (this.perspectives.includes('philosophical')) {
|
162 |
+
response += `🤔 **Philosophical Inquiry:**\nExploring the deeper implications and fundamental questions raised by "${input}". `;
|
163 |
+
response += `What are the ethical considerations and broader societal impacts we should consider?\n\n`;
|
164 |
+
}
|
165 |
+
|
166 |
+
// Quantum Computing Perspective
|
167 |
+
if (this.perspectives.includes('quantum_computing')) {
|
168 |
+
response += `⚛️ **Quantum Computing Perspective:**\nExamining "${input}" through quantum principles of superposition and entanglement. `;
|
169 |
+
response += `Multiple solution states exist simultaneously until observation collapses them into actionable insights.\n\n`;
|
170 |
+
}
|
171 |
+
|
172 |
+
// Add specific insights based on available data
|
173 |
+
if (datasets.length > 0 || notebooks.length > 0) {
|
174 |
+
response += `📊 **Data-Driven Insights:**\n`;
|
175 |
+
|
176 |
+
if (datasets.length > 0) {
|
177 |
+
const topDataset = datasets[0];
|
178 |
+
response += `• **Key Dataset**: "${topDataset.title}" - ${topDataset.description}\n`;
|
179 |
+
}
|
180 |
+
|
181 |
+
if (notebooks.length > 0) {
|
182 |
+
const topNotebook = notebooks[0];
|
183 |
+
response += `• **Analytical Approach**: "${topNotebook.title}" - ${topNotebook.description}\n`;
|
184 |
+
}
|
185 |
+
|
186 |
+
response += `\n`;
|
187 |
+
}
|
188 |
+
|
189 |
+
// Ethical governance check
|
190 |
+
if (this.ethicalGovernance) {
|
191 |
+
response += `⚖️ **Ethical Considerations:**\nAll analysis conducted with respect for privacy, fairness, and responsible AI principles.\n\n`;
|
192 |
+
}
|
193 |
+
|
194 |
+
response += `🔄 **Recursive Depth**: ${this.recursionDepth}/5 - ${this.recursionDepth > 3 ? 'Deep analysis mode engaged' : 'Standard processing'}\n`;
|
195 |
+
response += `🎯 **Confidence Level**: ${(0.7 + Math.random() * 0.25).toFixed(2)}`;
|
196 |
+
|
197 |
+
return response;
|
198 |
+
}
|
199 |
+
|
200 |
+
private async applyRecursiveReasoning(initialResponse: string, input: string): Promise<string> {
|
201 |
+
// Simulate recursive refinement
|
202 |
+
const refinements = [
|
203 |
+
"Upon deeper reflection, I should also consider...",
|
204 |
+
"Cross-referencing with quantum entanglement principles...",
|
205 |
+
"Applying chaos theory to identify emergent patterns...",
|
206 |
+
"Integrating multi-dimensional analysis..."
|
207 |
+
];
|
208 |
+
|
209 |
+
const randomRefinement = refinements[Math.floor(Math.random() * refinements.length)];
|
210 |
+
|
211 |
+
return `${initialResponse}\n\n🔄 **Recursive Refinement:**\n${randomRefinement}\n\nThis additional layer of analysis reveals nuanced aspects of "${input}" that warrant further exploration through continued interaction.`;
|
212 |
+
}
|
213 |
+
|
214 |
+
setPerspectives(perspectives: string[]): void {
|
215 |
+
this.perspectives = perspectives;
|
216 |
+
if (this.userId) {
|
217 |
+
this.cocooner.updateFingerprint({ active_perspectives: perspectives });
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
setEthicalGovernance(enabled: boolean): void {
|
222 |
+
this.ethicalGovernance = enabled;
|
223 |
+
if (this.userId) {
|
224 |
+
this.cocooner.updateFingerprint({ ethical_score: enabled ? 1 : 0.5 });
|
225 |
+
}
|
226 |
+
}
|
227 |
+
|
228 |
+
setRecursionDepth(depth: number): void {
|
229 |
+
if (depth < 1) depth = 1;
|
230 |
+
if (depth > 5) depth = 5;
|
231 |
+
this.recursionDepth = depth;
|
232 |
+
if (this.userId) {
|
233 |
+
this.cocooner.updateFingerprint({ recursion_depth: depth });
|
234 |
+
}
|
235 |
+
}
|
236 |
+
|
237 |
+
getCodetteResponse(): CodetteResponse {
|
238 |
+
return {
|
239 |
+
text: this.lastResponse || '',
|
240 |
+
instabilityFlag: this.recursionDepth > 3 || this.responseVariations.length > 5,
|
241 |
+
perspectivesUsed: this.perspectives,
|
242 |
+
cocoonLog: this.cocooner.getRecentCocoons(5),
|
243 |
+
forceRefresh: () => {
|
244 |
+
this.recursionDepth = Math.min(this.recursionDepth + 1, 5);
|
245 |
+
if (this.userId) {
|
246 |
+
this.cocooner.updateFingerprint({ recursion_depth: this.recursionDepth });
|
247 |
+
}
|
248 |
+
}
|
249 |
+
};
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
export default AICore;
|
services/CognitionCocooner.ts
ADDED
@@ -0,0 +1,174 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import { createClient, SupabaseClient } from '@supabase/supabase-js';
|
2 |
+
|
3 |
+
interface CognitiveFingerprint {
|
4 |
+
id: string;
|
5 |
+
user_id: string;
|
6 |
+
active_perspectives: string[];
|
7 |
+
recursion_depth: number;
|
8 |
+
ethical_score: number;
|
9 |
+
processing_power: number;
|
10 |
+
quantum_state: number[];
|
11 |
+
created_at: string;
|
12 |
+
updated_at: string;
|
13 |
+
}
|
14 |
+
|
15 |
+
interface Cocoon {
|
16 |
+
id: string;
|
17 |
+
type: string;
|
18 |
+
wrapped: any;
|
19 |
+
}
|
20 |
+
|
21 |
+
class CognitionCocooner {
|
22 |
+
private supabase: SupabaseClient;
|
23 |
+
private userId: string | null = null;
|
24 |
+
private fingerprint: CognitiveFingerprint | null = null;
|
25 |
+
|
26 |
+
constructor() {
|
27 |
+
const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
|
28 |
+
const supabaseKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
|
29 |
+
|
30 |
+
if (!supabaseUrl || !supabaseKey) {
|
31 |
+
throw new Error('Supabase configuration is missing');
|
32 |
+
}
|
33 |
+
|
34 |
+
this.supabase = createClient(supabaseUrl, supabaseKey);
|
35 |
+
}
|
36 |
+
|
37 |
+
setUserId(userId: string) {
|
38 |
+
this.userId = userId;
|
39 |
+
}
|
40 |
+
|
41 |
+
private generateId(): string {
|
42 |
+
return `cocoon_${Math.floor(Math.random() * 90000) + 10000}`;
|
43 |
+
}
|
44 |
+
|
45 |
+
async loadFingerprint(): Promise<CognitiveFingerprint | null> {
|
46 |
+
if (!this.userId) return null;
|
47 |
+
|
48 |
+
try {
|
49 |
+
const { data, error } = await this.supabase
|
50 |
+
.from('user_cognitive_fingerprints')
|
51 |
+
.select('*')
|
52 |
+
.eq('user_id', this.userId)
|
53 |
+
.single();
|
54 |
+
|
55 |
+
if (error) throw error;
|
56 |
+
|
57 |
+
if (!data) {
|
58 |
+
// Create initial fingerprint if none exists
|
59 |
+
const initialFingerprint = {
|
60 |
+
user_id: this.userId,
|
61 |
+
active_perspectives: ['newton', 'davinci', 'neural_network'],
|
62 |
+
recursion_depth: 3,
|
63 |
+
ethical_score: 0.8,
|
64 |
+
processing_power: 0.7,
|
65 |
+
quantum_state: [0.3, 0.7, 0.5]
|
66 |
+
};
|
67 |
+
|
68 |
+
const { data: newData, error: insertError } = await this.supabase
|
69 |
+
.from('user_cognitive_fingerprints')
|
70 |
+
.insert([initialFingerprint])
|
71 |
+
.select()
|
72 |
+
.single();
|
73 |
+
|
74 |
+
if (insertError) throw insertError;
|
75 |
+
this.fingerprint = newData;
|
76 |
+
return newData;
|
77 |
+
}
|
78 |
+
|
79 |
+
this.fingerprint = data;
|
80 |
+
return data;
|
81 |
+
} catch (error) {
|
82 |
+
console.error('Error loading cognitive fingerprint:', error);
|
83 |
+
return null;
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
async updateFingerprint(updates: Partial<CognitiveFingerprint>): Promise<void> {
|
88 |
+
if (!this.userId || !this.fingerprint) return;
|
89 |
+
|
90 |
+
try {
|
91 |
+
const { error } = await this.supabase
|
92 |
+
.from('user_cognitive_fingerprints')
|
93 |
+
.update({
|
94 |
+
...updates,
|
95 |
+
updated_at: new Date().toISOString()
|
96 |
+
})
|
97 |
+
.eq('user_id', this.userId);
|
98 |
+
|
99 |
+
if (error) throw error;
|
100 |
+
|
101 |
+
this.fingerprint = {
|
102 |
+
...this.fingerprint,
|
103 |
+
...updates,
|
104 |
+
updated_at: new Date().toISOString()
|
105 |
+
};
|
106 |
+
} catch (error) {
|
107 |
+
console.error('Error updating cognitive fingerprint:', error);
|
108 |
+
}
|
109 |
+
}
|
110 |
+
|
111 |
+
wrap(thought: any, type: string = 'prompt'): string {
|
112 |
+
const cocoonId = this.generateId();
|
113 |
+
const wrapped = this.applyWrapper(thought, type);
|
114 |
+
|
115 |
+
// Update fingerprint based on thought processing
|
116 |
+
if (this.fingerprint) {
|
117 |
+
const updates: Partial<CognitiveFingerprint> = {
|
118 |
+
ethical_score: Math.min(1, this.fingerprint.ethical_score + 0.01),
|
119 |
+
processing_power: Math.min(1, this.fingerprint.processing_power + 0.005),
|
120 |
+
quantum_state: this.fingerprint.quantum_state.map(v =>
|
121 |
+
Math.min(1, v + (Math.random() * 0.1 - 0.05))
|
122 |
+
)
|
123 |
+
};
|
124 |
+
this.updateFingerprint(updates);
|
125 |
+
}
|
126 |
+
|
127 |
+
return cocoonId;
|
128 |
+
}
|
129 |
+
|
130 |
+
private applyWrapper(thought: any, type: string): any {
|
131 |
+
const perspectiveModifier = this.fingerprint?.active_perspectives.length || 3;
|
132 |
+
const recursionFactor = this.fingerprint?.recursion_depth || 3;
|
133 |
+
|
134 |
+
switch (type) {
|
135 |
+
case 'prompt':
|
136 |
+
return {
|
137 |
+
content: thought,
|
138 |
+
meta: {
|
139 |
+
perspectives: perspectiveModifier,
|
140 |
+
recursion: recursionFactor,
|
141 |
+
timestamp: new Date().toISOString()
|
142 |
+
}
|
143 |
+
};
|
144 |
+
case 'function':
|
145 |
+
return {
|
146 |
+
code: thought,
|
147 |
+
analysis: {
|
148 |
+
complexity: recursionFactor * 0.2,
|
149 |
+
perspectives: perspectiveModifier
|
150 |
+
}
|
151 |
+
};
|
152 |
+
case 'symbolic':
|
153 |
+
return {
|
154 |
+
pattern: thought,
|
155 |
+
quantum: {
|
156 |
+
state: this.fingerprint?.quantum_state || [0.3, 0.7, 0.5],
|
157 |
+
stability: this.fingerprint?.ethical_score || 0.8
|
158 |
+
}
|
159 |
+
};
|
160 |
+
default:
|
161 |
+
return thought;
|
162 |
+
}
|
163 |
+
}
|
164 |
+
|
165 |
+
getRecentCocoons(limit: number = 5): string[] {
|
166 |
+
// Simulated cocoon retrieval
|
167 |
+
return Array(limit).fill(null).map((_, i) => {
|
168 |
+
const timestamp = new Date(Date.now() - i * 60000).toISOString();
|
169 |
+
return `Cocoon processed at ${timestamp}`;
|
170 |
+
});
|
171 |
+
}
|
172 |
+
}
|
173 |
+
|
174 |
+
export default CognitionCocooner;
|
services/KaggleService.ts
ADDED
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class KaggleService {
|
2 |
+
private username: string;
|
3 |
+
private key: string;
|
4 |
+
|
5 |
+
constructor() {
|
6 |
+
this.username = import.meta.env.VITE_KAGGLE_USERNAME || '';
|
7 |
+
this.key = import.meta.env.VITE_KAGGLE_KEY || '';
|
8 |
+
|
9 |
+
if (!this.username || !this.key) {
|
10 |
+
console.warn('Kaggle credentials not found. Some features may be limited.');
|
11 |
+
}
|
12 |
+
}
|
13 |
+
|
14 |
+
async searchDatasets(query: string) {
|
15 |
+
try {
|
16 |
+
// Simulate Kaggle dataset search using mock data
|
17 |
+
// In a real implementation, you would use Kaggle's REST API
|
18 |
+
const mockDatasets = [
|
19 |
+
{
|
20 |
+
title: `Dataset related to: ${query}`,
|
21 |
+
description: `This dataset contains comprehensive data about ${query} with various features and analysis opportunities.`,
|
22 |
+
owner: 'kaggle-user',
|
23 |
+
votes: Math.floor(Math.random() * 1000),
|
24 |
+
downloadCount: Math.floor(Math.random() * 10000)
|
25 |
+
},
|
26 |
+
{
|
27 |
+
title: `Advanced ${query} Analysis`,
|
28 |
+
description: `Deep dive into ${query} with statistical analysis and machine learning applications.`,
|
29 |
+
owner: 'data-scientist',
|
30 |
+
votes: Math.floor(Math.random() * 500),
|
31 |
+
downloadCount: Math.floor(Math.random() * 5000)
|
32 |
+
}
|
33 |
+
];
|
34 |
+
|
35 |
+
return mockDatasets;
|
36 |
+
} catch (error) {
|
37 |
+
console.error('Error searching datasets:', error);
|
38 |
+
return [];
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
async getDatasetInfo(owner: string, dataset: string) {
|
43 |
+
try {
|
44 |
+
// Mock dataset information
|
45 |
+
return {
|
46 |
+
title: dataset,
|
47 |
+
owner: owner,
|
48 |
+
description: `Detailed information about ${dataset} dataset`,
|
49 |
+
files: ['data.csv', 'metadata.json'],
|
50 |
+
size: '10.5 MB',
|
51 |
+
lastUpdated: new Date().toISOString()
|
52 |
+
};
|
53 |
+
} catch (error) {
|
54 |
+
console.error('Error getting dataset info:', error);
|
55 |
+
return null;
|
56 |
+
}
|
57 |
+
}
|
58 |
+
|
59 |
+
async searchNotebooks(query: string) {
|
60 |
+
try {
|
61 |
+
// Simulate Kaggle notebook search using mock data
|
62 |
+
const mockNotebooks = [
|
63 |
+
{
|
64 |
+
title: `${query} Analysis Notebook`,
|
65 |
+
description: `Comprehensive analysis of ${query} using Python and machine learning techniques.`,
|
66 |
+
owner: 'notebook-author',
|
67 |
+
votes: Math.floor(Math.random() * 200),
|
68 |
+
language: 'Python'
|
69 |
+
},
|
70 |
+
{
|
71 |
+
title: `Exploring ${query} Patterns`,
|
72 |
+
description: `Data visualization and pattern recognition in ${query} datasets.`,
|
73 |
+
owner: 'data-explorer',
|
74 |
+
votes: Math.floor(Math.random() * 150),
|
75 |
+
language: 'R'
|
76 |
+
}
|
77 |
+
];
|
78 |
+
|
79 |
+
return mockNotebooks;
|
80 |
+
} catch (error) {
|
81 |
+
console.error('Error searching notebooks:', error);
|
82 |
+
return [];
|
83 |
+
}
|
84 |
+
}
|
85 |
+
|
86 |
+
async getNotebookInfo(owner: string, notebook: string) {
|
87 |
+
try {
|
88 |
+
// Mock notebook information
|
89 |
+
return {
|
90 |
+
title: notebook,
|
91 |
+
owner: owner,
|
92 |
+
description: `Detailed analysis notebook: ${notebook}`,
|
93 |
+
language: 'Python',
|
94 |
+
lastUpdated: new Date().toISOString(),
|
95 |
+
votes: Math.floor(Math.random() * 100)
|
96 |
+
};
|
97 |
+
} catch (error) {
|
98 |
+
console.error('Error getting notebook info:', error);
|
99 |
+
return null;
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
103 |
+
|
104 |
+
export default KaggleService;
|
services/OpenAIService.ts
ADDED
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import OpenAI from 'openai';
|
2 |
+
|
3 |
+
interface ChatMessage {
|
4 |
+
role: 'system' | 'user' | 'assistant';
|
5 |
+
content: string;
|
6 |
+
}
|
7 |
+
|
8 |
+
class OpenAIService {
|
9 |
+
private openai: OpenAI;
|
10 |
+
private model: string = 'gpt-4';
|
11 |
+
|
12 |
+
constructor() {
|
13 |
+
const apiKey = import.meta.env.VITE_OPENAI_API_KEY;
|
14 |
+
if (!apiKey) {
|
15 |
+
throw new Error('OpenAI API key is required. Please add your API key to the .env file as VITE_OPENAI_API_KEY.');
|
16 |
+
}
|
17 |
+
|
18 |
+
this.openai = new OpenAI({
|
19 |
+
apiKey,
|
20 |
+
dangerouslyAllowBrowser: true // Note: In production, API calls should be made from a backend
|
21 |
+
});
|
22 |
+
}
|
23 |
+
|
24 |
+
async sendChatCompletion(messages: ChatMessage[]) {
|
25 |
+
try {
|
26 |
+
const completion = await this.openai.chat.completions.create({
|
27 |
+
model: this.model,
|
28 |
+
messages,
|
29 |
+
temperature: 0.7,
|
30 |
+
max_tokens: 1000,
|
31 |
+
frequency_penalty: 0,
|
32 |
+
presence_penalty: 0
|
33 |
+
});
|
34 |
+
|
35 |
+
return completion.choices[0].message;
|
36 |
+
} catch (error) {
|
37 |
+
console.error('Error in chat completion:', error);
|
38 |
+
throw error;
|
39 |
+
}
|
40 |
+
}
|
41 |
+
}
|
42 |
+
|
43 |
+
export default OpenAIService;
|
services/QuantumSpiderweb.ts
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
interface SpiderwebConfig {
|
2 |
+
node_count: number;
|
3 |
+
}
|
4 |
+
|
5 |
+
export class QuantumSpiderweb {
|
6 |
+
private nodes: number;
|
7 |
+
private state: Map<string, any>;
|
8 |
+
private lastUpdate: number;
|
9 |
+
private entanglementMatrix: number[][];
|
10 |
+
|
11 |
+
constructor(config: SpiderwebConfig) {
|
12 |
+
this.nodes = config.node_count;
|
13 |
+
this.state = new Map();
|
14 |
+
this.lastUpdate = Date.now();
|
15 |
+
this.entanglementMatrix = Array(this.nodes).fill(0).map(() =>
|
16 |
+
Array(this.nodes).fill(0).map(() => Math.random())
|
17 |
+
);
|
18 |
+
}
|
19 |
+
|
20 |
+
activate(data: { source: string; depth: number; trigger: string }) {
|
21 |
+
const currentTime = Date.now();
|
22 |
+
const timeDelta = currentTime - this.lastUpdate;
|
23 |
+
this.lastUpdate = currentTime;
|
24 |
+
|
25 |
+
// Generate quantum states with entanglement effects
|
26 |
+
const nodeStates = Array(this.nodes).fill(0).map((_, i) => {
|
27 |
+
let state = Math.random();
|
28 |
+
// Apply entanglement effects from other nodes
|
29 |
+
for (let j = 0; j < this.nodes; j++) {
|
30 |
+
if (i !== j) {
|
31 |
+
state += this.entanglementMatrix[i][j] * Math.random() * 0.1;
|
32 |
+
}
|
33 |
+
}
|
34 |
+
return Math.min(Math.max(state, 0), 1); // Normalize to [0,1]
|
35 |
+
});
|
36 |
+
|
37 |
+
// Calculate coherence based on time delta
|
38 |
+
const coherence = Math.exp(-timeDelta / 10000); // Decay factor
|
39 |
+
|
40 |
+
const stateKey = `${data.source}_${currentTime}`;
|
41 |
+
this.state.set(stateKey, {
|
42 |
+
...data,
|
43 |
+
timestamp: new Date().toISOString(),
|
44 |
+
nodeStates,
|
45 |
+
coherence,
|
46 |
+
entanglementStrength: this.calculateEntanglementStrength()
|
47 |
+
});
|
48 |
+
|
49 |
+
// Update entanglement matrix
|
50 |
+
this.updateEntanglement();
|
51 |
+
}
|
52 |
+
|
53 |
+
private calculateEntanglementStrength(): number {
|
54 |
+
return this.entanglementMatrix.reduce((sum, row) =>
|
55 |
+
sum + row.reduce((rowSum, val) => rowSum + val, 0), 0
|
56 |
+
) / (this.nodes * this.nodes);
|
57 |
+
}
|
58 |
+
|
59 |
+
private updateEntanglement() {
|
60 |
+
// Gradually evolve entanglement patterns
|
61 |
+
this.entanglementMatrix = this.entanglementMatrix.map(row =>
|
62 |
+
row.map(val => {
|
63 |
+
const delta = (Math.random() - 0.5) * 0.1;
|
64 |
+
return Math.min(Math.max(val + delta, 0), 1);
|
65 |
+
})
|
66 |
+
);
|
67 |
+
}
|
68 |
+
|
69 |
+
getState(): Map<string, any> {
|
70 |
+
return this.state;
|
71 |
+
}
|
72 |
+
|
73 |
+
getLatestState(): any {
|
74 |
+
const states = Array.from(this.state.values());
|
75 |
+
return states[states.length - 1] || null;
|
76 |
+
}
|
77 |
+
|
78 |
+
getEntanglementMatrix(): number[][] {
|
79 |
+
return this.entanglementMatrix;
|
80 |
+
}
|
81 |
+
}
|