Spaces:
Running
Running
| import React, { useState, useEffect } from 'react'; | |
| import { motion } from 'framer-motion'; | |
| // π¬ Perspective Trail Display | |
| export function PerspectiveTrail({ perspectives }: { perspectives: string[] }) { | |
| return ( | |
| <div className="mt-4 text-sm text-purple-700"> | |
| <p className="font-semibold">Activated Perspectives:</p> | |
| <motion.ul | |
| className="list-disc ml-5" | |
| initial={{ opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| transition={{ duration: 0.5 }} | |
| > | |
| {perspectives.map((perspective, index) => ( | |
| <motion.li | |
| key={index} | |
| initial={{ x: -20, opacity: 0 }} | |
| animate={{ x: 0, opacity: 1 }} | |
| transition={{ delay: index * 0.1 }} | |
| > | |
| {perspective} | |
| </motion.li> | |
| ))} | |
| </motion.ul> | |
| </div> | |
| ); | |
| } | |
| // π Cocoon Replay Viewer | |
| export function CocoonReplay({ cocoons }: { cocoons: string[] }) { | |
| const [activeIndex, setActiveIndex] = useState(0); | |
| useEffect(() => { | |
| const timer = setInterval(() => { | |
| setActiveIndex(prev => (prev + 1) % cocoons.length); | |
| }, 3000); | |
| return () => clearInterval(timer); | |
| }, [cocoons.length]); | |
| return ( | |
| <div className="mt-4 text-sm text-green-700"> | |
| <p className="font-semibold">Cocoon Memory:</p> | |
| <motion.div | |
| className="bg-green-100 p-2 rounded-md max-h-40 overflow-y-scroll" | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5 }} | |
| > | |
| {cocoons.map((cocoon, idx) => ( | |
| <motion.pre | |
| key={idx} | |
| className={`whitespace-pre-wrap text-xs mb-2 transition-colors duration-300 ${ | |
| idx === activeIndex ? 'bg-green-200 rounded p-1' : '' | |
| }`} | |
| initial={{ opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| transition={{ delay: idx * 0.1 }} | |
| > | |
| {cocoon} | |
| </motion.pre> | |
| ))} | |
| </motion.div> | |
| </div> | |
| ); | |
| } | |
| // π Quantum Collapse Detector | |
| export function CollapseDetector({ isUnstable }: { isUnstable: boolean }) { | |
| return ( | |
| <motion.div | |
| animate={{ | |
| scale: isUnstable ? [1, 1.3, 1] : 1, | |
| opacity: isUnstable ? [0.6, 1, 0.6] : 1, | |
| }} | |
| transition={{ duration: 1.5, repeat: Infinity }} | |
| className={`w-4 h-4 rounded-full mt-2 ml-2 ${ | |
| isUnstable ? "bg-red-500" : "bg-blue-300" | |
| }`} | |
| title={isUnstable ? "Quantum Instability Detected" : "Stable"} | |
| /> | |
| ); | |
| } | |
| // π§ CodetteResponse Interface | |
| export interface CodetteResponse { | |
| text: string; | |
| instabilityFlag: boolean; | |
| perspectivesUsed: string[]; | |
| cocoonLog: string[]; | |
| forceRefresh: () => void; | |
| } | |
| // π§ CodetteResponseCard Component | |
| export function CodetteResponseCard({ response }: { response: CodetteResponse }) { | |
| const [loopCount, setLoopCount] = useState(0); | |
| const [introspectiveMessage, setIntrospectiveMessage] = useState<string | null>(null); | |
| useEffect(() => { | |
| const last = sessionStorage.getItem("lastCodetteResponse"); | |
| if (last === response.text) { | |
| console.warn("Codette is repeating herself. Triggering fallback logic."); | |
| setLoopCount(prev => prev + 1); | |
| if (response.forceRefresh) { | |
| response.forceRefresh(); | |
| } | |
| setIntrospectiveMessage("I feel like I've said this before... Let me think differently."); | |
| } else { | |
| setLoopCount(0); | |
| setIntrospectiveMessage(null); | |
| } | |
| sessionStorage.setItem("lastCodetteResponse", response.text); | |
| }, [response.text]); | |
| return ( | |
| <motion.div | |
| className="border border-gray-200 p-4 rounded-xl shadow-sm bg-white max-w-[80%]" | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.5 }} | |
| > | |
| <p className="whitespace-pre-wrap">{response.text}</p> | |
| {introspectiveMessage && ( | |
| <motion.p | |
| className="text-xs text-rose-600 italic mt-2" | |
| initial={{ opacity: 0 }} | |
| animate={{ opacity: 1 }} | |
| transition={{ delay: 0.3 }} | |
| > | |
| {introspectiveMessage} | |
| </motion.p> | |
| )} | |
| <div className="flex items-center mt-2"> | |
| <span className="text-xs text-gray-500">System Readout:</span> | |
| <CollapseDetector isUnstable={response.instabilityFlag || loopCount > 2} /> | |
| </div> | |
| <PerspectiveTrail perspectives={response.perspectivesUsed} /> | |
| <CocoonReplay cocoons={response.cocoonLog} /> | |
| </motion.div> | |
| ); | |
| } |