fix(minecraft): debug dashboard layout problem

This commit is contained in:
Rin
2026-02-18 11:12:19 +08:00
committed by Neko Ayaka
parent a9dc7d52fe
commit ffa0a431b7
3 changed files with 325 additions and 199 deletions
+36 -1
View File
@@ -1176,7 +1176,22 @@ class LayoutManager {
this.startPos = config.type === 'v' ? e.clientX : e.clientY
const style = getComputedStyle(this.root)
this.startSize = Number.parseInt(style.getPropertyValue(config.var), 10)
const raw = style.getPropertyValue(config.var)
const parsed = Number.parseFloat(raw)
const fallbackSize = () => {
if (config.var === '--col-left')
return document.getElementById('left-column')?.getBoundingClientRect().width
if (config.var === '--row-1')
return document.getElementById('logs-section')?.getBoundingClientRect().height
if (config.var === '--row-2')
return document.getElementById('timeline-section')?.getBoundingClientRect().height
if (config.var === '--row-3')
return document.getElementById('llm-section')?.getBoundingClientRect().height
return undefined
}
this.startSize = Number.isFinite(parsed) ? parsed : (fallbackSize() || 200)
el.classList.add('dragging')
document.body.style.cursor = config.type === 'v' ? 'col-resize' : 'row-resize'
@@ -1256,6 +1271,9 @@ class DebugApp {
// Initialize layout
this.layoutManager.init()
// Tabs
this.setupTabs()
// Initialize all panels
Object.values(this.panels).forEach(panel => panel.init())
@@ -1277,6 +1295,23 @@ class DebugApp {
// Connect
this.client.connect()
}
setupTabs() {
const tabs = Array.from(document.querySelectorAll('.tab-button'))
const views = Array.from(document.querySelectorAll('.view'))
const activate = (target) => {
tabs.forEach(btn => btn.classList.toggle('active', btn.dataset.target === target))
views.forEach(view => view.classList.toggle('active', view.id === target))
}
tabs.forEach((btn) => {
btn.addEventListener('click', () => activate(btn.dataset.target))
})
// Default
activate('main-view')
}
}
// =============================================================================
+194 -181
View File
@@ -2,155 +2,148 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Debug Dashboard</title>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="tools.css">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Debug Dashboard</title>
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="tools.css">
</head>
<body>
<!-- Header Bar -->
<header id="header">
<div class="header-left">
<h1>Debug Dashboard</h1>
<div class="status-indicator">
<span id="connection-status" class="status-dot"></span>
<span id="status-text">Disconnected</span>
<!-- Header Bar -->
<header id="header">
<div class="header-left">
<h1>Debug Dashboard</h1>
<div class="status-indicator">
<span id="connection-status" class="status-dot"></span>
<span id="status-text">Disconnected</span>
</div>
</div>
<div class="header-stats">
<div class="stat">
<span class="stat-label">Events</span>
<span id="stat-events" class="stat-value">0</span>
</div>
<div class="stat">
<span class="stat-label">Queue</span>
<span id="stat-queue" class="stat-value">0</span>
</div>
<div class="stat">
<span class="stat-label">LLM Calls</span>
<span id="stat-llm" class="stat-value">0</span>
</div>
</div>
<div class="header-controls">
<button id="clear-logs-btn" title="Clear logs">Clear Logs</button>
<button id="pause-btn" title="Pause updates">Pause</button>
<button id="reconnect-btn" title="Reconnect WebSocket">Reconnect</button>
</div>
</header>
<!-- Tabs -->
<div class="tab-bar">
<button class="tab-button active" data-target="main-view">Dashboard</button>
<button class="tab-button" data-target="tools-view">Tools</button>
</div>
<!-- Main Layout -->
<main id="main-view" class="view active">
<div class="main-layout">
<!-- Left Column -->
<div id="left-column">
<!-- Queue & Processing -->
<section id="queue-section" class="panel">
<div class="panel-header">
<h2>Queue & Processing</h2>
<div class="panel-controls">
<span class="panel-badge" id="queue-count">0</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
<div class="panel-content">
<div id="queue-list" class="queue-list"></div>
<div class="divider"></div>
<div id="processing-info" class="processing-info">
<div class="processing-label">Processing:</div>
<div id="processing-content">Idle</div>
</div>
</div>
</section>
<!-- Reflex State -->
<section id="reflex-section" class="panel">
<div class="panel-header">
<h2>Reflex State</h2>
<div class="panel-controls">
<span class="panel-badge" id="reflex-mode">idle</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="header-stats">
<div class="stat">
<span class="stat-label">Events</span>
<span id="stat-events" class="stat-value">0</span>
</div>
<div class="panel-content">
<div class="kv-row">
<span class="kv-key">Active Behavior:</span>
<span class="kv-value" id="reflex-active-behavior">None</span>
</div>
<div class="stat">
<span class="stat-label">Queue</span>
<span id="stat-queue" class="stat-value">0</span>
<div class="divider"></div>
<div class="subsection-title">Attention</div>
<div class="kv-row">
<span class="kv-key">Last Signal:</span>
<span class="kv-value" id="reflex-signal-type">None</span>
</div>
<div class="stat">
<span class="stat-label">LLM Calls</span>
<span id="stat-llm" class="stat-value">0</span>
<div class="kv-row">
<span class="kv-key">Source:</span>
<span class="kv-value" id="reflex-signal-source">None</span>
</div>
</div>
<div class="header-controls">
<button id="clear-logs-btn" title="Clear logs">Clear Logs</button>
<button id="pause-btn" title="Pause updates">Pause</button>
<button id="reconnect-btn" title="Reconnect WebSocket">Reconnect</button>
</div>
</header>
<div class="divider"></div>
<div class="subsection-title">Social</div>
<div class="kv-row">
<span class="kv-key">Last Speaker:</span>
<span class="kv-value" id="reflex-social-speaker">None</span>
</div>
</div>
</section>
<!-- Main Grid Layout -->
<main id="main-grid">
<!-- Left Column -->
<div id="left-column">
<!-- Queue & Processing -->
<section id="queue-section" class="panel">
<div class="panel-header">
<h2>Queue & Processing</h2>
<div class="panel-controls">
<span class="panel-badge" id="queue-count">0</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="queue-list" class="queue-list"></div>
<div class="divider"></div>
<div id="processing-info" class="processing-info">
<div class="processing-label">Processing:</div>
<div id="processing-content">Idle</div>
</div>
</div>
</section>
<!-- Blackboard -->
<section id="blackboard-section" class="panel">
<div class="panel-header">
<h2>Blackboard</h2>
<div class="panel-controls">
<button id="blackboard-copy-btn" class="icon-btn" title="Copy JSON">📋</button>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<pre id="blackboard-json" class="json-display">{}</pre>
</div>
</section>
</div>
<!-- Reflex State -->
<section id="reflex-section" class="panel">
<div class="panel-header">
<h2>Reflex State</h2>
<div class="panel-controls">
<span class="panel-badge" id="reflex-mode">idle</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div class="kv-row">
<span class="kv-key">Active Behavior:</span>
<span class="kv-value" id="reflex-active-behavior">None</span>
</div>
<div class="divider"></div>
<div class="subsection-title">Attention</div>
<div class="kv-row">
<span class="kv-key">Last Signal:</span>
<span class="kv-value" id="reflex-signal-type">None</span>
</div>
<div class="kv-row">
<span class="kv-key">Source:</span>
<span class="kv-value" id="reflex-signal-source">None</span>
</div>
<div class="divider"></div>
<div class="subsection-title">Social</div>
<div class="kv-row">
<span class="kv-key">Last Speaker:</span>
<span class="kv-value" id="reflex-social-speaker">None</span>
</div>
</div>
</section>
<!-- Blackboard -->
<section id="blackboard-section" class="panel">
<div class="panel-header">
<h2>Blackboard</h2>
<div class="panel-controls">
<button id="blackboard-copy-btn" class="icon-btn" title="Copy JSON">📋</button>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<pre id="blackboard-json" class="json-display">{}</pre>
</div>
</section>
<!-- Tools Panel -->
<section id="tools-section" class="panel">
<div class="panel-header">
<h2>Tools</h2>
<div class="panel-controls">
<input type="search" id="tools-search" placeholder="Filter tools..." />
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="tools-grid" class="tools-grid"></div>
</div>
</section>
</div>
<!-- Splitter V1 (Left vs Logs/Timeline/etc) -->
<div class="splitter-v" id="splitter-v1"></div>
<!-- Splitter V1 (Left vs Right Grid) -->
<div class="splitter-v" id="splitter-v1"></div>
<!-- Right Grid Container -->
<div id="main-grid">
<!-- Right Column: Logs -->
<section id="logs-section" class="panel">
<div class="panel-header">
<h2>Logs</h2>
<div class="panel-controls">
<input type="search" id="log-search" placeholder="Search logs..." />
<select id="log-level-filter">
<option value="all">All Levels</option>
<option value="ERROR">ERROR</option>
<option value="WARN">WARN</option>
<option value="INFO">INFO</option>
<option value="DEBUG">DEBUG</option>
</select>
<label class="checkbox-label">
<input type="checkbox" id="auto-scroll" checked />
Auto-scroll
</label>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="logs-container" class="logs-container"></div>
<div class="panel-header">
<h2>Logs</h2>
<div class="panel-controls">
<input type="search" id="log-search" placeholder="Search logs..." />
<select id="log-level-filter">
<option value="all">All Levels</option>
<option value="ERROR">ERROR</option>
<option value="WARN">WARN</option>
<option value="INFO">INFO</option>
<option value="DEBUG">DEBUG</option>
</select>
<label class="checkbox-label">
<input type="checkbox" id="auto-scroll" checked />
Auto-scroll
</label>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="logs-container" class="logs-container"></div>
</div>
</section>
<!-- Splitter H1 (Logs vs Timeline) -->
@@ -158,31 +151,31 @@
<!-- Timeline: Event Trace View -->
<section id="timeline-section" class="panel">
<div class="panel-header">
<h2>Event Timeline</h2>
<div class="panel-controls">
<input type="search" id="timeline-search" placeholder="Filter events..." />
<select id="timeline-type-filter">
<option value="all">All Types</option>
<option value="raw:">Raw Events</option>
<option value="signal:">Signals</option>
</select>
<button id="timeline-clear-btn" class="icon-btn" title="Clear timeline">🗑️</button>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
<div class="panel-header">
<h2>Event Timeline</h2>
<div class="panel-controls">
<input type="search" id="timeline-search" placeholder="Filter events..." />
<select id="timeline-type-filter">
<option value="all">All Types</option>
<option value="raw:">Raw Events</option>
<option value="signal:">Signals</option>
</select>
<button id="timeline-clear-btn" class="icon-btn" title="Clear timeline">🗑️</button>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
<div class="panel-content">
<div id="timeline-container" class="timeline-container">
<div id="timeline-list" class="timeline-list"></div>
</div>
<div id="trace-detail" class="trace-detail hidden">
<div class="trace-detail-header">
<span id="trace-detail-title">Trace Details</span>
<button id="trace-detail-close" class="icon-btn"></button>
</div>
<div id="trace-detail-content"></div>
</div>
</div>
<div class="panel-content">
<div id="timeline-container" class="timeline-container">
<div id="timeline-list" class="timeline-list"></div>
</div>
<div id="trace-detail" class="trace-detail hidden">
<div class="trace-detail-header">
<span id="trace-detail-title">Trace Details</span>
<button id="trace-detail-close" class="icon-btn"></button>
</div>
<div id="trace-detail-content"></div>
</div>
</div>
</section>
<!-- Splitter H2 (Timeline vs LLM) -->
@@ -190,16 +183,16 @@
<!-- Bottom Row: LLM Traces -->
<section id="llm-section" class="panel">
<div class="panel-header">
<h2>LLM Traces</h2>
<div class="panel-controls">
<span class="panel-badge" id="llm-count">0</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="llm-list" class="llm-list"></div>
<div class="panel-header">
<h2>LLM Traces</h2>
<div class="panel-controls">
<span class="panel-badge" id="llm-count">0</span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="llm-list" class="llm-list"></div>
</div>
</section>
<!-- Splitter H3 (LLM vs Saliency) -->
@@ -207,23 +200,43 @@
<!-- Bottom Row: Saliency -->
<section id="saliency-section" class="panel">
<div class="panel-header">
<h2>Saliency Heatmap</h2>
<div class="panel-controls">
<span>Slot: <span id="saliency-slot" class="panel-badge">0</span></span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
<div class="panel-header">
<h2>Saliency Heatmap</h2>
<div class="panel-controls">
<span>Slot: <span id="saliency-slot" class="panel-badge">0</span></span>
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
<div class="panel-content">
<div class="saliency-container">
<canvas id="saliency-canvas"></canvas>
<div id="saliency-labels" class="saliency-labels"></div>
</div>
</div>
<div class="panel-content">
<div class="saliency-container">
<canvas id="saliency-canvas"></canvas>
<div id="saliency-labels" class="saliency-labels"></div>
</div>
</div>
</section>
</main>
</div>
</div>
</main>
<script src="app.js"></script>
<!-- Tools View -->
<section id="tools-view" class="view">
<div class="tools-view-shell">
<section id="tools-section" class="panel full-height">
<div class="panel-header">
<h2>Tools</h2>
<div class="panel-controls">
<input type="search" id="tools-search" placeholder="Filter tools..." />
<button class="icon-btn maximize-btn" title="Toggle maximize"></button>
</div>
</div>
<div class="panel-content">
<div id="tools-grid" class="tools-grid"></div>
</div>
</section>
</div>
</section>
<script src="app.js"></script>
</body>
</html>
+95 -17
View File
@@ -19,10 +19,10 @@
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
/* Resizable Grid Defaults */
--col-left: 350px;
--row-1: 300px;
--row-2: 200px;
--row-3: 200px;
--col-left: clamp(260px, 24vw, 420px);
--row-1: clamp(220px, 35vh, 1fr);
--row-2: clamp(180px, 28vh, 1fr);
--row-3: clamp(180px, 26vh, 1fr);
}
/* Base Styles */
@@ -58,6 +58,42 @@ body {
flex-shrink: 0;
}
/* Tabs */
.tab-bar {
display: flex;
gap: 8px;
padding: 8px 8px 0 8px;
background-color: var(--bg-primary);
border-bottom: 1px solid var(--border-color);
height: 40px;
box-sizing: border-box;
}
.tab-button {
padding: 6px 12px;
font-size: 12px;
background: var(--bg-secondary);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: 4px 4px 0 0;
cursor: pointer;
}
.tab-button.active {
background: var(--bg-tertiary);
border-bottom-color: var(--bg-tertiary);
font-weight: 600;
}
.view {
display: none;
height: calc(100vh - 48px - 40px);
}
.view.active {
display: block;
}
.header-left {
display: flex;
align-items: center;
@@ -145,36 +181,77 @@ button:hover,
#main-grid {
display: grid;
/* Columns: Left Panel | Splitter | Right Content */
grid-template-columns: var(--col-left) 8px 1fr;
grid-template-columns: 1fr;
/* Rows: Logs | Splitter | Timeline | Splitter | LLM | Splitter | Saliency */
grid-template-rows: var(--row-1) 8px var(--row-2) 8px var(--row-3) 8px 1fr;
grid-template-rows:
minmax(var(--row-1), 1fr) 8px minmax(var(--row-2), 1fr) 8px minmax(var(--row-3), 1fr) 8px 1fr;
gap: 0;
padding: 8px;
height: calc(100vh - 48px);
padding: 0;
height: 100%;
overflow: hidden;
align-items: stretch;
align-content: stretch;
}
#left-column {
display: flex;
flex-direction: column;
gap: 8px;
grid-column: 1 / 2;
grid-row: 1 / -1;
/* Span full height */
overflow: hidden;
overflow: auto;
padding-right: 4px;
/* Padding for visual separation */
min-height: 0;
width: var(--col-left);
flex-shrink: 0;
height: 100%;
}
/* Keep left-column panels visible; let tools consume remaining space */
#left-column>.panel {
flex: 0 0 auto;
}
#tools-section {
flex: 1 1 auto;
min-height: 240px;
}
/* Tools standalone view */
#tools-view {
padding: 8px;
box-sizing: border-box;
}
.tools-view-shell {
height: 100%;
}
.panel.full-height {
height: 100%;
}
/* Main layout wrapper: left column + splitter + right grid */
.main-layout {
display: flex;
height: calc(100vh - 48px - 40px);
padding: 8px;
gap: 8px;
box-sizing: border-box;
}
#main-grid {
flex: 1 1 auto;
min-height: 0;
padding: 8px;
}
/* Splitters */
.splitter-v {
grid-row: 1 / -1;
grid-column: 2 / 3;
cursor: col-resize;
background-color: transparent;
width: 8px;
z-index: 10;
position: relative;
flex: 0 0 8px;
}
.splitter-v::after {
@@ -271,6 +348,7 @@ button:hover,
border: 1px solid var(--border-color);
border-radius: 4px;
overflow: hidden;
min-height: 0;
}
.panel-header {
@@ -664,8 +742,8 @@ button:hover,
.timeline-container {
flex: 1;
overflow-y: auto;
max-height: 300px;
overflow: auto;
min-height: 0;
}
.timeline-list {