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> | |
); | |
} |