GLM-5.2-etheroi / index.html
akhaliq's picture
akhaliq HF Staff
feat: switch GLM-5.2 provider to fireworks-ai
51c51fa
Raw
History Blame Contribute Delete
54.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GLM 5.2</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600&family=Inter:wght@300;400;500;600;700&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<!-- Markdown Parser -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
:root {
/* Clean Minimalist Light Mode (Screenshot Aesthetics) */
--bg-color: #ffffff;
--sidebar-bg: #ffffff;
--sidebar-border: rgba(0, 0, 0, 0.06);
--sidebar-icon-color: #71717a;
--sidebar-icon-hover: #18181b;
--sidebar-active-bg: #f4f4f5;
--text-color: #09090b;
--text-muted: #71717a;
--text-terminal: #27272a;
--input-bg: #ffffff;
--input-border: rgba(0, 0, 0, 0.08);
--input-shadow: 0 4px 20px rgba(0, 0, 0, 0.03), 0 10px 40px -10px rgba(0, 0, 0, 0.05);
--btn-active-bg: #18181b;
--btn-active-color: #ffffff;
--btn-disabled-bg: #f4f4f5;
--btn-disabled-color: #a1a1aa;
--font-serif: 'Playfair Display', serif;
--font-sans: 'Outfit', 'Inter', sans-serif;
--font-mono: 'Fira Code', monospace;
--msg-user-bg: transparent;
--msg-assistant-bg: transparent;
--code-bg: #18181b;
--code-color: #f4f4f5;
--accent-color: #18181b;
--accent-bg: #f4f4f5;
--watermark-color: rgba(0, 0, 0, 0.02);
--capsule-bg: #f4f4f5;
--capsule-text: #27272a;
--capsule-border: rgba(0, 0, 0, 0.04);
--cursor-color: #18181b;
}
/* Dark Modern Mode */
.dark-mode {
--bg-color: #09090b;
--sidebar-bg: #09090b;
--sidebar-border: rgba(255, 255, 255, 0.06);
--sidebar-icon-color: #a1a1aa;
--sidebar-icon-hover: #ffffff;
--sidebar-active-bg: #27272a;
--text-color: #f4f4f5;
--text-muted: #a1a1aa;
--text-terminal: #e4e4e7;
--input-bg: #09090b;
--input-border: rgba(255, 255, 255, 0.08);
--input-shadow: 0 4px 25px rgba(0, 0, 0, 0.4);
--btn-active-bg: #ffffff;
--btn-active-color: #09090b;
--btn-disabled-bg: #27272a;
--btn-disabled-color: #71717a;
--code-bg: #27272a;
--code-color: #f4f4f5;
--accent-color: #ffffff;
--accent-bg: #27272a;
--watermark-color: rgba(255, 255, 255, 0.015);
--capsule-bg: #27272a;
--capsule-text: #e4e4e7;
--capsule-border: rgba(255, 255, 255, 0.04);
--cursor-color: #ffffff;
}
/* Classic Retro Hacker Terminal Theme */
.classic-terminal-mode {
--bg-color: #050806;
--sidebar-bg: #020403;
--sidebar-border: rgba(51, 255, 51, 0.15);
--sidebar-icon-color: rgba(51, 255, 51, 0.6);
--sidebar-icon-hover: #33ff33;
--sidebar-active-bg: rgba(51, 255, 51, 0.1);
--text-color: #33ff33;
--text-muted: rgba(51, 255, 51, 0.6);
--text-terminal: #33ff33;
--input-bg: #020403;
--input-border: rgba(51, 255, 51, 0.3);
--input-shadow: 0 0 15px rgba(51, 255, 51, 0.1);
--btn-active-bg: #33ff33;
--btn-active-color: #020403;
--btn-disabled-bg: rgba(51, 255, 51, 0.05);
--btn-disabled-color: rgba(51, 255, 51, 0.3);
--font-serif: 'Fira Code', monospace;
--font-sans: 'Fira Code', monospace;
--font-mono: 'Fira Code', monospace;
--code-bg: #020403;
--code-color: #33ff33;
--accent-color: #33ff33;
--accent-bg: rgba(51, 255, 51, 0.08);
--watermark-color: rgba(51, 255, 51, 0.02);
--capsule-bg: rgba(51, 255, 51, 0.05);
--capsule-text: #33ff33;
--capsule-border: rgba(51, 255, 51, 0.2);
--cursor-color: #33ff33;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
transition: background-color 0.25s ease, border-color 0.25s ease, color 0.15s ease;
}
body, html {
height: 100%;
width: 100%;
font-family: var(--font-sans);
background-color: var(--bg-color);
color: var(--text-color);
overflow: hidden;
display: flex;
}
/* Sidebar Styling (Matches Screenshot Layout) */
.sidebar {
width: 72px;
height: 100%;
background-color: var(--sidebar-bg);
border-right: 1px solid var(--sidebar-border);
display: flex;
flex-direction: column;
align-items: center;
padding: 16px 0;
justify-content: space-between;
z-index: 10;
}
.sidebar-top {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
width: 100%;
}
.sidebar-bottom {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
width: 100%;
}
.sidebar-btn {
width: 44px;
height: 44px;
border-radius: 8px;
border: 1px solid transparent;
background: transparent;
color: var(--sidebar-icon-color);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
position: relative;
}
.sidebar-btn:hover {
color: var(--sidebar-icon-hover);
background-color: var(--sidebar-active-bg);
}
.sidebar-btn.active {
background-color: var(--sidebar-active-bg);
color: var(--sidebar-icon-hover);
border-color: var(--sidebar-border);
}
/* Top Brand Button (Boxed Z Logo) */
.brand-btn {
width: 44px;
height: 44px;
border-radius: 8px;
background-color: var(--bg-color);
border: 1px solid var(--sidebar-border);
color: var(--text-color);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-weight: 700;
font-family: var(--font-sans);
font-size: 18px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.02);
}
.brand-btn:hover {
background-color: var(--sidebar-active-bg);
}
/* Tooltip */
.sidebar-btn::after {
content: attr(data-tooltip);
position: absolute;
left: 80px;
background: #18181b;
color: #ffffff;
padding: 4px 8px;
border-radius: 4px;
font-size: 11px;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease, transform 0.2s ease;
transform: translateX(-10px);
z-index: 100;
font-family: var(--font-sans);
}
.sidebar-btn:hover::after {
opacity: 1;
transform: translateX(0);
}
/* Main Workspace */
.workspace {
flex: 1;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
}
/* Watermark Background Z */
.watermark-container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 450px;
height: 450px;
pointer-events: none;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
}
.watermark-svg {
width: 100%;
height: 100%;
stroke: var(--watermark-color);
fill: none;
stroke-width: 0.8;
stroke-linecap: round;
stroke-linejoin: round;
}
/* Welcome Center State */
.welcome-panel {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
z-index: 2;
padding: 32px;
user-select: none;
}
.welcome-title {
font-family: var(--font-serif);
font-size: 48px;
font-weight: 400;
margin-bottom: 16px;
color: var(--text-color);
letter-spacing: -0.5px;
animation: fadeInUp 0.8s ease;
}
.welcome-subtitle {
font-family: var(--font-sans);
font-size: 16px;
color: var(--text-muted);
font-weight: 400;
letter-spacing: 0.1px;
animation: fadeInUp 0.8s ease 0.1s both;
}
/* Chat Terminal Console Output */
.chat-container {
flex: 1;
overflow-y: auto;
padding: 40px 10%;
display: none;
flex-direction: column;
gap: 24px;
z-index: 2;
scroll-behavior: smooth;
}
.chat-container.terminal-layout {
background-size: 20px 20px;
background-image:
linear-gradient(to right, rgba(0, 0, 0, 0.01) 1px, transparent 1px),
linear-gradient(to bottom, rgba(0, 0, 0, 0.01) 1px, transparent 1px);
}
.dark-mode .chat-container.terminal-layout {
background-image:
linear-gradient(to right, rgba(255, 255, 255, 0.005) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.005) 1px, transparent 1px);
}
.classic-terminal-mode .chat-container.terminal-layout {
background-image:
linear-gradient(to right, rgba(51, 255, 51, 0.015) 1px, transparent 1px),
linear-gradient(to bottom, rgba(51, 255, 51, 0.015) 1px, transparent 1px);
}
.message-row {
display: flex;
flex-direction: column;
width: 100%;
animation: fadeIn 0.3s ease-out;
line-height: 1.6;
}
/* Terminal Prompt Headers */
.prompt-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
user-select: none;
}
.prompt-prefix-user {
color: #3b82f6; /* Modern Blue */
font-weight: 600;
}
.classic-terminal-mode .prompt-prefix-user {
color: #33ff33;
}
.prompt-prefix-system {
color: #10b981; /* Modern Green */
font-weight: 600;
}
.classic-terminal-mode .prompt-prefix-system {
color: #33ff33;
}
.prompt-command {
color: var(--text-muted);
font-size: 12px;
}
.prompt-text {
color: var(--text-color);
white-space: pre-wrap;
word-break: break-word;
padding-left: 4px;
}
.message-content {
padding-left: 16px;
border-left: 2px solid var(--sidebar-border);
color: var(--text-terminal);
margin-top: 4px;
word-break: break-word;
}
.message-content p {
margin-bottom: 12px;
}
.message-content p:last-child {
margin-bottom: 0;
}
/* Code Block Styling */
.message-content pre {
background-color: var(--code-bg);
color: var(--code-color);
padding: 14px;
border-radius: 8px;
overflow-x: auto;
margin: 12px 0;
border: 1px solid var(--sidebar-border);
position: relative;
}
.message-content code {
font-family: var(--font-mono);
font-size: 13px;
}
/* Floating Message Input Panel (Matches GLM-5.2 Layout) */
.input-panel {
width: 100%;
max-width: 800px;
margin: 0 auto 32px auto;
padding: 0 24px;
z-index: 5;
}
.input-container {
background-color: var(--input-bg);
border: 1px solid var(--input-border);
border-radius: 16px;
padding: 16px 20px;
box-shadow: var(--input-shadow);
display: flex;
flex-direction: column;
gap: 12px;
}
.textarea-wrapper {
width: 100%;
}
.chat-input {
width: 100%;
border: none;
outline: none;
background: transparent;
color: var(--text-color);
font-family: var(--font-sans);
font-size: 16px;
resize: none;
max-height: 200px;
height: 24px;
line-height: 1.5;
}
.chat-input::placeholder {
color: var(--text-muted);
opacity: 0.8;
}
/* Input Controls Panel */
.input-controls {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.controls-left {
display: flex;
align-items: center;
gap: 12px;
}
.action-circle-btn {
width: 32px;
height: 32px;
border-radius: 50%;
border: 1px solid var(--input-border);
background: transparent;
color: var(--text-color);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.action-circle-btn:hover {
background-color: var(--sidebar-active-bg);
}
/* Capsule Agent Button (Screenshot style) */
.agent-capsule {
display: flex;
align-items: center;
gap: 6px;
background-color: var(--capsule-bg);
border: 1px solid var(--capsule-border);
color: var(--capsule-text);
padding: 6px 14px;
border-radius: 20px;
font-family: var(--font-sans);
font-size: 13px;
font-weight: 500;
cursor: pointer;
user-select: none;
border: 1px solid var(--sidebar-border);
}
.agent-capsule:hover {
background-color: var(--sidebar-active-bg);
filter: brightness(0.95);
}
.agent-capsule svg {
color: var(--text-muted);
}
/* Send Circular Button (Screenshot style) */
.send-btn {
width: 32px;
height: 32px;
border-radius: 50%;
border: none;
background-color: var(--btn-disabled-bg);
color: var(--btn-disabled-color);
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s ease;
}
.send-btn.active {
background-color: var(--btn-active-bg);
color: var(--btn-active-color);
}
.send-btn svg {
width: 16px;
height: 16px;
}
/* Blinking Terminal Cursor */
.terminal-cursor {
display: inline-block;
width: 8px;
height: 15px;
background-color: var(--cursor-color);
margin-left: 4px;
animation: blink 0.8s infinite;
vertical-align: middle;
}
/* Settings Drawer overlay */
.settings-drawer {
position: absolute;
left: 73px;
top: 0;
bottom: 0;
width: 320px;
background-color: var(--sidebar-bg);
border-right: 1px solid var(--sidebar-border);
z-index: 9;
box-shadow: 10px 0 30px rgba(0,0,0,0.02);
padding: 24px;
display: flex;
flex-direction: column;
gap: 20px;
transform: translateX(-105%);
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
.settings-drawer.open {
transform: translateX(0);
}
.settings-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.settings-title {
font-size: 18px;
font-weight: 600;
}
.close-drawer-btn {
background: transparent;
border: none;
color: var(--text-muted);
cursor: pointer;
}
.close-drawer-btn:hover {
color: var(--text-color);
}
.settings-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.settings-label {
font-size: 13px;
font-weight: 500;
color: var(--text-muted);
}
.settings-input, .settings-select {
width: 100%;
background-color: var(--input-bg);
border: 1px solid var(--sidebar-border);
padding: 10px 12px;
border-radius: 8px;
color: var(--text-color);
font-family: var(--font-sans);
font-size: 14px;
outline: none;
}
.settings-input:focus, .settings-select:focus {
border-color: var(--text-color);
}
/* CLI Info Alert */
.cli-info-banner {
background-color: var(--accent-bg);
color: var(--text-color);
border: 1px solid var(--sidebar-border);
border-radius: 8px;
padding: 12px;
font-size: 12px;
line-height: 1.5;
font-family: var(--font-mono);
}
/* Matrix Canvas */
#matrix-canvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 0;
opacity: 0.12;
display: none;
}
/* Animations */
@keyframes blink {
0%, 49% { opacity: 1; }
50%, 100% { opacity: 0; }
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* Scrollbar styling */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--sidebar-border);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--text-muted);
}
/* System notification log */
.system-log {
color: #eab308;
font-style: italic;
}
.classic-terminal-mode .system-log {
color: #ffb000;
}
/* Welcoming terminal dashboard box */
.welcome-terminal-box {
background-color: var(--input-bg);
border: 1px solid var(--input-border);
border-radius: 12px;
width: 100%;
max-width: 480px;
box-shadow: var(--input-shadow);
text-align: left;
margin: 20px 0;
overflow: hidden;
animation: fadeInUp 0.8s ease 0.2s both;
}
.welcome-terminal-header {
background-color: var(--sidebar-bg);
border-bottom: 1px solid var(--sidebar-border);
padding: 10px 16px;
display: flex;
align-items: center;
gap: 6px;
}
.terminal-dot {
width: 8px;
height: 8px;
border-radius: 50%;
display: inline-block;
}
.terminal-dot.red { background-color: #ef4444; }
.terminal-dot.yellow { background-color: #f59e0b; }
.terminal-dot.green { background-color: #10b981; }
.terminal-title {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
margin-left: 8px;
flex-grow: 1;
text-align: center;
margin-right: 30px;
}
.welcome-terminal-content {
padding: 16px 20px;
margin: 0;
overflow: auto;
}
.welcome-terminal-content code {
font-family: var(--font-mono);
font-size: 13px;
color: var(--text-terminal);
line-height: 1.6;
}
/* Chat Status Bar styles */
.chat-status-bar {
background-color: var(--sidebar-bg);
border-bottom: 1px solid var(--sidebar-border);
padding: 10px 24px;
font-size: 12px;
display: none;
align-items: center;
justify-content: space-between;
color: var(--text-muted);
z-index: 3;
user-select: none;
}
.chat-status-bar .status-item {
display: flex;
align-items: center;
gap: 6px;
}
.chat-status-bar .status-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background-color: #10b981;
}
/* Message styling variations based on Mode */
.message-row.style-standard {
font-family: var(--font-sans);
font-size: 15px;
line-height: 1.6;
}
.message-row.style-standard .prompt-header {
margin-bottom: 6px;
}
.message-row.style-standard .standard-sender-user {
font-weight: 600;
font-size: 13px;
color: var(--text-color);
background-color: var(--sidebar-active-bg);
padding: 2px 8px;
border-radius: 4px;
}
.message-row.style-standard .standard-sender-system {
font-weight: 600;
font-size: 13px;
color: var(--text-color);
}
.message-row.style-standard .prompt-text {
padding-left: 0;
color: var(--text-color);
font-size: 15px;
}
.message-row.style-standard .message-content {
padding-left: 0;
border-left: none;
color: var(--text-color);
font-size: 15px;
}
.message-row.style-standard .message-content p {
margin-bottom: 12px;
}
/* Standard Mode code blocks styling */
.message-row.style-standard .message-content pre {
background-color: var(--capsule-bg);
color: var(--text-color);
border: 1px solid var(--sidebar-border);
}
.message-row.style-standard .message-content code {
color: inherit;
}
.message-row.style-terminal {
font-family: var(--font-mono);
font-size: 14px;
line-height: 1.6;
}
</style>
</head>
<body>
<!-- Matrix Code Rain Canvas -->
<canvas id="matrix-canvas"></canvas>
<!-- Left Sidebar (Screenshots structure) -->
<nav class="sidebar">
<div class="sidebar-top">
<!-- Brand GLM Logo (Minimalist Boxed Header) -->
<button class="brand-btn" id="home-brand-btn" onclick="goToHome()" title="GLM 5.2 Workspace" style="font-size: 11px; font-weight: 800; letter-spacing: -0.5px;">GLM</button>
<button class="sidebar-btn" id="new-chat-btn" onclick="clearSession()" data-tooltip="New Workspace Chat">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"/>
<path d="M18.5 2.5a2.121 2.121 0 1 1 3 3L12 15l-4 1 1-4 9.5-9.5z"/>
</svg>
</button>
</div>
<div class="sidebar-bottom">
<!-- Theme Toggler (Sun/Moon/Retro CLI Terminal) -->
<button class="sidebar-btn" id="theme-btn" onclick="cycleTheme()" data-tooltip="Cycle Theme Mode">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/>
<circle cx="12" cy="12" r="4"/>
</svg>
</button>
<!-- Configuration / Settings Cog -->
<button class="sidebar-btn" id="settings-btn" onclick="toggleSettings()" data-tooltip="Settings & Credentials">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="3"/>
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/>
</svg>
</button>
</div>
</nav>
<!-- Sliding Settings Drawer -->
<div class="settings-drawer" id="settings-drawer">
<div class="settings-header">
<span class="settings-title">Configuration Drawer</span>
<button class="close-drawer-btn" onclick="toggleSettings()">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"/>
<line x1="6" y1="6" x2="18" y2="18"/>
</svg>
</button>
</div>
<div class="settings-group">
<label class="settings-label" for="temperature-input">Temperature (Creativity)</label>
<input type="range" id="temperature-input" min="0.1" max="1.5" step="0.1" value="0.7" oninput="document.getElementById('temp-val').innerText = this.value; saveConfig()">
<span id="temp-val" style="font-size:12px; margin-top:2px;">0.7</span>
</div>
<div class="settings-group">
<label class="settings-label" for="system-input">System Instruction / Agent Prompt</label>
<textarea id="system-input" class="settings-input" rows="4" placeholder="You are a helpful assistant..." onchange="saveConfig()"></textarea>
</div>
<div class="cli-info-banner">
<strong>Terminal Mode Info:</strong><br>
You can type commands directly in the chat bar!<br>
<code>/clear</code>: Reset chat<br>
<code>/theme</code>: Cycle styles<br>
<code>/help</code>: Display CLI manual<br>
<code>/matrix</code>: Toggle digital rain
</div>
</div>
<!-- Main Pane -->
<div class="workspace">
<!-- SVG Watermark Background 5.2 (Double Stencil Outline) -->
<div class="watermark-container">
<svg class="watermark-svg" viewBox="0 0 100 100">
<path d="M 30,25 H 70 V 48 H 30 V 75 H 70" />
<path d="M 35,30 H 65 V 43 H 35 V 70 H 65" stroke-dasharray="2, 2" />
</svg>
</div>
<!-- Welcome Initial Panel -->
<div class="welcome-panel" id="welcome-panel">
<h1 class="welcome-title">GLM 5.2</h1>
<p class="welcome-subtitle" style="font-family: var(--font-serif); font-size: 24px; margin-bottom: 12px;">Create anything you can imagine</p>
<!-- Sleek terminal status dashboard inside welcome screen -->
<div class="welcome-terminal-box">
<div class="welcome-terminal-header">
<span class="terminal-dot red"></span>
<span class="terminal-dot yellow"></span>
<span class="terminal-dot green"></span>
<span class="terminal-title">visitor@glm5.2: ~</span>
</div>
<pre class="welcome-terminal-content"><code>system_boot_sequence: SUCCESS
model_identity : zai-org/GLM-5.2:fireworks-ai
connection_state : ONLINE
stream_completions : ACTIVE
Type a query or /help to interact with GLM 5.2...</code></pre>
</div>
<p class="welcome-subtext" style="font-size: 13px; color: var(--text-muted); margin-top: 8px;">Interact with GLM 5.2 and explore the boundless creative world</p>
</div>
<!-- Chat Status Bar -->
<div class="chat-status-bar" id="chat-status-bar">
<span class="status-item"><span class="status-dot"></span> GLM 5.2 CLI Session</span>
<span class="status-item font-mono" style="font-family: var(--font-mono)">Model: zai-org/GLM-5.2:fireworks-ai</span>
<span class="status-item" id="status-agent-mode">Mode: Standard</span>
</div>
<!-- Chat Logs Console -->
<div class="chat-container" id="chat-container"></div>
<!-- Input Bar (Matches Floating GLM-5.2 Layout) -->
<div class="input-panel">
<div class="input-container">
<div class="textarea-wrapper">
<textarea
id="chat-input"
class="chat-input"
placeholder="Send a Message"
rows="1"
oninput="adjustInputHeight(this); checkInputLength(this)"
onkeydown="handleKeyPress(event)"
></textarea>
</div>
<div class="input-controls">
<div class="controls-left">
<!-- Agent pill button (Standard / Terminal toggle) -->
<div class="agent-capsule" id="agent-capsule" onclick="toggleAgentMode()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<polyline points="4 17 10 11 4 5"/>
<line x1="12" y1="19" x2="20" y2="19"/>
</svg>
<span id="agent-pill-label">Standard Mode</span>
</div>
</div>
<!-- Send Up-Arrow Button -->
<button class="send-btn" id="send-btn" onclick="submitChat()" disabled>
<!-- Rounded arrow up -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="19" x2="12" y2="5"/>
<polyline points="5 12 12 5 19 12"/>
</svg>
</button>
</div>
</div>
</div>
</div>
<!-- Scripting and logic -->
<script>
// State variables
let chatHistory = []; // Local memory of session conversation
let activeAgentMode = 'standard'; // standard, terminal
let currentTheme = 'light'; // light, dark, classic-terminal
let matrixInterval = null; // Digital rain interval reference
// On Page Load: Hydrate settings from local storage
window.addEventListener('DOMContentLoaded', () => {
const savedTemp = localStorage.getItem('temp');
if (savedTemp) {
document.getElementById('temperature-input').value = savedTemp;
document.getElementById('temp-val').innerText = savedTemp;
}
const savedSystem = localStorage.getItem('system_prompt');
if (savedSystem) {
document.getElementById('system-input').value = savedSystem;
}
const savedTheme = localStorage.getItem('theme');
if (savedTheme) {
applyTheme(savedTheme);
}
});
// Config Drawer toggles
function toggleSettings() {
const drawer = document.getElementById('settings-drawer');
drawer.classList.toggle('open');
}
function saveConfig() {
const temp = document.getElementById('temperature-input').value;
const system = document.getElementById('system-input').value.trim();
localStorage.setItem('temp', temp);
localStorage.setItem('system_prompt', system);
}
// Navigation back home
function goToHome() {
document.getElementById('welcome-panel').style.display = 'flex';
document.getElementById('chat-container').style.display = 'none';
document.getElementById('chat-status-bar').style.display = 'none';
}
// Clear Workspace History
function clearSession() {
chatHistory = [];
const container = document.getElementById('chat-container');
container.innerHTML = '';
// Log local terminal reset
appendLocalLog("Session reset. Terminal memory buffer cleared.");
goToHome();
}
// Append locally printed logs (for CLI actions)
function appendLocalLog(text) {
const container = document.getElementById('chat-container');
// Check if welcome panel is visible, hide it
if (document.getElementById('welcome-panel').style.display !== 'none') {
document.getElementById('welcome-panel').style.display = 'none';
container.style.display = 'flex';
document.getElementById('chat-status-bar').style.display = 'flex';
}
const logRow = document.createElement('div');
logRow.className = 'message-row';
logRow.innerHTML = `
<div class="prompt-header">
<span class="prompt-prefix-system">system@glm5.2:~$</span>
<span class="prompt-command">info</span>
</div>
<div class="prompt-text system-log">${text}</div>
`;
container.appendChild(logRow);
container.scrollTop = container.scrollHeight;
}
// Adjusts input textarea height depending on characters typed
function adjustInputHeight(textarea) {
textarea.style.height = 'auto';
textarea.style.height = (textarea.scrollHeight) + 'px';
}
// Toggles the send button color and activity state based on input presence
function checkInputLength(textarea) {
const sendBtn = document.getElementById('send-btn');
if (textarea.value.trim().length > 0) {
sendBtn.classList.add('active');
sendBtn.disabled = false;
} else {
sendBtn.classList.remove('active');
sendBtn.disabled = true;
}
}
// Key Press handling: Shift+Enter inserts newline, Enter submits
function handleKeyPress(event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
submitChat();
}
}
// Toggles theme through cycle: Light -> Dark -> Retro CLI Terminal
function cycleTheme() {
if (currentTheme === 'light') {
applyTheme('dark');
} else if (currentTheme === 'dark') {
applyTheme('classic-terminal');
} else {
applyTheme('light');
}
}
function applyTheme(themeName) {
document.body.classList.remove('dark-mode', 'classic-terminal-mode');
const matrixCanvas = document.getElementById('matrix-canvas');
// Stop matrix loop unless in classic-terminal-mode
if (matrixInterval) {
clearInterval(matrixInterval);
matrixInterval = null;
}
matrixCanvas.style.display = 'none';
if (themeName === 'dark') {
document.body.classList.add('dark-mode');
currentTheme = 'dark';
} else if (themeName === 'classic-terminal') {
document.body.classList.add('classic-terminal-mode');
currentTheme = 'classic-terminal';
initMatrixRain();
} else {
currentTheme = 'light';
}
localStorage.setItem('theme', currentTheme);
}
// Toggle Agents (Terminal mode or Standard chat mode)
function toggleAgentMode() {
const pillLabel = document.getElementById('agent-pill-label');
const systemTextarea = document.getElementById('system-input');
const chatContainer = document.getElementById('chat-container');
if (activeAgentMode === 'standard') {
activeAgentMode = 'terminal';
pillLabel.innerText = "Terminal Mode";
systemTextarea.value = "You are a senior system administrator and Unix terminal helper. Answer requests using command-line commands, scripts, code configurations, and wrap instructions in monospaced outputs.";
appendLocalLog("Agent profile set to: Unix Terminal CLI assistant.");
chatContainer.classList.add('terminal-layout');
} else {
activeAgentMode = 'standard';
pillLabel.innerText = "Standard Mode";
systemTextarea.value = "";
appendLocalLog("Agent profile restored to: default general assistant.");
chatContainer.classList.remove('terminal-layout');
}
const statusAgentLabel = document.getElementById('status-agent-mode');
if (statusAgentLabel) {
statusAgentLabel.innerText = "Mode: " + (activeAgentMode === 'standard' ? 'Standard' : 'Terminal');
}
const statusBar = document.getElementById('chat-status-bar');
if (statusBar) {
statusBar.style.display = (activeAgentMode === 'terminal' && chatContainer.style.display === 'flex') ? 'flex' : 'none';
}
saveConfig();
}
// Handle slash command local executes
function handleSlashCommand(commandStr) {
const container = document.getElementById('chat-container');
const cmd = commandStr.trim();
// Append user prompt action to screen
const promptRow = document.createElement('div');
promptRow.className = 'message-row';
promptRow.innerHTML = `
<div class="prompt-header">
<span class="prompt-prefix-user">visitor@glm5.2:~$</span>
<span class="prompt-command">run</span>
</div>
<div class="prompt-text">${cmd}</div>
`;
container.appendChild(promptRow);
if (cmd === '/clear') {
clearSession();
return;
}
// Create response layout for command output
const respRow = document.createElement('div');
respRow.className = 'message-row';
let outputText = '';
if (cmd.startsWith('/help')) {
outputText = `
<strong>GLM-5.2 CLI SYSTEM MANUAL</strong>
----------------------------------------
Here is a list of available command line functions:
• <code>/help</code> - Prints this helper instruction table.
• <code>/clear</code> - Resets active session logs and moves to welcome home panel.
• <code>/theme</code> - Alternates theme context (Light -> Dark -> Classic green terminal).
• <code>/matrix</code> - Toggles background matrix digital rain canvas.
• <code>/system [prompt]</code> - Updates assistant's instruction context in config dynamically.
----------------------------------------
`;
} else if (cmd.startsWith('/theme')) {
cycleTheme();
outputText = `Theme toggled to: <strong>${currentTheme.toUpperCase()}</strong>`;
} else if (cmd.startsWith('/matrix')) {
const canvas = document.getElementById('matrix-canvas');
if (canvas.style.display === 'block') {
canvas.style.display = 'none';
if (matrixInterval) clearInterval(matrixInterval);
matrixInterval = null;
outputText = "Digital matrix rain canvas disabled.";
} else {
canvas.style.display = 'block';
initMatrixRain();
outputText = "Digital matrix rain canvas enabled.";
}
} else if (cmd.startsWith('/system ')) {
const sysText = cmd.substring(8);
document.getElementById('system-input').value = sysText;
saveConfig();
outputText = `System prompt set to: <em>"${sysText}"</em>`;
} else {
outputText = `Unknown system command: <code>${cmd}</code>. Type <code>/help</code> for list of available CLI commands.`;
}
respRow.innerHTML = `
<div class="prompt-header">
<span class="prompt-prefix-system">system@glm5.2:~$</span>
<span class="prompt-command">stdout</span>
</div>
<div class="message-content">${outputText}</div>
`;
container.appendChild(respRow);
container.scrollTop = container.scrollHeight;
}
// Submits user message to the API endpoint and streams the output
async function submitChat() {
const inputField = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-btn');
const welcomePanel = document.getElementById('welcome-panel');
const chatContainer = document.getElementById('chat-container');
const text = inputField.value.trim();
if (!text) return;
// Reset Input field
inputField.value = '';
inputField.style.height = 'auto';
sendBtn.classList.remove('active');
sendBtn.disabled = true;
// Check if user is typing a local command
if (text.startsWith('/')) {
// Check if welcome page is visible
if (welcomePanel.style.display !== 'none') {
welcomePanel.style.display = 'none';
chatContainer.style.display = 'flex';
if (activeAgentMode === 'terminal') {
document.getElementById('chat-status-bar').style.display = 'flex';
}
}
handleSlashCommand(text);
return;
}
// Clean UI welcome state
if (welcomePanel.style.display !== 'none') {
welcomePanel.style.display = 'none';
chatContainer.style.display = 'flex';
if (activeAgentMode === 'terminal') {
document.getElementById('chat-status-bar').style.display = 'flex';
}
}
// Append User message row
const userRow = document.createElement('div');
userRow.className = `message-row user-row style-${activeAgentMode}`;
if (activeAgentMode === 'standard') {
userRow.innerHTML = `
<div class="prompt-header">
<span class="standard-sender-user">You</span>
</div>
<div class="prompt-text">${escapeHtml(text)}</div>
`;
} else {
userRow.innerHTML = `
<div class="prompt-header">
<span class="prompt-prefix-user">visitor@glm5.2:~$</span>
<span class="prompt-command">prompt</span>
</div>
<div class="prompt-text">${escapeHtml(text)}</div>
`;
}
chatContainer.appendChild(userRow);
chatContainer.scrollTop = chatContainer.scrollHeight;
// Save user prompt to conversation history list
chatHistory.push({ role: 'user', content: text });
// Create Assistant loading stream container
const streamId = 'stream-' + Date.now();
const assistantRow = document.createElement('div');
assistantRow.className = `message-row assistant-row style-${activeAgentMode}`;
if (activeAgentMode === 'standard') {
assistantRow.innerHTML = `
<div class="prompt-header">
<span class="standard-sender-system">GLM 5.2</span>
</div>
<div class="message-content" id="${streamId}">
<span class="standard-loader">typing...</span>
</div>
`;
} else {
assistantRow.innerHTML = `
<div class="prompt-header">
<span class="prompt-prefix-system">system@glm5.2:~$</span>
<span class="prompt-command">./run_glm_5.2_agent</span>
</div>
<div class="message-content" id="${streamId}">
<span class="terminal-cursor"></span>
</div>
`;
}
chatContainer.appendChild(assistantRow);
chatContainer.scrollTop = chatContainer.scrollHeight;
const streamContainer = document.getElementById(streamId);
// Construct full payload messages list incorporating custom system instruction
const apiMessages = [];
const systemPrompt = document.getElementById('system-input').value.trim();
if (systemPrompt) {
apiMessages.push({ role: 'system', content: systemPrompt });
}
apiMessages.push(...chatHistory);
const selectedModel = "zai-org/GLM-5.2:fireworks-ai";
const temperatureVal = parseFloat(document.getElementById('temperature-input').value);
try {
const response = await fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
messages: apiMessages,
model: selectedModel,
temperature: temperatureVal
})
});
if (!response.ok) {
throw new Error(`Connection failure: Status ${response.status}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let streamedOutput = "";
let buffer = "";
while (true) {
const { value, done } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split('\n');
// Retain trailing partial line in buffer
buffer = lines.pop();
for (const line of lines) {
const cleanLine = line.trim();
if (!cleanLine) continue;
if (cleanLine.startsWith('data: ')) {
const dataStr = cleanLine.substring(6);
if (dataStr === '[DONE]') {
break;
}
try {
const payload = JSON.parse(dataStr);
if (payload.error) {
streamedOutput += `\n\n**API Output Exception:** ${payload.error}`;
} else if (payload.content) {
streamedOutput += payload.content;
}
// Update current rendering block with Markdown parse and flashing cursor indicator
if (activeAgentMode === 'terminal') {
streamContainer.innerHTML = marked.parse(streamedOutput) + '<span class="terminal-cursor"></span>';
} else {
streamContainer.innerHTML = marked.parse(streamedOutput);
}
chatContainer.scrollTop = chatContainer.scrollHeight;
} catch (err) {
console.error('Failed to unpack payload chunk:', cleanLine, err);
}
}
}
}
// Finalize streaming output remove indicator cursor
streamContainer.innerHTML = marked.parse(streamedOutput);
// Store assistant output to local chat history memory
chatHistory.push({ role: 'assistant', content: streamedOutput });
chatContainer.scrollTop = chatContainer.scrollHeight;
} catch (err) {
streamContainer.innerHTML = `<span style="color:#ef4444;">Operation failed: ${err.message}</span>`;
console.error(err);
}
}
// Helper to prevent tag insertions in text content
function escapeHtml(text) {
return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
// Digital Code Rain Matrix Animation
function initMatrixRain() {
const canvas = document.getElementById('matrix-canvas');
const ctx = canvas.getContext('2d');
canvas.style.display = 'block';
// Resize canvas to cover viewport
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
// Matrix character list
const matrixChars = "01010101XYZGLM52SYSTEMCLIWORKSPACECONNECT";
const fontArr = matrixChars.split("");
const fontSize = 14;
const columns = canvas.width / fontSize;
// Track drop positions vertically
const drops = [];
for (let x = 0; x < columns; x++) {
drops[x] = 1;
}
function drawMatrix() {
// Set light/dark overlay blending depending on theme
ctx.fillStyle = currentTheme === 'classic-terminal' ? 'rgba(5, 8, 6, 0.04)' : 'rgba(9, 9, 11, 0.04)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Set green text
ctx.fillStyle = currentTheme === 'classic-terminal' ? '#33ff33' : '#a1a1aa';
ctx.font = fontSize + "px monospace";
for (let i = 0; i < drops.length; i++) {
const text = fontArr[Math.floor(Math.random() * fontArr.length)];
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
// Reset drop when hitting screen bottom boundary
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) {
drops[i] = 0;
}
drops[i]++;
}
}
if (matrixInterval) clearInterval(matrixInterval);
matrixInterval = setInterval(drawMatrix, 35);
}
</script>
</body>
</html>