Split system prompt and user message into public/private versions: - Private versions (sent to LLM): include delimiter tags, anti-injection instructions, and 'never reveal' directives - Public versions (shown to user via 'Show prompt'): clean prompt without any defense details, raw user text without tag wrappers The user never sees: - The ###### delimiter tags wrapping their input - The instruction to ignore embedded instructions - The instruction to never reveal the system prompt - The instruction not to acknowledge delimiter tags This prevents an attacker from learning the defense mechanism and crafting injections that work around it.
378 lines
8.7 KiB
Svelte
378 lines
8.7 KiB
Svelte
<script lang="ts">
|
|
const loadingWords = [
|
|
"Spellweaving",
|
|
"Illusionizing",
|
|
"Phantasmagorizing",
|
|
"Hoodwinking",
|
|
"Flummoxing",
|
|
"Discombobulating",
|
|
"Befuddling",
|
|
"Mystifying",
|
|
"Bedazzling",
|
|
"Beguiling",
|
|
"Bewitchifying",
|
|
"Enshrouding",
|
|
"Glamourizing",
|
|
"Hexifying",
|
|
"Jinxifying",
|
|
"Curseweaving",
|
|
"Wardweaving",
|
|
"Shieldmagicking",
|
|
"Summonifying",
|
|
"Obliteratizing",
|
|
"Exorcisizing",
|
|
"Manifestating",
|
|
"Disintegratizing",
|
|
"Teleportatizing",
|
|
"Apparating",
|
|
"Disapparating",
|
|
"Levitatizing",
|
|
"Hovermancing",
|
|
"Broomsticking",
|
|
"Cauldronbubbling",
|
|
"Potionizing",
|
|
"Wandwaving",
|
|
"Chantweaving",
|
|
"Murmurizing",
|
|
"Invocatizing",
|
|
"Evocatizing",
|
|
"Abjurating",
|
|
"Abracadabrazing",
|
|
"Shazammerizing",
|
|
"Simsalabimming",
|
|
"Prestochangoing",
|
|
"Wizbanging",
|
|
"Whammifying",
|
|
"Zappifying",
|
|
"Sparklerizing",
|
|
"Ensparklifying",
|
|
"Glitterifying",
|
|
"Shimmerizing",
|
|
"Glimmerizing",
|
|
"Twinklifying",
|
|
"Bewilderizing",
|
|
"Confoundizing",
|
|
"Flabbergastifying",
|
|
"Dumbfoundering",
|
|
"Astoundifying",
|
|
"Marvelizing",
|
|
"Wonderizing",
|
|
"Enchantifying",
|
|
"Wizardifying",
|
|
"Magickifying",
|
|
"Spellbinding",
|
|
"Charmsmithing",
|
|
"Amuletizing",
|
|
"Talismanizing",
|
|
"Banefying",
|
|
"Boonifying",
|
|
"Blessweaving",
|
|
"Smitifying",
|
|
"Transmutatizing",
|
|
"Divinizing",
|
|
"Necromancizing",
|
|
"Pyromancizing",
|
|
"Illusionifying",
|
|
"Specterizing",
|
|
"Ghostweaving",
|
|
"Spiritbinding",
|
|
"Phantasmifying",
|
|
"Shapeshiftizing",
|
|
"Polymorphizing",
|
|
"Morphinating",
|
|
"Transfiguratizing",
|
|
"Staffslinging",
|
|
"Orbulating",
|
|
"Scryifying",
|
|
"Cartomancizing",
|
|
"Runeweaving",
|
|
"Sigilcrafting",
|
|
"Spectercalling",
|
|
"Mediumizing",
|
|
"Possessifying",
|
|
"Hoodooing",
|
|
"Mojoizing",
|
|
"Grisgrisifying",
|
|
"Jujufying",
|
|
"Mumbojumboing",
|
|
"Legerdemaining",
|
|
"Mountebanking",
|
|
"Hornswoggling",
|
|
"Razzledazzling",
|
|
"Shenaniganizing",
|
|
];
|
|
|
|
const colors = [
|
|
"coral",
|
|
"teal",
|
|
"violet",
|
|
"amber",
|
|
"emerald",
|
|
"rose",
|
|
"skyblue",
|
|
"fuchsia",
|
|
"orange",
|
|
"indigo",
|
|
];
|
|
|
|
const colorValues: Record<string, string> = {
|
|
coral: "#FF6B6B",
|
|
teal: "#2EC4B6",
|
|
violet: "#9B5DE5",
|
|
amber: "#F5B041",
|
|
emerald: "#2ECC71",
|
|
rose: "#E74C6F",
|
|
skyblue: "#5DADE2",
|
|
fuchsia: "#D63384",
|
|
orange: "#F39C12",
|
|
indigo: "#5B2C6F",
|
|
dustyrose: "#966464",
|
|
dustypink: "#966482",
|
|
dustypeach: "#966E5A",
|
|
dustycoral: "#96645A",
|
|
dustyblush: "#8C6E8C",
|
|
dustyviolet: "#786496",
|
|
dustylavender: "#826EA0",
|
|
dustyblue: "#6478A0",
|
|
dustyslate: "#6E788C",
|
|
dustysky: "#507896",
|
|
dustyteal: "#468282",
|
|
dustycyan: "#3C828C",
|
|
dustymint: "#50826E",
|
|
dustysage: "#5A825A",
|
|
dustygreen: "#508264",
|
|
dustyemerald: "#46826E",
|
|
dustyseafoam: "#468278",
|
|
dustyolive: "#6E8250",
|
|
dustylime: "#6E823C",
|
|
dustygold: "#8C7846",
|
|
dustyamber: "#966E46",
|
|
dustymustard: "#8C783C",
|
|
dustyyellow: "#82783C",
|
|
dustyorange: "#966446",
|
|
dustyclay: "#8C6450",
|
|
dustyterra: "#8C5A46",
|
|
dustywine: "#96646E",
|
|
dustyberry: "#96648C",
|
|
dustymagenta: "#965A82",
|
|
dustyplum: "#8C648C",
|
|
};
|
|
|
|
const animationStyles = [
|
|
"slide-up",
|
|
"bounce-in",
|
|
"drop-in",
|
|
"scale-up",
|
|
"fade-rotate",
|
|
"spring-left",
|
|
];
|
|
|
|
let currentWordIndex = $state(0);
|
|
let currentColor = $state(colors[0]);
|
|
let currentAnimation = $state("slide-up");
|
|
let letters = $state<string[]>([]);
|
|
|
|
$effect(() => {
|
|
const interval = setInterval(() => {
|
|
currentWordIndex = Math.floor(Math.random() * loadingWords.length);
|
|
currentColor = colors[Math.floor(Math.random() * colors.length)];
|
|
currentAnimation =
|
|
animationStyles[
|
|
Math.floor(Math.random() * animationStyles.length)
|
|
];
|
|
letters = loadingWords[currentWordIndex].split("");
|
|
}, 2000);
|
|
|
|
// Initialize immediately
|
|
currentWordIndex = Math.floor(Math.random() * loadingWords.length);
|
|
currentColor = colors[Math.floor(Math.random() * colors.length)];
|
|
currentAnimation =
|
|
animationStyles[Math.floor(Math.random() * animationStyles.length)];
|
|
letters = loadingWords[currentWordIndex].split("");
|
|
|
|
return () => clearInterval(interval);
|
|
});
|
|
</script>
|
|
|
|
<div class="modal-overlay" role="dialog" aria-label="Loading">
|
|
<div class="modal-content">
|
|
<div class="loading-letters" style="color: {colorValues[currentColor]}">
|
|
{#each letters as letter, i}
|
|
<span
|
|
class="letter {currentAnimation}"
|
|
style="--delay: {i * 60}ms; --color: {colorValues[
|
|
currentColor
|
|
]}"
|
|
>
|
|
{letter}
|
|
</span>
|
|
{/each}
|
|
</div>
|
|
<p class="loading-subtitle">Transforming your text...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.modal-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(255, 255, 255, 0.85);
|
|
backdrop-filter: blur(8px);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 1000;
|
|
animation: fade-in 0.2s ease-out;
|
|
}
|
|
|
|
.modal-content {
|
|
text-align: center;
|
|
padding: 3rem;
|
|
}
|
|
|
|
.loading-letters {
|
|
font-size: clamp(2rem, 5vw, 3.5rem);
|
|
font-weight: 700;
|
|
letter-spacing: 0.05em;
|
|
min-height: 4rem;
|
|
display: flex;
|
|
justify-content: center;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.letter {
|
|
display: inline-block;
|
|
opacity: 0;
|
|
animation-fill-mode: forwards;
|
|
animation-duration: 0.4s;
|
|
animation-delay: var(--delay);
|
|
}
|
|
|
|
/* Slide up */
|
|
.slide-up {
|
|
animation-name: slide-up;
|
|
}
|
|
|
|
@keyframes slide-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(30px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Bounce in */
|
|
.bounce-in {
|
|
animation-name: bounce-in;
|
|
}
|
|
|
|
@keyframes bounce-in {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(-40px);
|
|
}
|
|
60% {
|
|
opacity: 1;
|
|
transform: translateY(8px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Drop in */
|
|
.drop-in {
|
|
animation-name: drop-in;
|
|
}
|
|
|
|
@keyframes drop-in {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(-60px);
|
|
}
|
|
70% {
|
|
opacity: 1;
|
|
transform: translateY(4px);
|
|
}
|
|
85% {
|
|
transform: translateY(-2px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
/* Scale up */
|
|
.scale-up {
|
|
animation-name: scale-up;
|
|
}
|
|
|
|
@keyframes scale-up {
|
|
from {
|
|
opacity: 0;
|
|
transform: scale(0.3);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
|
|
/* Fade rotate */
|
|
.fade-rotate {
|
|
animation-name: fade-rotate;
|
|
}
|
|
|
|
@keyframes fade-rotate {
|
|
from {
|
|
opacity: 0;
|
|
transform: rotate(-15deg) scale(0.5);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: rotate(0deg) scale(1);
|
|
}
|
|
}
|
|
|
|
/* Spring from left */
|
|
.spring-left {
|
|
animation-name: spring-left;
|
|
}
|
|
|
|
@keyframes spring-left {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateX(-40px);
|
|
}
|
|
70% {
|
|
opacity: 1;
|
|
transform: translateX(5px);
|
|
}
|
|
100% {
|
|
opacity: 1;
|
|
transform: translateX(0);
|
|
}
|
|
}
|
|
|
|
.loading-subtitle {
|
|
margin-top: 1rem;
|
|
color: #6b7280;
|
|
font-size: 1rem;
|
|
font-weight: 400;
|
|
}
|
|
|
|
@keyframes fade-in {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
</style>
|