Clean up mock Vibe UI
This commit is contained in:
parent
7c1deca8ae
commit
afb13cb397
14 changed files with 3138 additions and 1336 deletions
40
html3.html
40
html3.html
|
|
@ -70,20 +70,20 @@
|
|||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="h-screen w-screen overflow-hidden flex flex-col bg-white text-gray-800 font-sans selection:bg-brand-200">
|
||||
<body class="h-screen w-screen overflow-hidden flex flex-col bg-[var(--bg,#ffffff)] text-[var(--text,#1f2937)] font-sans selection:bg-brand-200">
|
||||
|
||||
<div class="flex-1 flex overflow-hidden relative">
|
||||
|
||||
<!-- LEFT SIDEBAR -->
|
||||
<aside class="w-14 shrink-0 bg-white border-r border-gray-100 flex flex-col items-center py-6 z-20 relative">
|
||||
<div class="flex flex-col space-y-8 text-gray-500">
|
||||
<button class="hover:text-brand-600 transition-colors"><i class="fa-solid fa-chevron-right"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-solid fa-house"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-solid fa-border-all"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-regular fa-user"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-solid fa-layer-group"></i></button>
|
||||
<button class="hover:text-brand-600 transition-colors text-xl"><i class="fa-solid fa-gear"></i></button>
|
||||
<aside class="w-14 shrink-0 bg-[var(--bg-secondary,#ffffff)] border-r border-[var(--border-color,#f3f4f6)] flex flex-col items-center py-6 z-20 relative">
|
||||
<div class="flex flex-col space-y-8 text-[var(--text-secondary,#6b7280)]">
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors"><i class="fa-solid fa-chevron-right"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-solid fa-house"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-solid fa-magnifying-glass"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-solid fa-border-all"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-regular fa-user"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-solid fa-layer-group"></i></button>
|
||||
<button class="hover:text-[var(--primary,#16a34a)] transition-colors text-xl"><i class="fa-solid fa-gear"></i></button>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
|
@ -91,29 +91,29 @@
|
|||
<main class="flex-1 flex flex-col min-w-0 relative z-10">
|
||||
|
||||
<!-- TOP NAVIGATION PATH -->
|
||||
<header class="h-12 shrink-0 bg-white border-b border-gray-100 flex items-center px-6">
|
||||
<header class="h-12 shrink-0 bg-[var(--bg,#ffffff)] border-b border-[var(--border-color,#f3f4f6)] flex items-center px-6">
|
||||
<div class="font-mono text-xs font-semibold tracking-wider flex space-x-3 items-center">
|
||||
<span class="text-gray-400">// DASHBOARD</span>
|
||||
<span class="text-gray-300">></span>
|
||||
<span class="text-gray-800">// E-COMMERCE APP DEVELOPMENT</span>
|
||||
<span class="text-[var(--text-secondary,#9ca3af)]">// DASHBOARD</span>
|
||||
<span class="text-[var(--text-muted,#d1d5db)]">></span>
|
||||
<span class="text-[var(--text,#1f2937)]">// E-COMMERCE APP DEVELOPMENT</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- STAGE NAVIGATION -->
|
||||
<nav class="h-12 shrink-0 bg-white/90 backdrop-blur-sm border-b border-gray-100 flex items-center font-mono text-xs font-semibold z-10">
|
||||
<div class="flex-1 flex justify-center border-r border-gray-100 py-3 hover:bg-gray-50 cursor-pointer text-gray-400 transition-colors">
|
||||
<nav class="h-12 shrink-0 bg-[var(--bg,#ffffff)] border-b border-[var(--border-color,#f3f4f6)] flex items-center font-mono text-xs font-semibold z-10">
|
||||
<div class="flex-1 flex justify-center border-r border-[var(--border-color,#f3f4f6)] py-3 hover:bg-[var(--bg-hover,#f9fafb)] cursor-pointer text-[var(--text-secondary,#9ca3af)] transition-colors">
|
||||
// PLAN
|
||||
</div>
|
||||
<div class="flex-1 flex justify-center border-r border-gray-100 py-3 bg-brand-50 text-brand-600 cursor-pointer border-b-2 border-b-brand-500 transition-colors shadow-[inset_0_2px_4px_rgba(34,197,94,0.05)]">
|
||||
<div class="flex-1 flex justify-center border-r border-[var(--border-color,#f3f4f6)] py-3 bg-[var(--primary-bg,#f0fdf4)] text-[var(--primary,#16a34a)] cursor-pointer border-b-2 border-b-[var(--primary,#22c55e)] transition-colors shadow-[inset_0_2px_4px_rgba(34,197,94,0.05)]">
|
||||
// BUILD
|
||||
</div>
|
||||
<div class="flex-1 flex justify-center border-r border-gray-100 py-3 hover:bg-gray-50 cursor-pointer text-gray-400 transition-colors">
|
||||
<div class="flex-1 flex justify-center border-r border-[var(--border-color,#f3f4f6)] py-3 hover:bg-[var(--bg-hover,#f9fafb)] cursor-pointer text-[var(--text-secondary,#9ca3af)] transition-colors">
|
||||
// REVIEW
|
||||
</div>
|
||||
<div class="flex-1 flex justify-center border-r border-gray-100 py-3 hover:bg-gray-50 cursor-pointer text-gray-400 transition-colors">
|
||||
<div class="flex-1 flex justify-center border-r border-[var(--border-color,#f3f4f6)] py-3 hover:bg-[var(--bg-hover,#f9fafb)] cursor-pointer text-[var(--text-secondary,#9ca3af)] transition-colors">
|
||||
// DEPLOY
|
||||
</div>
|
||||
<div class="flex-1 flex justify-center py-3 hover:bg-gray-50 cursor-pointer text-gray-400 transition-colors">
|
||||
<div class="flex-1 flex justify-center py-3 hover:bg-[var(--bg-hover,#f9fafb)] cursor-pointer text-[var(--text-secondary,#9ca3af)] transition-colors">
|
||||
// MONITOR
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ const SUITE_DIRS: &[&str] = &[
|
|||
"project",
|
||||
#[cfg(feature = "goals")]
|
||||
"goals",
|
||||
"vibe",
|
||||
];
|
||||
|
||||
const ROOT_FILES: &[&str] = &[
|
||||
|
|
@ -163,7 +164,7 @@ pub async fn index(OriginalUri(uri): OriginalUri) -> Response {
|
|||
let path_parts: Vec<&str> = path.split('/').collect();
|
||||
let fs_path = if path_parts.len() > 1 {
|
||||
let mut start_idx = 1;
|
||||
let known_dirs = ["suite", "js", "css", "vendor", "assets", "public", "partials", "settings", "auth", "about", "drive", "chat", "tasks", "admin", "mail", "calendar", "meet", "docs", "sheet", "slides", "paper", "research", "sources", "learn", "analytics", "dashboards", "monitoring", "people", "crm", "tickets", "billing", "products", "video", "player", "canvas", "social", "project", "goals", "workspace", "designer"];
|
||||
let known_dirs = ["suite", "js", "css", "vendor", "assets", "public", "partials", "settings", "auth", "about", "drive", "chat", "tasks", "admin", "mail", "calendar", "meet", "docs", "sheet", "slides", "paper", "research", "sources", "learn", "analytics", "dashboards", "monitoring", "people", "crm", "tickets", "billing", "products", "video", "player", "canvas", "social", "project", "goals", "workspace", "designer", "vibe"];
|
||||
|
||||
// Special case: /auth/suite/* should map to suite/* (auth is a route, not a directory)
|
||||
if path_parts.get(1) == Some(&"auth") && path_parts.get(2) == Some(&"suite") {
|
||||
|
|
|
|||
604
ui/suite/css/chat-agent-mode.css
Normal file
604
ui/suite/css/chat-agent-mode.css
Normal file
|
|
@ -0,0 +1,604 @@
|
|||
/* Chat Agent Mode — Z.ai toggle + OpenClaw multi-panel layout */
|
||||
|
||||
/* ============================================
|
||||
AGENT / CHAT MODE TOGGLE (Z.ai style)
|
||||
============================================ */
|
||||
|
||||
.chat-mode-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
background: var(--surface, #1a1a24);
|
||||
border: 1px solid var(--border, #2a2a2a);
|
||||
border-radius: 20px;
|
||||
padding: 2px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.chat-mode-btn {
|
||||
padding: 5px 14px;
|
||||
border: none;
|
||||
border-radius: 18px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
background: transparent;
|
||||
color: var(--text-secondary, #888);
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.chat-mode-btn.active {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(132, 214, 105, 0.3);
|
||||
}
|
||||
|
||||
.chat-mode-btn:not(.active):hover {
|
||||
color: var(--text, #fff);
|
||||
background: var(--hover, rgba(255, 255, 255, 0.05));
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
QUICK ACTION CHIPS (Z.ai style)
|
||||
============================================ */
|
||||
|
||||
.quick-actions-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
justify-content: center;
|
||||
animation: quickActionsIn 0.4s ease;
|
||||
}
|
||||
|
||||
@keyframes quickActionsIn {
|
||||
from { opacity: 0; transform: translateY(8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
|
||||
.quick-action-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid var(--border, #2a2a2a);
|
||||
border-radius: 24px;
|
||||
background: var(--surface, #1a1a24);
|
||||
color: var(--text, #fff);
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.quick-action-chip:hover {
|
||||
border-color: #84d669;
|
||||
background: rgba(132, 214, 105, 0.08);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(132, 214, 105, 0.15);
|
||||
}
|
||||
|
||||
.quick-action-chip:active {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.quick-action-icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
AGENT MODE — MULTI-PANEL LAYOUT
|
||||
============================================ */
|
||||
|
||||
.chat-layout.agent-mode {
|
||||
max-width: none;
|
||||
padding: 0;
|
||||
display: grid;
|
||||
grid-template-columns: 48px 1fr 1fr;
|
||||
grid-template-rows: 1fr auto auto;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
/* Agent Mode Left Sidebar */
|
||||
.agent-sidebar {
|
||||
display: none;
|
||||
grid-row: 1 / -1;
|
||||
grid-column: 1;
|
||||
background: #f8f8f8;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
flex-direction: column;
|
||||
z-index: 50;
|
||||
}
|
||||
|
||||
.agent-mode .agent-sidebar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.agent-sidebar-item {
|
||||
width: 48px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
background: transparent;
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
border-top: none;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.agent-sidebar-item:hover {
|
||||
background: #fff;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.agent-sidebar-item.active {
|
||||
background: #fff;
|
||||
border-left: 3px solid #84d669;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.agent-sidebar-badge {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
min-width: 16px;
|
||||
height: 16px;
|
||||
padding: 0 4px;
|
||||
border-radius: 8px;
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
/* Chat Panel (in agent mode) */
|
||||
.agent-mode #messages {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.agent-mode footer {
|
||||
grid-column: 2 / -1;
|
||||
padding: 8px 16px;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
THOUGHT PROCESS BLOCK
|
||||
============================================ */
|
||||
|
||||
.thought-process {
|
||||
margin: 12px 0;
|
||||
border: 1px solid var(--border, #e0e0e0);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: var(--surface, #f8f9fa);
|
||||
}
|
||||
|
||||
.thought-process-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 10px 14px;
|
||||
cursor: pointer;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text, #3b3b3b);
|
||||
background: var(--surface, #f0f1f2);
|
||||
transition: background 0.15s;
|
||||
border: none;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.thought-process-header:hover {
|
||||
background: var(--hover, #e8e9ea);
|
||||
}
|
||||
|
||||
.thought-process-toggle {
|
||||
transition: transform 0.2s;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.thought-process.expanded .thought-process-toggle {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.thought-process-body {
|
||||
display: none;
|
||||
padding: 12px 14px;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: var(--text-secondary, #666);
|
||||
border-top: 1px solid var(--border, #e0e0e0);
|
||||
}
|
||||
|
||||
.thought-process.expanded .thought-process-body {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
BROWSER PANEL
|
||||
============================================ */
|
||||
|
||||
.agent-browser-panel {
|
||||
display: none;
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
border-left: 1px solid #f0f1f2;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.agent-mode .agent-browser-panel {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.browser-panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 12px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.browser-url-bar {
|
||||
flex: 1;
|
||||
padding: 4px 10px;
|
||||
background: #fff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.browser-panel-content {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.browser-panel-content iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.browser-panel-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
color: #ccc;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
TERMINAL PANEL
|
||||
============================================ */
|
||||
|
||||
.agent-terminal-panel {
|
||||
display: none;
|
||||
grid-column: 2;
|
||||
grid-row: 2;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
flex-direction: column;
|
||||
max-height: 200px;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.agent-mode .agent-terminal-panel {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.terminal-panel-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
background: #1e1e1e;
|
||||
border-bottom: 1px solid #333;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #84d669;
|
||||
}
|
||||
|
||||
.terminal-panel-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
background: #1e1e1e;
|
||||
padding: 8px 12px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
.terminal-line {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.terminal-line.stderr {
|
||||
color: #f87171;
|
||||
}
|
||||
|
||||
.terminal-line.stdout {
|
||||
color: #d4d4d4;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
AGENT INFO CARD
|
||||
============================================ */
|
||||
|
||||
.agent-info-card {
|
||||
display: none;
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
border-left: 1px solid #f0f1f2;
|
||||
padding: 12px 16px;
|
||||
background: #f8f8f8;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.agent-mode .agent-info-card {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.agent-info-name {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.agent-info-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background: #84d669;
|
||||
}
|
||||
|
||||
.agent-level-badge {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.badge-evolved {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-bred {
|
||||
background: #f59e0b;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-wild {
|
||||
background: #ef4444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.agent-info-model {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.agent-info-toggles {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.agent-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.agent-toggle-switch {
|
||||
width: 28px;
|
||||
height: 16px;
|
||||
border-radius: 8px;
|
||||
background: #ccc;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.agent-toggle-switch.on {
|
||||
background: #84d669;
|
||||
}
|
||||
|
||||
.agent-toggle-switch::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
transition: transform 0.2s;
|
||||
}
|
||||
|
||||
.agent-toggle-switch.on::after {
|
||||
transform: translateX(12px);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
STEP COUNTER BAR
|
||||
============================================ */
|
||||
|
||||
.agent-step-bar {
|
||||
display: none;
|
||||
grid-column: 1 / -1;
|
||||
grid-row: 3;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 8px 16px;
|
||||
background: #f8f8f8;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.agent-mode .agent-step-bar {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.step-counter {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.step-nav-btn {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid #e0e0e0;
|
||||
background: #fff;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s;
|
||||
font-size: 14px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.step-nav-btn:hover {
|
||||
border-color: #84d669;
|
||||
color: #84d669;
|
||||
}
|
||||
|
||||
.step-action-btns {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.step-action-btn {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 50%;
|
||||
border: none;
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s;
|
||||
font-size: 16px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.step-action-btn:hover {
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 2px 8px rgba(132, 214, 105, 0.3);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
TODO LIST (OpenClaw style)
|
||||
============================================ */
|
||||
|
||||
.agent-todo-list {
|
||||
margin: 12px 0;
|
||||
border: 1px solid var(--border, #e0e0e0);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.agent-todo-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 8px 14px;
|
||||
background: var(--surface, #f0f1f2);
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text, #3b3b3b);
|
||||
}
|
||||
|
||||
.agent-todo-count {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
padding: 1px 6px;
|
||||
border-radius: 10px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.agent-todo-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 14px;
|
||||
border-top: 1px solid var(--border, #e0e0e0);
|
||||
font-size: 13px;
|
||||
color: var(--text, #3b3b3b);
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.agent-todo-item.done {
|
||||
opacity: 0.5;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.agent-todo-check {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid #ccc;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.agent-todo-item.done .agent-todo-check {
|
||||
background: #84d669;
|
||||
border-color: #84d669;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
|
@ -1,26 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>BUILD V3 - Web Desktop Environment</title>
|
||||
|
||||
|
||||
<!-- Link to the existing compiled CSS -->
|
||||
<link rel="stylesheet" href="/suite/css/app.css" />
|
||||
<link rel="stylesheet" href="/suite/css/base.css" />
|
||||
<link rel="stylesheet" href="/suite/css/theme-sentient.css" />
|
||||
<link rel="stylesheet" href="/suite/css/desktop.css" />
|
||||
|
||||
|
||||
<!-- Local JS requirements per AGENTS.md / UI.md -->
|
||||
<script src="/suite/js/vendor/htmx.min.js"></script>
|
||||
<script src="/suite/js/window-manager.js"></script>
|
||||
<script src="/suite/js/theme-manager.js"></script>
|
||||
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', 'Fira Sans', Arial, sans-serif;
|
||||
background: white;
|
||||
background: var(--bg, #ffffff);
|
||||
color: var(--text, #333333);
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
|
|
@ -28,97 +35,321 @@
|
|||
}
|
||||
|
||||
/* Core Layout replicating BUILD V3 screenshot styling */
|
||||
.build-container { width: 100%; height: 100vh; display: flex; }
|
||||
|
||||
.build-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/* Left Sidebar */
|
||||
.sidebar { width: 51px; height: 100vh; background: #f8f8f8; border-right: 1px solid #f0f1f2; display: flex; flex-direction: column; z-index: 100; }
|
||||
.sidebar-item { width: 51px; height: 50px; border-bottom: 1px solid #f0f1f2; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.15s ease; }
|
||||
.sidebar-item:hover { background: #ffffff; }
|
||||
.sidebar-item.active { background: #ffffff; border-left: 3px solid #84d669; }
|
||||
.sidebar-icon { width: 30px; height: 30px; opacity: 0.6; }
|
||||
.sidebar-item:hover .sidebar-icon { opacity: 1; }
|
||||
.sidebar {
|
||||
width: 51px;
|
||||
height: 100vh;
|
||||
background: var(--bg-secondary, #f8f8f8);
|
||||
border-right: 1px solid var(--border-color, #f0f1f2);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
width: 51px;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid var(--border-color, #f0f1f2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
}
|
||||
|
||||
.sidebar-item:hover {
|
||||
background: var(--bg, #ffffff);
|
||||
}
|
||||
|
||||
.sidebar-item.active {
|
||||
background: var(--bg, #ffffff);
|
||||
border-left: 3px solid var(--primary, #84d669);
|
||||
}
|
||||
|
||||
.sidebar-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
stroke: var(--text-secondary, #3b3b3b);
|
||||
opacity: 0.6;
|
||||
transition: stroke 0.15s ease, opacity 0.15s ease;
|
||||
}
|
||||
|
||||
.sidebar-item:hover .sidebar-icon {
|
||||
opacity: 1;
|
||||
stroke: var(--text, #3b3b3b);
|
||||
}
|
||||
|
||||
/* Main Content wrapper */
|
||||
.main-wrapper { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
|
||||
|
||||
.main-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Top Navigation Tabs */
|
||||
.tabs-container { display: flex; flex-direction: column; background: #f8f8f8; border-bottom: 1px solid #f0f1f2; z-index: 100;}
|
||||
.tabs-row { display: flex; height: 34px; }
|
||||
.main-tab { height: 34px; min-width: 169px; flex: 1; border-right: 1px solid #f0f1f2; display: flex; align-items: center; padding: 0 18px; cursor: pointer; }
|
||||
.main-tab:hover { background: #ffffff; }
|
||||
.main-tab.active { background: #84d669; }
|
||||
.main-tab.active .main-tab-content { color: white; }
|
||||
.main-tab-content { display: flex; align-items: center; gap: 4px; font-family: 'Fira Code', monospace; font-size: 14px; font-weight: 500; color: #3b3b3b; }
|
||||
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-secondary, #f8f8f8);
|
||||
border-bottom: 1px solid var(--border-color, #f0f1f2);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.tabs-row {
|
||||
display: flex;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.main-tab {
|
||||
height: 34px;
|
||||
min-width: 169px;
|
||||
flex: 1;
|
||||
border-right: 1px solid var(--border-color, #f0f1f2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 18px;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s ease;
|
||||
}
|
||||
|
||||
.main-tab:hover {
|
||||
background: var(--bg, #ffffff);
|
||||
}
|
||||
|
||||
.main-tab.active {
|
||||
background: var(--primary, #84d669);
|
||||
}
|
||||
|
||||
.main-tab.active .main-tab-content {
|
||||
color: var(--bg, #ffffff);
|
||||
}
|
||||
|
||||
.main-tab-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary, #3b3b3b);
|
||||
transition: color 0.15s ease;
|
||||
}
|
||||
|
||||
/* Workspace (Where windows float) */
|
||||
.workspace { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: white; position: relative; }
|
||||
|
||||
.workspace {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: var(--bg, #ffffff);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* The Panel Grid (Desktop Icons) */
|
||||
.panel-section { flex: 1; padding: 26px 33px; overflow-y: auto; z-index: 10; position: absolute; inset: 0; pointer-events: none;}
|
||||
|
||||
.panel-section {
|
||||
flex: 1;
|
||||
padding: 26px 33px;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Interactive Desktop Icons triggering HTMX */
|
||||
.desktop-icons-container {
|
||||
display: flex; flex-direction: column; gap: 20px; align-items: center; width: 100px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
align-items: center;
|
||||
width: 100px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.desktop-icon {
|
||||
display: flex; flex-direction: column; align-items: center; width: 80px;
|
||||
cursor: pointer; position: relative; gap: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.app-icon {
|
||||
width: 64px; height: 64px; border-radius: 16px;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 16px;
|
||||
background: linear-gradient(135deg, #4ade80 0%, #15803d 100%);
|
||||
box-shadow: inset 0px 2px 4px rgba(255,255,255,0.4), inset 0px -3px 0 rgba(20,83,45,0.8), 0px 6px 12px rgba(0,0,0,0.15);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
box-shadow: inset 0px 2px 4px rgba(255, 255, 255, 0.4), inset 0px -3px 0 rgba(20, 83, 45, 0.8), 0px 6px 12px rgba(0, 0, 0, 0.15);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.15s ease;
|
||||
}
|
||||
.desktop-icon:hover .app-icon { transform: scale(1.05); }
|
||||
.app-icon svg { width: 32px; height: 32px; stroke: white; }
|
||||
|
||||
|
||||
.desktop-icon:hover .app-icon {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.app-icon svg {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
stroke: white;
|
||||
}
|
||||
|
||||
.desktop-icon-label {
|
||||
font-family: 'Fira Code', monospace; font-size: 12px; font-weight: 600; color: #374151;
|
||||
background: rgba(255, 255, 255, 0.7); backdrop-filter: blur(4px);
|
||||
padding: 2px 8px; border-radius: 4px; text-align: center;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--text-secondary, #374151);
|
||||
background: var(--bg-alpha-70, rgba(255, 255, 255, 0.7));
|
||||
backdrop-filter: blur(4px);
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* The background abstract pattern from BUILD V3 */
|
||||
.bg-grid { position: absolute; inset: 0; background-image: linear-gradient(to right, #f0fdf4 1px, transparent 1px), linear-gradient(to bottom, #f0fdf4 1px, transparent 1px); background-size: 40px 40px; z-index: 0; pointer-events: none; }
|
||||
.bg-svg { position: absolute; top: -10%; left: -10%; width: 120%; height: 120%; z-index: 0; opacity: 0.6; pointer-events: none; }
|
||||
.bg-svg path { fill: none; stroke: #e6f2eb; stroke-width: 45; stroke-linecap: round; stroke-linejoin: round; }
|
||||
.bg-svg path.inner { stroke: #f7faf9; stroke-width: 41; }
|
||||
.bg-grid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: linear-gradient(to right, var(--bg-grid, #f0fdf4) 1px, transparent 1px), linear-gradient(to bottom, var(--bg-grid, #f0fdf4) 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-svg {
|
||||
position: absolute;
|
||||
top: -10%;
|
||||
left: -10%;
|
||||
width: 120%;
|
||||
height: 120%;
|
||||
z-index: 0;
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-svg path {
|
||||
fill: none;
|
||||
stroke: var(--bg-grid-stroke, #e6f2eb);
|
||||
stroke-width: 45;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.bg-svg path.inner {
|
||||
stroke: var(--bg-grid-stroke-inner, #f7faf9);
|
||||
stroke-width: 41;
|
||||
}
|
||||
|
||||
/* Bottom Taskbar */
|
||||
.toolbar { height: 50px; background: white; border-top: 1px solid #f0f1f2; display: flex; align-items: center; padding: 0 8px; z-index: 100; position: relative;}
|
||||
#taskbar-apps { display: flex; flex: 1; height: 100%; align-items: center; gap: 0px; }
|
||||
.toolbar-time { font-family: 'Fira Code', monospace; font-size: 14px; color: #3b3b3b; text-align: right; line-height: 1.4; padding: 0 10px; margin-left: auto; }
|
||||
.toolbar {
|
||||
height: 50px;
|
||||
background: var(--bg-secondary, white);
|
||||
border-top: 1px solid var(--border-color, #f0f1f2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#taskbar-apps {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
gap: 0px;
|
||||
}
|
||||
|
||||
.toolbar-time {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
color: var(--text-secondary, #3b3b3b);
|
||||
text-align: right;
|
||||
line-height: 1.4;
|
||||
padding: 0 10px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Taskbar Items generated by WindowManager */
|
||||
.taskbar-item { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.15s ease; border-bottom: 2px solid transparent;}
|
||||
.taskbar-item:hover { background: #f8f8f8; }
|
||||
.taskbar-item.active { border-bottom-color: #84d669; background: linear-gradient(to bottom, rgba(132,214,105,0) 50%, rgba(132,214,105,0.1) 100%); }
|
||||
.taskbar-item {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.taskbar-item:hover {
|
||||
background: var(--bg-hover, #f8f8f8);
|
||||
}
|
||||
|
||||
.taskbar-item.active {
|
||||
border-bottom-color: var(--primary, #84d669);
|
||||
background: linear-gradient(to bottom, transparent 50%, var(--primary-alpha-10, rgba(132, 214, 105, 0.1)) 100%);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- Minibar Component (Phase 8) -->
|
||||
<div hx-get="/suite/partials/minibar.html" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
|
||||
<div class="build-container">
|
||||
<!-- Left Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-item active" title="Home">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
|
||||
<polyline points="9 22 9 12 15 12 15 22"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Search">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Terminal">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="4 17 10 11 4 5"></polyline>
|
||||
<line x1="12" y1="19" x2="20" y2="19"></line>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="User">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Apps">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="14" width="7" height="7"></rect>
|
||||
<rect x="3" y="14" width="7" height="7"></rect>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" style="margin-top: auto;" title="Settings">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.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-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-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-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 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 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
<path
|
||||
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.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-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-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-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 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 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
|
@ -126,23 +357,34 @@
|
|||
<div class="main-wrapper">
|
||||
<!-- Top Navigation Tabs -->
|
||||
<div class="tabs-container">
|
||||
<div class="breadcrumb-row" style="display: flex; height: 34px; border-bottom: 1px solid #f0f1f2; align-items: center; padding: 0 18px; font-family: 'Fira Code', monospace; font-size: 14px; color: #6b7280; gap: 8px;">
|
||||
<span style="color: #374151;">// DASHBOARD</span>
|
||||
<span style="color: #9ca3af;">></span>
|
||||
<span style="color: #374151;">// E-COMMERCE APP DEVELOPMENT</span>
|
||||
<div class="breadcrumb-row"
|
||||
style="display: flex; height: 34px; border-bottom: 1px solid var(--border-color, #f0f1f2); align-items: center; padding: 0 18px; font-family: 'Fira Code', monospace; font-size: 14px; color: var(--text-muted, #6b7280); gap: 8px;">
|
||||
<span style="color: var(--text-secondary, #374151);">// DASHBOARD</span>
|
||||
<span style="color: var(--text-muted, #9ca3af);">></span>
|
||||
<span style="color: var(--text, #374151); font-weight: 600;">// E-COMMERCE APP DEVELOPMENT</span>
|
||||
</div>
|
||||
<div class="tabs-row">
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>PLAN</span></div></div>
|
||||
<div class="main-tab active"><div class="main-tab-content"><span>//</span><span>BUILD</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>REVIEW</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>DEPLOY</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>MONITOR</span></div></div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>PLAN</span></div>
|
||||
</div>
|
||||
<div class="main-tab active">
|
||||
<div class="main-tab-content"><span>//</span><span>BUILD</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>REVIEW</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>DEPLOY</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>MONITOR</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workspace container where WindowManager operates -->
|
||||
<div class="workspace" id="desktop-content">
|
||||
|
||||
|
||||
<!-- Background Pattern -->
|
||||
<div class="bg-grid"></div>
|
||||
<svg class="bg-svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1000 600">
|
||||
|
|
@ -156,52 +398,85 @@
|
|||
|
||||
<div class="panel-section">
|
||||
<div class="desktop-icons-container">
|
||||
|
||||
<div class="desktop-icon" data-app-id="vibe" data-app-title="Vibe" hx-get="/suite/partials/vibe.html" hx-swap="none">
|
||||
|
||||
<div class="desktop-icon" data-app-id="vibe" data-app-title="Vibe"
|
||||
hx-get="/suite/partials/vibe.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 2v20M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Vibe</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="tasks" data-app-title="Tasks" hx-get="/suite/tasks/tasks.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="tasks" data-app-title="Tasks"
|
||||
hx-get="/suite/tasks/task-window.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9 11l3 3L22 4" />
|
||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Tasks</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="chat" data-app-title="Chat" hx-get="/suite/chat/chat.html" hx-swap="none">
|
||||
|
||||
<div class="desktop-icon" data-app-id="chat" data-app-title="Chat"
|
||||
hx-get="/suite/partials/chat.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Chat</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="terminal" data-app-title="Terminal" hx-get="/suite/terminal/terminal.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="terminal" data-app-title="Terminal"
|
||||
hx-get="/suite/terminal/terminal.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg 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>
|
||||
<svg 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>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Terminal</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="drive" data-app-title="Explorer" hx-get="/suite/drive/drive.html" hx-swap="none">
|
||||
|
||||
<div class="desktop-icon" data-app-id="drive" data-app-title="Explorer"
|
||||
hx-get="/suite/drive/drive.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<path
|
||||
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Explorer</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="editor" data-app-title="Editor" hx-get="/suite/editor.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="editor" data-app-title="Editor"
|
||||
hx-get="/suite/editor.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="16 18 22 12 16 6" />
|
||||
<polyline points="8 6 2 12 8 18" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Editor</span>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="browser" data-app-title="Browser" hx-get="/suite/browser/browser.html" hx-swap="none">
|
||||
|
||||
<div class="desktop-icon" data-app-id="browser" data-app-title="Browser"
|
||||
hx-get="/suite/browser/browser.html" hx-swap="none">
|
||||
<div class="app-icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76"/></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
||||
stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<polygon points="16.24 7.76 14.12 14.12 7.76 16.24 9.88 9.88 16.24 7.76" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="desktop-icon-label">Browser</span>
|
||||
</div>
|
||||
|
|
@ -235,7 +510,7 @@
|
|||
} else {
|
||||
console.error("WindowManager class not loaded from window-manager.js");
|
||||
}
|
||||
|
||||
|
||||
// Initialize ThemeManager
|
||||
if (typeof window.ThemeManager !== 'undefined') {
|
||||
window.ThemeManager.init();
|
||||
|
|
@ -243,21 +518,21 @@
|
|||
});
|
||||
|
||||
// Listen to HTMX afterRequest event
|
||||
document.body.addEventListener('htmx:afterRequest', function(evt) {
|
||||
document.body.addEventListener('htmx:afterRequest', function (evt) {
|
||||
const target = evt.detail.elt;
|
||||
|
||||
|
||||
// Check if the click came from a desktop icon
|
||||
if (target.classList.contains('desktop-icon')) {
|
||||
const appId = target.getAttribute('data-app-id');
|
||||
const title = target.getAttribute('data-app-title');
|
||||
const htmlContent = evt.detail.xhr.response;
|
||||
|
||||
|
||||
// Tell WindowManager to open it
|
||||
if (window.wm) {
|
||||
window.wm.open(appId, title, htmlContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ensure Theme dropdown is re-injected if wiped
|
||||
if (window.ThemeManager) {
|
||||
const container = document.getElementById('themeSelectorContainer');
|
||||
|
|
@ -271,9 +546,10 @@
|
|||
// Simple Clock implementation matching the screenshot bottom right corner
|
||||
setInterval(() => {
|
||||
const now = new Date();
|
||||
document.getElementById('clock-time').textContent = now.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
document.getElementById('clock-time').textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
document.getElementById('clock-date').textContent = now.toLocaleDateString();
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</html>
|
||||
302
ui/suite/js/chat-agent-mode.js
Normal file
302
ui/suite/js/chat-agent-mode.js
Normal file
|
|
@ -0,0 +1,302 @@
|
|||
/**
|
||||
* Chat Agent Mode — handles toggling between Agent and Chat mode,
|
||||
* multi-panel layout management, and WebSocket message routing
|
||||
* for thought process, terminal output, browser preview, and step tracking.
|
||||
*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var agentMode = false;
|
||||
var currentStep = 0;
|
||||
var totalSteps = 0;
|
||||
var terminalLineCount = 0;
|
||||
|
||||
function initAgentMode() {
|
||||
setupModeToggle();
|
||||
setupToggleSwitches();
|
||||
setupStepNavigation();
|
||||
setupQuickActions();
|
||||
setupSidebarItems();
|
||||
}
|
||||
|
||||
function setupModeToggle() {
|
||||
var agentBtn = document.getElementById("modeAgentBtn");
|
||||
var chatBtn = document.getElementById("modeChatBtn");
|
||||
if (!agentBtn || !chatBtn) return;
|
||||
|
||||
agentBtn.addEventListener("click", function () {
|
||||
setMode("agent");
|
||||
});
|
||||
chatBtn.addEventListener("click", function () {
|
||||
setMode("chat");
|
||||
});
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
var chatApp = document.getElementById("chat-app");
|
||||
var agentBtn = document.getElementById("modeAgentBtn");
|
||||
var chatBtn = document.getElementById("modeChatBtn");
|
||||
var quickActions = document.getElementById("quickActions");
|
||||
|
||||
if (!chatApp || !agentBtn || !chatBtn) return;
|
||||
|
||||
agentMode = mode === "agent";
|
||||
|
||||
agentBtn.classList.toggle("active", agentMode);
|
||||
chatBtn.classList.toggle("active", !agentMode);
|
||||
|
||||
if (agentMode) {
|
||||
chatApp.classList.add("agent-mode");
|
||||
if (quickActions) quickActions.style.display = "none";
|
||||
} else {
|
||||
chatApp.classList.remove("agent-mode");
|
||||
if (quickActions) quickActions.style.display = "";
|
||||
}
|
||||
}
|
||||
|
||||
function setupToggleSwitches() {
|
||||
var planToggle = document.getElementById("togglePlan");
|
||||
var yoloToggle = document.getElementById("toggleYolo");
|
||||
|
||||
if (planToggle) {
|
||||
planToggle.addEventListener("click", function () {
|
||||
this.classList.toggle("on");
|
||||
emitModeChange();
|
||||
});
|
||||
}
|
||||
if (yoloToggle) {
|
||||
yoloToggle.addEventListener("click", function () {
|
||||
this.classList.toggle("on");
|
||||
emitModeChange();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function emitModeChange() {
|
||||
var planOn = document.getElementById("togglePlan");
|
||||
var yoloOn = document.getElementById("toggleYolo");
|
||||
var mode = "plan";
|
||||
if (yoloOn && yoloOn.classList.contains("on")) {
|
||||
mode = "yolo";
|
||||
}
|
||||
if (window.ws && window.ws.readyState === WebSocket.OPEN) {
|
||||
window.ws.send(JSON.stringify({
|
||||
type: "toggle_mode",
|
||||
mode: mode
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
function setupStepNavigation() {
|
||||
var prevBtn = document.getElementById("stepPrev");
|
||||
var nextBtn = document.getElementById("stepNext");
|
||||
|
||||
if (prevBtn) {
|
||||
prevBtn.addEventListener("click", function () {
|
||||
if (currentStep > 1) {
|
||||
currentStep--;
|
||||
updateStepCounter();
|
||||
}
|
||||
});
|
||||
}
|
||||
if (nextBtn) {
|
||||
nextBtn.addEventListener("click", function () {
|
||||
if (currentStep < totalSteps) {
|
||||
currentStep++;
|
||||
updateStepCounter();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateStepCounter() {
|
||||
var display = document.getElementById("stepCounterText");
|
||||
if (display) {
|
||||
display.textContent = currentStep + " / " + totalSteps;
|
||||
}
|
||||
}
|
||||
|
||||
function setupQuickActions() {
|
||||
var chips = document.querySelectorAll(".quick-action-chip");
|
||||
chips.forEach(function (chip) {
|
||||
chip.addEventListener("click", function () {
|
||||
var action = this.getAttribute("data-action");
|
||||
var prompts = {
|
||||
"full-stack": "Create a full-stack web application",
|
||||
"writing": "Help me write ",
|
||||
"data-insight": "Analyze data and provide insights",
|
||||
"magic-design": "Design a beautiful UI for "
|
||||
};
|
||||
var input = document.getElementById("messageInput");
|
||||
if (input && prompts[action]) {
|
||||
input.value = prompts[action];
|
||||
input.focus();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupSidebarItems() {
|
||||
var items = document.querySelectorAll(".agent-sidebar-item");
|
||||
items.forEach(function (item) {
|
||||
item.addEventListener("click", function () {
|
||||
items.forEach(function (i) { i.classList.remove("active"); });
|
||||
this.classList.add("active");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Agent Mode WebSocket Message Handlers
|
||||
=========================================== */
|
||||
|
||||
function handleAgentMessage(data) {
|
||||
if (!agentMode) return;
|
||||
|
||||
switch (data.type) {
|
||||
case "thought_process":
|
||||
renderThoughtProcess(data.content);
|
||||
break;
|
||||
case "terminal_output":
|
||||
appendTerminalLine(data.line, data.stream);
|
||||
break;
|
||||
case "browser_ready":
|
||||
showBrowserPreview(data.url);
|
||||
break;
|
||||
case "step_progress":
|
||||
currentStep = data.current;
|
||||
totalSteps = data.total;
|
||||
updateStepCounter();
|
||||
break;
|
||||
case "step_complete":
|
||||
break;
|
||||
case "todo_update":
|
||||
renderTodoList(data.todos);
|
||||
break;
|
||||
case "agent_status":
|
||||
updateAgentInfo(data);
|
||||
break;
|
||||
case "file_created":
|
||||
incrementBadge("explorerBadge");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function renderThoughtProcess(content) {
|
||||
var messages = document.getElementById("messages");
|
||||
if (!messages) return;
|
||||
|
||||
var block = document.createElement("div");
|
||||
block.className = "thought-process";
|
||||
block.innerHTML =
|
||||
'<button class="thought-process-header">' +
|
||||
'<span class="thought-process-toggle">▶</span>' +
|
||||
'<span>Thought Process</span>' +
|
||||
"</button>" +
|
||||
'<div class="thought-process-body">' + escapeForHtml(content) + "</div>";
|
||||
|
||||
var header = block.querySelector(".thought-process-header");
|
||||
header.addEventListener("click", function () {
|
||||
block.classList.toggle("expanded");
|
||||
});
|
||||
|
||||
messages.appendChild(block);
|
||||
}
|
||||
|
||||
function appendTerminalLine(text, stream) {
|
||||
var terminal = document.getElementById("terminalPanelContent");
|
||||
if (!terminal) return;
|
||||
|
||||
var line = document.createElement("div");
|
||||
line.className = "terminal-line " + (stream || "stdout");
|
||||
line.textContent = text;
|
||||
terminal.appendChild(line);
|
||||
terminal.scrollTop = terminal.scrollHeight;
|
||||
|
||||
terminalLineCount++;
|
||||
incrementBadge("terminalBadge");
|
||||
}
|
||||
|
||||
function showBrowserPreview(url) {
|
||||
var content = document.getElementById("browserPanelContent");
|
||||
var urlBar = document.getElementById("browserUrlBar");
|
||||
if (!content || !urlBar) return;
|
||||
|
||||
urlBar.value = url;
|
||||
content.innerHTML = '<iframe src="' + url + '" sandbox="allow-scripts allow-same-origin"></iframe>';
|
||||
}
|
||||
|
||||
function renderTodoList(todos) {
|
||||
var messages = document.getElementById("messages");
|
||||
if (!messages) return;
|
||||
|
||||
var existing = messages.querySelector(".agent-todo-list:last-child");
|
||||
if (existing) existing.remove();
|
||||
|
||||
var list = document.createElement("div");
|
||||
list.className = "agent-todo-list";
|
||||
|
||||
var headerHtml = '<div class="agent-todo-header">' +
|
||||
'<span>📋 Todos</span>' +
|
||||
'<span class="agent-todo-count">' + todos.length + "</span>" +
|
||||
"</div>";
|
||||
|
||||
var itemsHtml = todos.map(function (todo) {
|
||||
var doneClass = todo.done ? " done" : "";
|
||||
var checkMark = todo.done ? "✓" : "";
|
||||
return '<div class="agent-todo-item' + doneClass + '">' +
|
||||
'<span class="agent-todo-check">' + checkMark + "</span>" +
|
||||
'<span>' + escapeForHtml(todo.text) + "</span>" +
|
||||
"</div>";
|
||||
}).join("");
|
||||
|
||||
list.innerHTML = headerHtml + itemsHtml;
|
||||
messages.appendChild(list);
|
||||
}
|
||||
|
||||
function updateAgentInfo(data) {
|
||||
var nameEl = document.getElementById("agentNameDisplay");
|
||||
var levelEl = document.getElementById("agentLevelBadge");
|
||||
var modelEl = document.getElementById("agentModelDisplay");
|
||||
|
||||
if (nameEl && data.name) nameEl.textContent = data.name;
|
||||
if (levelEl && data.level) {
|
||||
levelEl.textContent = data.level;
|
||||
levelEl.className = "agent-level-badge badge-" + data.level.toLowerCase();
|
||||
}
|
||||
if (modelEl && data.model) {
|
||||
modelEl.textContent = data.model + " — " + (data.usage || 0) + "%";
|
||||
}
|
||||
}
|
||||
|
||||
function incrementBadge(badgeId) {
|
||||
var badge = document.getElementById(badgeId);
|
||||
if (!badge) return;
|
||||
var count = parseInt(badge.textContent, 10) || 0;
|
||||
badge.textContent = count + 1;
|
||||
badge.style.display = "";
|
||||
}
|
||||
|
||||
function escapeForHtml(text) {
|
||||
var div = document.createElement("div");
|
||||
div.textContent = text || "";
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
/* ===========================================
|
||||
Expose to global scope
|
||||
=========================================== */
|
||||
|
||||
window.AgentMode = {
|
||||
init: initAgentMode,
|
||||
handleMessage: handleAgentMessage,
|
||||
setMode: setMode,
|
||||
isActive: function () { return agentMode; }
|
||||
};
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initAgentMode);
|
||||
} else {
|
||||
initAgentMode();
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<link rel="stylesheet" href="/suite/chat/chat.css?v=3" />
|
||||
<link rel="stylesheet" href="/suite/css/markdown-message.css" />
|
||||
<link rel="stylesheet" href="/suite/css/chat-agent-mode.css" />
|
||||
|
||||
<div class="chat-layout" id="chat-app">
|
||||
<!-- Connection Status -->
|
||||
|
|
@ -8,9 +9,119 @@
|
|||
<span class="connection-text">Connecting...</span>
|
||||
</div>
|
||||
|
||||
<!-- Agent Mode: Left Sidebar -->
|
||||
<aside class="agent-sidebar" id="agentSidebar">
|
||||
<button class="agent-sidebar-item active" data-panel="chat" title="Chat">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="agent-sidebar-item" data-panel="tasks" title="Tasks">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M9 11l3 3L22 4" />
|
||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="agent-sidebar-item" data-panel="terminal" title="Terminal">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="4 17 10 11 4 5" />
|
||||
<line x1="12" y1="19" x2="20" y2="19" />
|
||||
</svg>
|
||||
<span class="agent-sidebar-badge" id="terminalBadge" style="display:none;">0</span>
|
||||
</button>
|
||||
<button class="agent-sidebar-item" data-panel="explorer" title="Explorer">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />
|
||||
</svg>
|
||||
<span class="agent-sidebar-badge" id="explorerBadge" style="display:none;">0</span>
|
||||
</button>
|
||||
<button class="agent-sidebar-item" data-panel="editor" title="Editor">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="16 18 22 12 16 6" />
|
||||
<polyline points="8 6 2 12 8 18" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="agent-sidebar-item" data-panel="browser" title="Browser">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="2" y1="12" x2="22" y2="12" />
|
||||
<path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
||||
</svg>
|
||||
</button>
|
||||
</aside>
|
||||
|
||||
<main id="messages"></main>
|
||||
|
||||
<!-- Agent Mode: Browser Panel -->
|
||||
<div class="agent-browser-panel" id="agentBrowserPanel">
|
||||
<div class="browser-panel-header">
|
||||
<span>// BROWSER</span>
|
||||
<input type="text" class="browser-url-bar" id="browserUrlBar" value="" readonly
|
||||
placeholder="No preview active" />
|
||||
</div>
|
||||
<div class="browser-panel-content" id="browserPanelContent">
|
||||
<div class="browser-panel-empty">Waiting for app preview...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Agent Mode: Terminal Panel -->
|
||||
<div class="agent-terminal-panel" id="agentTerminalPanel">
|
||||
<div class="terminal-panel-header">
|
||||
<span>// TERMINAL</span>
|
||||
</div>
|
||||
<div class="terminal-panel-content" id="terminalPanelContent"></div>
|
||||
</div>
|
||||
|
||||
<!-- Agent Mode: Agent Info Card -->
|
||||
<div class="agent-info-card" id="agentInfoCard">
|
||||
<div class="agent-info-name">
|
||||
<span class="agent-info-dot"></span>
|
||||
<span id="agentNameDisplay">Agent #1</span>
|
||||
</div>
|
||||
<span class="agent-level-badge badge-evolved" id="agentLevelBadge">EVOLVED</span>
|
||||
<div class="agent-info-model" id="agentModelDisplay">Claude Opus 4.5 — 99%</div>
|
||||
<div class="agent-info-toggles">
|
||||
<div class="agent-toggle">
|
||||
<span>Plan</span>
|
||||
<button class="agent-toggle-switch on" id="togglePlan" type="button"></button>
|
||||
</div>
|
||||
<div class="agent-toggle">
|
||||
<span>YOLO</span>
|
||||
<button class="agent-toggle-switch" id="toggleYolo" type="button"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Agent Mode: Step Counter Bar -->
|
||||
<div class="agent-step-bar" id="agentStepBar">
|
||||
<div class="step-counter">
|
||||
<button class="step-nav-btn" id="stepPrev" type="button">◄</button>
|
||||
<span id="stepCounterText">0 / 0</span>
|
||||
<button class="step-nav-btn" id="stepNext" type="button">►</button>
|
||||
</div>
|
||||
<div class="step-action-btns">
|
||||
<button class="step-action-btn" title="Chat" type="button">💬</button>
|
||||
<button class="step-action-btn" title="Edit" type="button">✏️</button>
|
||||
<button class="step-action-btn" title="Code" type="button"></></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<!-- Quick Action Chips (visible in chat mode) -->
|
||||
<div class="quick-actions-container" id="quickActions">
|
||||
<button class="quick-action-chip" type="button" data-action="full-stack">
|
||||
<span class="quick-action-icon">🔧</span> Full-Stack
|
||||
</button>
|
||||
<button class="quick-action-chip" type="button" data-action="writing">
|
||||
<span class="quick-action-icon">✏️</span> Writing
|
||||
</button>
|
||||
<button class="quick-action-chip" type="button" data-action="data-insight">
|
||||
<span class="quick-action-icon">📊</span> Data Insight
|
||||
</button>
|
||||
<button class="quick-action-chip" type="button" data-action="magic-design">
|
||||
<span class="quick-action-icon">✨</span> Magic Design
|
||||
</button>
|
||||
</div>
|
||||
<div class="suggestions-container" id="suggestions"></div>
|
||||
<div class="mention-dropdown" id="mentionDropdown">
|
||||
<div class="mention-header">
|
||||
|
|
@ -19,6 +130,11 @@
|
|||
<div class="mention-results" id="mentionResults"></div>
|
||||
</div>
|
||||
<form class="input-container" id="chatForm">
|
||||
<!-- Agent/Chat Mode Toggle (Z.ai style) -->
|
||||
<div class="chat-mode-toggle" id="chatModeToggle">
|
||||
<button type="button" class="chat-mode-btn active" data-mode="agent" id="modeAgentBtn">Agent</button>
|
||||
<button type="button" class="chat-mode-btn" data-mode="chat" id="modeChatBtn">Chat</button>
|
||||
</div>
|
||||
<input name="content" id="messageInput" type="text" placeholder="Message... (type @ to mention)"
|
||||
data-i18n-placeholder="chat-placeholder" autofocus autocomplete="off" />
|
||||
<button type="submit" id="sendBtn" title="Send" data-i18n-title="chat-send">
|
||||
|
|
@ -911,6 +1027,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Route agent-type messages to AgentMode handler
|
||||
if (window.AgentMode && data.type && [
|
||||
"thought_process", "terminal_output", "browser_ready",
|
||||
"step_progress", "step_complete", "todo_update",
|
||||
"agent_status", "file_created"
|
||||
].indexOf(data.type) !== -1) {
|
||||
window.AgentMode.handleMessage(data);
|
||||
}
|
||||
|
||||
// Only process bot responses
|
||||
if (data.message_type === MessageType.BOT_RESPONSE) {
|
||||
console.log("Processing bot response:", data);
|
||||
|
|
@ -945,7 +1070,7 @@
|
|||
// Apply theme data from WebSocket events
|
||||
function getContrastYIQ(hexcolor) {
|
||||
if (!hexcolor) return '#ffffff';
|
||||
|
||||
|
||||
// Handle named colors and variables by letting the browser resolve them
|
||||
var temp = document.createElement("div");
|
||||
temp.style.color = hexcolor;
|
||||
|
|
@ -953,14 +1078,14 @@
|
|||
document.div.appendChild(temp);
|
||||
var style = window.getComputedStyle(temp).color;
|
||||
document.div.removeChild(temp);
|
||||
|
||||
|
||||
var rgb = style.match(/\d+/g);
|
||||
if (!rgb || rgb.length < 3) return '#ffffff';
|
||||
|
||||
|
||||
var r = parseInt(rgb[0]);
|
||||
var g = parseInt(rgb[1]);
|
||||
var b = parseInt(rgb[2]);
|
||||
|
||||
|
||||
var yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;
|
||||
return (yiq >= 128) ? '#000000' : '#ffffff';
|
||||
}
|
||||
|
|
@ -1179,4 +1304,5 @@
|
|||
|
||||
console.log("Chat module initialized with @ mentions support");
|
||||
})();
|
||||
</script>
|
||||
</script>
|
||||
<script src="/suite/js/chat-agent-mode.js"></script>
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
<style>
|
||||
/* CRITICAL: Overriding default Tailwind resets that break the layout */
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Fira Code', 'Fira Sans', Arial, sans-serif !important;
|
||||
background: white !important;
|
||||
|
|
@ -11,73 +16,291 @@
|
|||
}
|
||||
|
||||
/* Core Layout replicating BUILD V3 screenshot styling */
|
||||
.build-container { width: 100%; height: 100vh; display: flex; position: absolute; inset: 0; z-index: 1000; background: white;}
|
||||
|
||||
.build-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
z-index: 1000;
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* Left Sidebar */
|
||||
.sidebar { width: 51px; height: 100vh; background: #f8f8f8; border-right: 1px solid #f0f1f2; display: flex; flex-direction: column; z-index: 100; }
|
||||
.sidebar-item { width: 51px; height: 50px; border-bottom: 1px solid #f0f1f2; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.15s ease; position: relative;}
|
||||
.sidebar-item:hover { background: #ffffff; }
|
||||
.sidebar-item.active { background: #ffffff; border-left: 3px solid #84d669; }
|
||||
.sidebar-icon { width: 30px; height: 30px; opacity: 0.6; }
|
||||
.sidebar-item:hover .sidebar-icon { opacity: 1; }
|
||||
.sidebar {
|
||||
width: 51px;
|
||||
height: 100vh;
|
||||
background: #f8f8f8;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.sidebar-item {
|
||||
width: 51px;
|
||||
height: 50px;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sidebar-item:hover {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.sidebar-item.active {
|
||||
background: #ffffff;
|
||||
border-left: 3px solid #84d669;
|
||||
}
|
||||
|
||||
.sidebar-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.sidebar-item:hover .sidebar-icon {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Main Content wrapper */
|
||||
.main-wrapper { flex: 1; display: flex; flex-direction: column; overflow: hidden; position: relative; }
|
||||
|
||||
.main-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Top Navigation Tabs */
|
||||
.tabs-container { display: flex; flex-direction: column; background: #f8f8f8; border-bottom: 1px solid #f0f1f2; z-index: 100;}
|
||||
.tabs-row { display: flex; height: 34px; }
|
||||
.main-tab { height: 34px; min-width: 169px; flex: 1; border-right: 1px solid #f0f1f2; display: flex; align-items: center; padding: 0 18px; cursor: pointer; position: relative; }
|
||||
.main-tab:hover { background: #ffffff; }
|
||||
.main-tab.active { background: #84d669; border-color: #84d669;}
|
||||
.main-tab.active .main-tab-content { color: white; }
|
||||
.main-tab-content { display: flex; align-items: center; gap: 4px; font-family: 'Fira Code', monospace; font-size: 14px; font-weight: 500; color: #3b3b3b; }
|
||||
|
||||
.tabs-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.tabs-row {
|
||||
display: flex;
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.main-tab {
|
||||
height: 34px;
|
||||
min-width: 169px;
|
||||
flex: 1;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 18px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-tab:hover {
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.main-tab.active {
|
||||
background: #84d669;
|
||||
border-color: #84d669;
|
||||
}
|
||||
|
||||
.main-tab.active .main-tab-content {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.main-tab-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
/* Workspace (Where windows float) */
|
||||
.workspace { flex: 1; display: flex; flex-direction: column; overflow: hidden; background: white; position: relative; z-index: 10;}
|
||||
|
||||
.workspace {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
/* The Panel Grid (Desktop Icons) */
|
||||
.panel-section { flex: 1; padding: 26px 33px; overflow-y: auto; z-index: 10; position: absolute; inset: 0; pointer-events: none;}
|
||||
.panel-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; max-width: 1200px; pointer-events: auto;}
|
||||
|
||||
.panel-section {
|
||||
flex: 1;
|
||||
padding: 26px 33px;
|
||||
overflow-y: auto;
|
||||
z-index: 10;
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.panel-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
max-width: 1200px;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
/* Interactive Desktop Icons triggering HTMX */
|
||||
.desktop-icon {
|
||||
background: white; border: 1px solid #f0f1f2; border-radius: 8px; height: 67px; padding: 10px;
|
||||
display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-start;
|
||||
cursor: pointer; transition: all 0.2s ease; position: relative; width: 100%;
|
||||
background: white;
|
||||
border: 1px solid #f0f1f2;
|
||||
border-radius: 8px;
|
||||
height: 67px;
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
align-items: flex-start;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.desktop-icon:hover {
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
transform: translateY(-2px);
|
||||
border-color: #84d669;
|
||||
}
|
||||
|
||||
.panel-card-icon {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 10px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.panel-card-label {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: #3b3b3b;
|
||||
margin-top: auto;
|
||||
}
|
||||
.desktop-icon:hover { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); transform: translateY(-2px); border-color: #84d669; }
|
||||
.panel-card-icon { position: absolute; top: -20px; left: 10px; width: 42px; height: 42px; }
|
||||
.panel-card-label { font-family: 'Fira Code', monospace; font-size: 13px; font-weight: 500; color: #3b3b3b; margin-top: auto; }
|
||||
|
||||
/* The background abstract pattern from BUILD V3 */
|
||||
.bg-grid { position: absolute; inset: 0; background-image: linear-gradient(to right, #f0fdf4 1px, transparent 1px), linear-gradient(to bottom, #f0fdf4 1px, transparent 1px); background-size: 40px 40px; z-index: 0; pointer-events: none; }
|
||||
.bg-svg { position: absolute; top: -10%; left: -10%; width: 120%; height: 120%; z-index: 0; opacity: 0.6; pointer-events: none; display: block !important;}
|
||||
.bg-svg path { fill: none; stroke: #e6f2eb; stroke-width: 45; stroke-linecap: round; stroke-linejoin: round; }
|
||||
.bg-svg path.inner { stroke: #f7faf9; stroke-width: 41; }
|
||||
.bg-grid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image: linear-gradient(to right, #f0fdf4 1px, transparent 1px), linear-gradient(to bottom, #f0fdf4 1px, transparent 1px);
|
||||
background-size: 40px 40px;
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bg-svg {
|
||||
position: absolute;
|
||||
top: -10%;
|
||||
left: -10%;
|
||||
width: 120%;
|
||||
height: 120%;
|
||||
z-index: 0;
|
||||
opacity: 0.6;
|
||||
pointer-events: none;
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.bg-svg path {
|
||||
fill: none;
|
||||
stroke: #e6f2eb;
|
||||
stroke-width: 45;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.bg-svg path.inner {
|
||||
stroke: #f7faf9;
|
||||
stroke-width: 41;
|
||||
}
|
||||
|
||||
/* Bottom Taskbar */
|
||||
.toolbar { height: 50px; background: white; border-top: 1px solid #f0f1f2; display: flex; align-items: center; padding: 0 8px; z-index: 100; position: relative;}
|
||||
#taskbar-apps { display: flex; flex: 1; height: 100%; align-items: center; gap: 0px; }
|
||||
.toolbar-time { font-family: 'Fira Code', monospace; font-size: 14px; color: #3b3b3b; text-align: right; line-height: 1.4; padding: 0 10px; margin-left: auto; }
|
||||
.toolbar {
|
||||
height: 50px;
|
||||
background: white;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 8px;
|
||||
z-index: 100;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#taskbar-apps {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
gap: 0px;
|
||||
}
|
||||
|
||||
.toolbar-time {
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 14px;
|
||||
color: #3b3b3b;
|
||||
text-align: right;
|
||||
line-height: 1.4;
|
||||
padding: 0 10px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* Taskbar Items generated by WindowManager */
|
||||
.taskbar-item { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: all 0.15s ease; border-bottom: 2px solid transparent;}
|
||||
.taskbar-item:hover { background: #f8f8f8; }
|
||||
.taskbar-item.active { border-bottom-color: #84d669; background: linear-gradient(to bottom, rgba(132,214,105,0) 50%, rgba(132,214,105,0.1) 100%); }
|
||||
|
||||
.taskbar-item {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s ease;
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.taskbar-item:hover {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.taskbar-item.active {
|
||||
border-bottom-color: #84d669;
|
||||
background: linear-gradient(to bottom, rgba(132, 214, 105, 0) 50%, rgba(132, 214, 105, 0.1) 100%);
|
||||
}
|
||||
|
||||
/* Utility */
|
||||
svg { display: block; }
|
||||
svg {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="build-container">
|
||||
<!-- Left Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<div class="sidebar-item active" title="Home">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
|
||||
<polyline points="9 22 9 12 15 12 15 22"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-item" title="Terminal">
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2"><polyline points="4 17 10 11 4 5"></polyline><line x1="12" y1="19" x2="20" y2="19"></line></svg>
|
||||
<svg class="sidebar-icon" viewBox="0 0 24 24" fill="none" stroke="#3b3b3b" stroke-width="2">
|
||||
<polyline points="4 17 10 11 4 5"></polyline>
|
||||
<line x1="12" y1="19" x2="20" y2="19"></line>
|
||||
</svg>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
|
|
@ -86,16 +309,24 @@
|
|||
<!-- Top Navigation Tabs -->
|
||||
<div class="tabs-container">
|
||||
<div class="tabs-row">
|
||||
<div class="main-tab active"><div class="main-tab-content"><span>//</span><span>BUILD</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>REVIEW</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>DEPLOY</span></div></div>
|
||||
<div class="main-tab"><div class="main-tab-content"><span>//</span><span>MONITOR</span></div></div>
|
||||
<div class="main-tab active">
|
||||
<div class="main-tab-content"><span>//</span><span>BUILD</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>REVIEW</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>DEPLOY</span></div>
|
||||
</div>
|
||||
<div class="main-tab">
|
||||
<div class="main-tab-content"><span>//</span><span>MONITOR</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Workspace container where WindowManager operates -->
|
||||
<div class="workspace" id="desktop-content-inner">
|
||||
|
||||
|
||||
<!-- Background Pattern -->
|
||||
<div class="bg-grid"></div>
|
||||
<svg class="bg-svg" preserveAspectRatio="xMidYMid slice" viewBox="0 0 1000 600">
|
||||
|
|
@ -109,62 +340,80 @@
|
|||
|
||||
<div class="panel-section">
|
||||
<div class="panel-grid">
|
||||
|
||||
|
||||
<!-- HTMX Enabled Desktop Icons that WindowManager catches -->
|
||||
<div class="desktop-icon" data-app-id="vibe" data-app-title="Vibe" hx-get="/suite/partials/chat.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="chat" data-app-title="Chat"
|
||||
hx-get="/suite/partials/chat.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<circle cx="21" cy="21" r="20" stroke="#84d669" stroke-width="2"/>
|
||||
<path d="M14 21h14M21 14v14" stroke="#84d669" stroke-width="2"/>
|
||||
<circle cx="21" cy="21" r="20" stroke="#84d669" stroke-width="2" />
|
||||
<path d="M14 21h14M21 14v14" stroke="#84d669" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Mantis</div>
|
||||
<div class="panel-card-label">Chat</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="tasks" data-app-title="Tasks" hx-get="/suite/partials/tasks.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="vibe" data-app-title="Vibe"
|
||||
hx-get="/suite/partials/vibe.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<rect x="2" y="2" width="38" height="38" rx="4" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="12" y1="12" x2="30" y2="12" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="12" y1="21" x2="30" y2="21" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="12" y1="30" x2="24" y2="30" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<circle cx="21" cy="21" r="20" stroke="#84d669" stroke-width="2" />
|
||||
<path d="M12 14l8 7-8 7" stroke="#84d669" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round" />
|
||||
<line x1="22" y1="28" x2="32" y2="28" stroke="#84d669" stroke-width="2"
|
||||
stroke-linecap="round" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Vibe</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="tasks" data-app-title="Tasks"
|
||||
hx-get="/suite/tasks/task-window.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<rect x="2" y="2" width="38" height="38" rx="4" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="12" y1="12" x2="30" y2="12" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="12" y1="21" x2="30" y2="21" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="12" y1="30" x2="24" y2="30" stroke="#3b3b3b" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Tasks</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="terminal" data-app-title="Terminal" hx-get="/suite/partials/terminal.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="terminal" data-app-title="Terminal"
|
||||
hx-get="/suite/partials/terminal.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<rect x="2" y="4" width="38" height="34" rx="4" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="14" x2="32" y2="14" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="22" x2="28" y2="22" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="30" x2="24" y2="30" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<rect x="2" y="4" width="38" height="34" rx="4" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="14" x2="32" y2="14" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="22" x2="28" y2="22" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="30" x2="24" y2="30" stroke="#3b3b3b" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Terminal</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="explorer" data-app-title="Explorer" hx-get="/suite/partials/explorer.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="explorer" data-app-title="Explorer"
|
||||
hx-get="/suite/partials/explorer.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<rect x="2" y="2" width="38" height="38" rx="4" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="10" x2="32" y2="10" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="18" x2="28" y2="18" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="26" x2="32" y2="26" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="10" y1="34" x2="24" y2="34" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<rect x="2" y="2" width="38" height="38" rx="4" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="10" x2="32" y2="10" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="18" x2="28" y2="18" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="26" x2="32" y2="26" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="10" y1="34" x2="24" y2="34" stroke="#3b3b3b" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Explorer</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="editor" data-app-title="Editor" hx-get="/suite/partials/editor.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="editor" data-app-title="Editor"
|
||||
hx-get="/suite/partials/editor.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<polyline points="4 8 12 2 20 8" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="12" y1="2" x2="12" y2="24" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<polyline points="22 16 30 10 38 16" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<line x1="30" y1="10" x2="30" y2="32" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<polyline points="4 8 12 2 20 8" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="12" y1="2" x2="12" y2="24" stroke="#3b3b3b" stroke-width="2" />
|
||||
<polyline points="22 16 30 10 38 16" stroke="#3b3b3b" stroke-width="2" />
|
||||
<line x1="30" y1="10" x2="30" y2="32" stroke="#3b3b3b" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Editor</div>
|
||||
</div>
|
||||
|
||||
<div class="desktop-icon" data-app-id="browser" data-app-title="Browser" hx-get="/suite/partials/browser.html" hx-swap="none">
|
||||
<div class="desktop-icon" data-app-id="browser" data-app-title="Browser"
|
||||
hx-get="/suite/partials/browser.html" hx-swap="none">
|
||||
<svg class="panel-card-icon" viewBox="0 0 42 42" fill="none">
|
||||
<rect x="2" y="4" width="38" height="34" rx="4" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<circle cx="14" cy="16" r="4" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<path d="M6 34a6 6 0 0 1 6-6h10a6 6 0 0 1 6 6v2H6v-2z" stroke="#3b3b3b" stroke-width="2"/>
|
||||
<rect x="2" y="4" width="38" height="34" rx="4" stroke="#3b3b3b" stroke-width="2" />
|
||||
<circle cx="14" cy="16" r="4" stroke="#3b3b3b" stroke-width="2" />
|
||||
<path d="M6 34a6 6 0 0 1 6-6h10a6 6 0 0 1 6 6v2H6v-2z" stroke="#3b3b3b" stroke-width="2" />
|
||||
</svg>
|
||||
<div class="panel-card-label">Browser</div>
|
||||
</div>
|
||||
|
|
@ -195,7 +444,7 @@
|
|||
const now = new Date();
|
||||
const timeEl = document.getElementById('clock-time');
|
||||
const dateEl = document.getElementById('clock-date');
|
||||
if(timeEl) timeEl.textContent = now.toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
|
||||
if(dateEl) dateEl.textContent = now.toLocaleDateString();
|
||||
if (timeEl) timeEl.textContent = now.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
|
||||
if (dateEl) dateEl.textContent = now.toLocaleDateString();
|
||||
}, 1000);
|
||||
</script>
|
||||
73
ui/suite/partials/minibar.html
Normal file
73
ui/suite/partials/minibar.html
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<!-- Minibar Component — Top-left navigation -->
|
||||
<style>
|
||||
.minibar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 28px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 12px;
|
||||
z-index: 9999;
|
||||
font-family: 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
.minibar-brand {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.minibar-brand-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.minibar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.minibar-btn {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background: transparent;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s;
|
||||
font-size: 13px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.minibar-btn:hover {
|
||||
background: #e0e0e0;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="minibar" id="minibar">
|
||||
<div class="minibar-brand">
|
||||
<svg class="minibar-brand-icon" viewBox="0 0 24 24" fill="none" stroke="#84d669" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<path d="M8 12l3 3 5-5" />
|
||||
</svg>
|
||||
<span>Agent Farm</span>
|
||||
</div>
|
||||
<div class="minibar-actions">
|
||||
<button class="minibar-btn" title="Settings" type="button">⚙</button>
|
||||
<button class="minibar-btn" title="Account" type="button">👤</button>
|
||||
</div>
|
||||
</div>
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,7 +1,7 @@
|
|||
/* =============================================================================
|
||||
AUTOTASK - SENTIENT THEME
|
||||
Dark UI with Neon Yellow/Lime Accents (#CDFE00)
|
||||
Pixel-perfect match to Mantis Farm Dashboard
|
||||
Pixel-perfect match to Agent Dashboard
|
||||
============================================================================= */
|
||||
|
||||
/* =============================================================================
|
||||
|
|
@ -1166,10 +1166,12 @@ body:has(.autotask-container) {
|
|||
}
|
||||
|
||||
@keyframes blink {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
@ -1224,10 +1226,12 @@ body:has(.autotask-container) {
|
|||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
filter: drop-shadow(0 0 4px var(--sentient-accent-glow));
|
||||
}
|
||||
|
||||
50% {
|
||||
filter: drop-shadow(0 0 12px var(--sentient-accent));
|
||||
}
|
||||
|
|
@ -1335,6 +1339,7 @@ body:has(.autotask-container) {
|
|||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
|
|
@ -1596,6 +1601,7 @@ body:has(.autotask-container) {
|
|||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
|
|
@ -1709,4 +1715,4 @@ body:has(.autotask-container) {
|
|||
width: auto;
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* =============================================================================
|
||||
AUTOTASK - SENTIENT THEME
|
||||
Dark UI with Neon Yellow/Lime Accents (#CDFE00)
|
||||
Pixel-perfect match to Mantis Farm Dashboard
|
||||
Pixel-perfect match to Agent Dashboard
|
||||
============================================================================= */
|
||||
|
||||
/* =============================================================================
|
||||
|
|
@ -1166,10 +1166,12 @@ body:has(.autotask-container) {
|
|||
}
|
||||
|
||||
@keyframes blink {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
@ -1224,10 +1226,12 @@ body:has(.autotask-container) {
|
|||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
|
||||
0%,
|
||||
100% {
|
||||
filter: drop-shadow(0 0 4px var(--sentient-accent-glow));
|
||||
}
|
||||
|
||||
50% {
|
||||
filter: drop-shadow(0 0 12px var(--sentient-accent));
|
||||
}
|
||||
|
|
@ -1335,6 +1339,7 @@ body:has(.autotask-container) {
|
|||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
|
|
@ -1596,6 +1601,7 @@ body:has(.autotask-container) {
|
|||
opacity: 0;
|
||||
transform: translateX(20px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(0);
|
||||
|
|
@ -1709,4 +1715,4 @@ body:has(.autotask-container) {
|
|||
width: auto;
|
||||
bottom: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
411
ui/suite/tasks/task-window.css
Normal file
411
ui/suite/tasks/task-window.css
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
/* Task Window — Unified Tasks Dashboard Styles */
|
||||
|
||||
.tw-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
font-family: 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
TAB HEADER
|
||||
============================================ */
|
||||
|
||||
.tw-tabs-header {
|
||||
display: flex;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
min-height: 34px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.tw-tab {
|
||||
height: 34px;
|
||||
min-width: 140px;
|
||||
padding: 0 18px;
|
||||
border: none;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
background: transparent;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
transition: all 0.15s;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tw-tab:hover {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.tw-tab.active {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.tw-tab-prefix {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.tw-tab .tw-tab-close {
|
||||
margin-left: 8px;
|
||||
opacity: 0.5;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tw-tab .tw-tab-close:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
PIPELINE TABS
|
||||
============================================ */
|
||||
|
||||
.tw-pipeline-tabs {
|
||||
display: flex;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.tw-pipeline-tab {
|
||||
flex: 1;
|
||||
height: 32px;
|
||||
border: none;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
background: transparent;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.tw-pipeline-tab:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.tw-pipeline-tab:hover {
|
||||
background: #fff;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.tw-pipeline-tab.active {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
FILTERS
|
||||
============================================ */
|
||||
|
||||
.tw-filters {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.tw-filter-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 5px 12px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.tw-filter-chip:hover {
|
||||
border-color: #84d669;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.tw-filter-chip.active {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
border-color: #84d669;
|
||||
}
|
||||
|
||||
.tw-filter-icon {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
INTENT BAR
|
||||
============================================ */
|
||||
|
||||
.tw-intent-bar {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.tw-intent-input {
|
||||
flex: 1;
|
||||
padding: 8px 14px;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 6px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
color: #3b3b3b;
|
||||
outline: none;
|
||||
transition: border-color 0.15s;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.tw-intent-input:focus {
|
||||
border-color: #84d669;
|
||||
box-shadow: 0 0 0 3px rgba(132, 214, 105, 0.15);
|
||||
}
|
||||
|
||||
.tw-intent-input::placeholder {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.tw-intent-run {
|
||||
padding: 8px 20px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.tw-intent-run:hover {
|
||||
background: #72c458;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(132, 214, 105, 0.3);
|
||||
}
|
||||
|
||||
.tw-intent-run:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
SPLIT VIEW (task list + detail)
|
||||
============================================ */
|
||||
|
||||
.tw-split-view {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.tw-task-list {
|
||||
width: 280px;
|
||||
min-width: 200px;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tw-task-list-empty {
|
||||
padding: 24px 16px;
|
||||
text-align: center;
|
||||
color: #bbb;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.tw-task-detail {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.tw-task-detail-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.tw-task-detail-empty p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.tw-hint {
|
||||
font-size: 12px;
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
TASK LIST ITEMS
|
||||
============================================ */
|
||||
|
||||
.tw-task-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 10px 16px;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
}
|
||||
|
||||
.tw-task-item:hover {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.tw-task-item.active {
|
||||
background: rgba(132, 214, 105, 0.08);
|
||||
border-left: 3px solid #84d669;
|
||||
}
|
||||
|
||||
.tw-task-status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tw-task-status-dot.running {
|
||||
background: #84d669;
|
||||
}
|
||||
|
||||
.tw-task-status-dot.pending {
|
||||
background: #f59e0b;
|
||||
}
|
||||
|
||||
.tw-task-status-dot.completed {
|
||||
background: #3b82f6;
|
||||
}
|
||||
|
||||
.tw-task-status-dot.failed {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.tw-task-status-dot.paused {
|
||||
background: #888;
|
||||
}
|
||||
|
||||
.tw-task-item-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.tw-task-item-name {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.tw-task-item-type {
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
AGENT PROFILE VIEW
|
||||
============================================ */
|
||||
|
||||
.tw-agent-profile {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.tw-agent-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
margin-bottom: 24px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.tw-agent-avatar {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 50%;
|
||||
background: #84d669;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tw-agent-meta {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tw-agent-title {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #3b3b3b;
|
||||
margin: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.tw-agent-subtitle {
|
||||
font-size: 12px;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
.tw-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.tw-section-title {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: #888;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.tw-stat-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.tw-stat-card {
|
||||
padding: 12px;
|
||||
background: #f8f8f8;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.tw-stat-value {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.tw-stat-label {
|
||||
font-size: 10px;
|
||||
color: #888;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.3px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
189
ui/suite/tasks/task-window.html
Normal file
189
ui/suite/tasks/task-window.html
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
<!-- Task Window — Unified Tasks Dashboard (Phase 2) -->
|
||||
<link rel="stylesheet" href="/suite/tasks/task-window.css" />
|
||||
|
||||
<div class="tw-container" id="taskWindow">
|
||||
<!-- Tab Header -->
|
||||
<div class="tw-tabs-header" id="twTabsHeader">
|
||||
<button class="tw-tab active" data-tab="dashboard" id="tabDashboard">
|
||||
<span class="tw-tab-prefix">//</span> DASHBOARD
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Tab Content: Dashboard -->
|
||||
<div class="tw-tab-content active" id="tabContentDashboard">
|
||||
<!-- Pipeline Tabs -->
|
||||
<div class="tw-pipeline-tabs">
|
||||
<button class="tw-pipeline-tab" data-stage="plan">// PLAN</button>
|
||||
<button class="tw-pipeline-tab active" data-stage="build">// BUILD</button>
|
||||
<button class="tw-pipeline-tab" data-stage="review">// REVIEW</button>
|
||||
<button class="tw-pipeline-tab" data-stage="deploy">// DEPLOY</button>
|
||||
<button class="tw-pipeline-tab" data-stage="monitor">// MONITOR</button>
|
||||
</div>
|
||||
|
||||
<!-- Filter Chips -->
|
||||
<div class="tw-filters">
|
||||
<button class="tw-filter-chip active" data-filter="all">
|
||||
<span class="tw-filter-icon">■</span> All
|
||||
</button>
|
||||
<button class="tw-filter-chip" data-filter="active">
|
||||
<span class="tw-filter-icon">⚡</span> Active
|
||||
</button>
|
||||
<button class="tw-filter-chip" data-filter="completed">
|
||||
<span class="tw-filter-icon">✅</span> Complete
|
||||
</button>
|
||||
<button class="tw-filter-chip" data-filter="paused">
|
||||
<span class="tw-filter-icon">⏸</span> Paused
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Intent Bar -->
|
||||
<div class="tw-intent-bar">
|
||||
<input type="text" class="tw-intent-input" id="intentInput"
|
||||
placeholder="What would you like to do? e.g. 'create a CRM'" />
|
||||
<button class="tw-intent-run" id="intentRunBtn" type="button">RUN</button>
|
||||
</div>
|
||||
|
||||
<!-- Tasks List + Detail split -->
|
||||
<div class="tw-split-view">
|
||||
<div class="tw-task-list" id="taskList" hx-get="/api/ui/tasks?filter=all" hx-trigger="load"
|
||||
hx-swap="innerHTML">
|
||||
<div class="tw-task-list-empty">Loading tasks...</div>
|
||||
</div>
|
||||
<div class="tw-task-detail" id="taskDetail">
|
||||
<div class="tw-task-detail-empty">
|
||||
<p>Select a task</p>
|
||||
<p class="tw-hint">Click on a task from the list to view details.</p>
|
||||
<p class="tw-hint">Bot Database: All apps share the same database tables.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tab Content: Agent Profile (dynamically created) -->
|
||||
<div class="tw-tab-content" id="tabContentAgent" style="display:none;">
|
||||
<div class="tw-agent-profile" id="agentProfileContent">
|
||||
<!-- Loaded via HTMX when an agent tab is clicked -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
function initTaskWindow() {
|
||||
setupTabs();
|
||||
setupPipelineTabs();
|
||||
setupFilters();
|
||||
setupIntentBar();
|
||||
}
|
||||
|
||||
function setupTabs() {
|
||||
var tabsHeader = document.getElementById("twTabsHeader");
|
||||
if (!tabsHeader) return;
|
||||
|
||||
tabsHeader.addEventListener("click", function (e) {
|
||||
var tab = e.target.closest(".tw-tab");
|
||||
if (!tab) return;
|
||||
|
||||
var allTabs = tabsHeader.querySelectorAll(".tw-tab");
|
||||
allTabs.forEach(function (t) { t.classList.remove("active"); });
|
||||
tab.classList.add("active");
|
||||
|
||||
var tabId = tab.getAttribute("data-tab");
|
||||
var allContent = document.querySelectorAll(".tw-tab-content");
|
||||
allContent.forEach(function (c) {
|
||||
c.style.display = "none";
|
||||
c.classList.remove("active");
|
||||
});
|
||||
|
||||
if (tabId === "dashboard") {
|
||||
var dash = document.getElementById("tabContentDashboard");
|
||||
if (dash) { dash.style.display = ""; dash.classList.add("active"); }
|
||||
} else {
|
||||
var agent = document.getElementById("tabContentAgent");
|
||||
if (agent) { agent.style.display = ""; agent.classList.add("active"); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setupPipelineTabs() {
|
||||
var container = document.querySelector(".tw-pipeline-tabs");
|
||||
if (!container) return;
|
||||
|
||||
container.addEventListener("click", function (e) {
|
||||
var tab = e.target.closest(".tw-pipeline-tab");
|
||||
if (!tab) return;
|
||||
|
||||
container.querySelectorAll(".tw-pipeline-tab").forEach(function (t) {
|
||||
t.classList.remove("active");
|
||||
});
|
||||
tab.classList.add("active");
|
||||
});
|
||||
}
|
||||
|
||||
function setupFilters() {
|
||||
var container = document.querySelector(".tw-filters");
|
||||
if (!container) return;
|
||||
|
||||
container.addEventListener("click", function (e) {
|
||||
var chip = e.target.closest(".tw-filter-chip");
|
||||
if (!chip) return;
|
||||
|
||||
container.querySelectorAll(".tw-filter-chip").forEach(function (c) {
|
||||
c.classList.remove("active");
|
||||
});
|
||||
chip.classList.add("active");
|
||||
});
|
||||
}
|
||||
|
||||
function setupIntentBar() {
|
||||
var input = document.getElementById("intentInput");
|
||||
var runBtn = document.getElementById("intentRunBtn");
|
||||
if (!input || !runBtn) return;
|
||||
|
||||
function submitIntent() {
|
||||
var text = input.value.trim();
|
||||
if (!text) return;
|
||||
|
||||
runBtn.disabled = true;
|
||||
runBtn.textContent = "...";
|
||||
|
||||
fetch("/api/autotask/classify", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ intent: text })
|
||||
})
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
input.value = "";
|
||||
runBtn.disabled = false;
|
||||
runBtn.textContent = "RUN";
|
||||
|
||||
if (window.htmx) {
|
||||
htmx.trigger("#taskList", "load");
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.error("Intent submission failed:", err);
|
||||
runBtn.disabled = false;
|
||||
runBtn.textContent = "RUN";
|
||||
});
|
||||
}
|
||||
|
||||
runBtn.addEventListener("click", submitIntent);
|
||||
input.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
submitIntent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", initTaskWindow);
|
||||
} else {
|
||||
initTaskWindow();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
494
ui/suite/vibe/agents-sidebar.css
Normal file
494
ui/suite/vibe/agents-sidebar.css
Normal file
|
|
@ -0,0 +1,494 @@
|
|||
/* Agents & Workspaces Sidebar + Vibe Canvas Styles */
|
||||
|
||||
/* ============================================
|
||||
VIBE CONTAINER
|
||||
============================================ */
|
||||
|
||||
.vibe-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
font-family: 'Fira Code', monospace;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
PIPELINE TABS
|
||||
============================================ */
|
||||
|
||||
.vibe-pipeline {
|
||||
display: flex;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.vibe-pipeline-tab {
|
||||
flex: 1;
|
||||
height: 34px;
|
||||
border: none;
|
||||
border-right: 1px solid #f0f1f2;
|
||||
background: transparent;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.vibe-pipeline-tab:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.vibe-pipeline-tab:hover {
|
||||
background: #fff;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.vibe-pipeline-tab.active {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
VIBE BODY (Canvas + Sidebar)
|
||||
============================================ */
|
||||
|
||||
.vibe-body {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
CANVAS AREA
|
||||
============================================ */
|
||||
|
||||
.vibe-canvas {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.vibe-canvas-empty {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vibe-canvas-icon {
|
||||
font-size: 48px;
|
||||
}
|
||||
|
||||
.vibe-canvas-empty h3 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.vibe-canvas-empty p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.vibe-canvas-prompt {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
}
|
||||
|
||||
.vibe-prompt-input {
|
||||
flex: 1;
|
||||
padding: 10px 16px;
|
||||
border: 2px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
color: #3b3b3b;
|
||||
outline: none;
|
||||
transition: border-color 0.2s;
|
||||
}
|
||||
|
||||
.vibe-prompt-input:focus {
|
||||
border-color: #84d669;
|
||||
box-shadow: 0 0 0 3px rgba(132, 214, 105, 0.15);
|
||||
}
|
||||
|
||||
.vibe-prompt-input::placeholder {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.vibe-prompt-btn {
|
||||
padding: 10px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.vibe-prompt-btn:hover {
|
||||
background: #72c458;
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(132, 214, 105, 0.3);
|
||||
}
|
||||
|
||||
.vibe-prompt-btn:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
/* Steps */
|
||||
.vibe-steps {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
/* Preview */
|
||||
.vibe-preview {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-top: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.vibe-preview-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.vibe-preview-url {
|
||||
flex: 1;
|
||||
padding: 3px 10px;
|
||||
background: #fff;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.vibe-preview-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.vibe-preview-content iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
AGENTS & WORKSPACES SIDEBAR
|
||||
============================================ */
|
||||
|
||||
.agents-sidebar {
|
||||
width: 260px;
|
||||
min-width: 260px;
|
||||
background: #f8f8f8;
|
||||
border-left: 1px solid #f0f1f2;
|
||||
overflow-y: auto;
|
||||
transition: width 0.25s, min-width 0.25s;
|
||||
}
|
||||
|
||||
.agents-sidebar.collapsed {
|
||||
width: 0;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Section */
|
||||
.as-section {
|
||||
border-bottom: 1px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.as-section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 14px 8px 14px;
|
||||
}
|
||||
|
||||
.as-section-header h3 {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: #888;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.as-collapse-btn {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.as-collapse-btn:hover {
|
||||
background: #e0e0e0;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
AGENT CARDS
|
||||
============================================ */
|
||||
|
||||
.as-agent-list {
|
||||
padding: 0 8px;
|
||||
}
|
||||
|
||||
.as-agent-card {
|
||||
background: #fff;
|
||||
border: 1px solid #f0f1f2;
|
||||
border-radius: 8px;
|
||||
padding: 10px 12px;
|
||||
margin-bottom: 6px;
|
||||
cursor: grab;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.as-agent-card:hover {
|
||||
border-color: #84d669;
|
||||
box-shadow: 0 2px 8px rgba(132, 214, 105, 0.1);
|
||||
}
|
||||
|
||||
.as-agent-card.dragging {
|
||||
opacity: 0.5;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.as-agent-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.as-status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.as-status-dot.green {
|
||||
background: #84d669;
|
||||
}
|
||||
|
||||
.as-status-dot.yellow {
|
||||
background: #f59e0b;
|
||||
}
|
||||
|
||||
.as-status-dot.red {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.as-status-dot.gray {
|
||||
background: #ccc;
|
||||
}
|
||||
|
||||
.as-agent-name {
|
||||
flex: 1;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #3b3b3b;
|
||||
}
|
||||
|
||||
.as-drag-handle {
|
||||
color: #ccc;
|
||||
font-size: 14px;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.as-agent-body {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.as-agent-icons {
|
||||
font-size: 12px;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.as-badge {
|
||||
display: inline-block;
|
||||
padding: 1px 6px;
|
||||
border-radius: 3px;
|
||||
font-size: 9px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.badge-evolved {
|
||||
background: #84d669;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-bred {
|
||||
background: #f59e0b;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.badge-wild {
|
||||
background: #ef4444;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Quota Bar */
|
||||
.as-agent-bar {
|
||||
height: 3px;
|
||||
background: #f0f1f2;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.as-bar-fill {
|
||||
height: 100%;
|
||||
background: #84d669;
|
||||
border-radius: 2px;
|
||||
transition: width 0.3s;
|
||||
}
|
||||
|
||||
.as-bar-fill.bred {
|
||||
background: #f59e0b;
|
||||
}
|
||||
|
||||
.as-bar-fill.wild {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
/* Create Agent Button */
|
||||
.as-create-btn {
|
||||
width: calc(100% - 16px);
|
||||
margin: 8px 8px;
|
||||
padding: 8px;
|
||||
border: 2px dashed #e0e0e0;
|
||||
border-radius: 8px;
|
||||
background: transparent;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.as-create-btn:hover {
|
||||
border-color: #84d669;
|
||||
color: #84d669;
|
||||
background: rgba(132, 214, 105, 0.05);
|
||||
}
|
||||
|
||||
/* ============================================
|
||||
WORKSPACES
|
||||
============================================ */
|
||||
|
||||
.as-workspace-list {
|
||||
padding: 0 8px 8px 8px;
|
||||
}
|
||||
|
||||
.as-workspace-item {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.as-workspace-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
padding: 8px 10px;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
background: transparent;
|
||||
font-family: 'Fira Code', monospace;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: #3b3b3b;
|
||||
cursor: pointer;
|
||||
transition: background 0.15s;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.as-workspace-toggle:hover {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.as-workspace-arrow {
|
||||
font-size: 8px;
|
||||
color: #888;
|
||||
width: 8px;
|
||||
transition: transform 0.15s;
|
||||
}
|
||||
|
||||
.as-workspace-count {
|
||||
margin-left: auto;
|
||||
font-size: 10px;
|
||||
background: #e0e0e0;
|
||||
color: #666;
|
||||
padding: 1px 6px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.as-workspace-body {
|
||||
padding: 4px 0 4px 20px;
|
||||
}
|
||||
|
||||
.as-workspace-agent {
|
||||
padding: 4px 10px;
|
||||
font-size: 11px;
|
||||
color: #666;
|
||||
border-left: 2px solid #f0f1f2;
|
||||
}
|
||||
|
||||
.as-workspace-dropzone {
|
||||
margin-top: 4px;
|
||||
padding: 10px;
|
||||
border: 2px dashed #e0e0e0;
|
||||
border-radius: 6px;
|
||||
text-align: center;
|
||||
font-size: 11px;
|
||||
color: #ccc;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.as-workspace-dropzone.drag-over {
|
||||
border-color: #84d669;
|
||||
background: rgba(132, 214, 105, 0.05);
|
||||
color: #84d669;
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue