5839bc47ce
- Add 'watchdog' to KNOWN_PROFILES (5th agent) - Custom status check via watchdog state file + kanban gateway fallback - New /api/watchdog/status endpoint with scripts, plugins, heartbeat info - Watchdog endpoint bypasses auth (public, non-sensitive) - Update frontend PROFILE_ICONS + cache buster
293 lines
16 KiB
HTML
293 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<meta name="theme-color" content="#0d1117">
|
|
<title>Hermes Command Center</title>
|
|
<link rel="stylesheet" href="/static/style.css?v=13">
|
|
</head>
|
|
<body>
|
|
<div id="app">
|
|
<!-- Desktop Sidebar -->
|
|
<nav class="sidebar" id="sidebar">
|
|
<div class="logo">🎛️ Command Center</div>
|
|
<ul class="nav-links">
|
|
<li><a href="#dashboard" class="active">📊 Dashboard</a></li>
|
|
<li><a href="#agents">💬 Chat</a></li>
|
|
<li><a href="#config">⚙️ Config</a></li>
|
|
<li><a href="#kanban">📋 Kanban</a></li>
|
|
<li><a href="#vault">📚 Vault</a></li>
|
|
<li><a href="#services">🔧 Services</a></li>
|
|
<li><a href="#network">🌐 Network</a></li>
|
|
</ul>
|
|
</nav>
|
|
|
|
<!-- Mobile Bottom Nav -->
|
|
<nav class="bottom-nav" id="bottom-nav">
|
|
<a href="#dashboard" class="nav-item active" data-tab="dashboard">📊<span>Home</span></a>
|
|
<a href="#agents" class="nav-item" data-tab="agents">💬<span>Chat</span></a>
|
|
<a href="#config" class="nav-item" data-tab="config">⚙️<span>Config</span></a>
|
|
<a href="#kanban" class="nav-item" data-tab="kanban">📋<span>Tasks</span></a>
|
|
<a href="#vault" class="nav-item" data-tab="vault">📚<span>Vault</span></a>
|
|
<a href="#network" class="nav-item" data-tab="network">🌐<span>Net</span></a>
|
|
</nav>
|
|
|
|
<main class="content" id="content">
|
|
|
|
<!-- ════════════ Dashboard Panel ════════════ -->
|
|
<section id="dashboard" class="panel">
|
|
<h2 class="panel-title">📊 Dashboard</h2>
|
|
<div class="dash-grid" id="dash-grid">
|
|
<div class="dash-card" id="dash-agents">
|
|
<div class="dash-card-icon">💬</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-agents-val">—</div>
|
|
<div class="dash-card-label">Agents Online</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-card" id="dash-hosts">
|
|
<div class="dash-card-icon">🖥️</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-hosts-val">—</div>
|
|
<div class="dash-card-label">Hosts</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-card" id="dash-files">
|
|
<div class="dash-card-icon">⚙️</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-files-val">—</div>
|
|
<div class="dash-card-label">Config Files</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-card" id="dash-msgs">
|
|
<div class="dash-card-icon">💭</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-msgs-val">—</div>
|
|
<div class="dash-card-label">Chat Messages</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-card" id="dash-tasks">
|
|
<div class="dash-card-icon">✅</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-tasks-val">—</div>
|
|
<div class="dash-card-label">Tasks Done</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-card" id="dash-boards">
|
|
<div class="dash-card-icon">📋</div>
|
|
<div class="dash-card-body">
|
|
<div class="dash-card-value" id="dash-boards-val">—</div>
|
|
<div class="dash-card-label">Kanban Boards</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="dash-section">
|
|
<h3>Quick Actions</h3>
|
|
<div class="dash-actions">
|
|
<button class="btn btn-sm" onclick="window.location.hash='#agents'">💬 Open Chat</button>
|
|
<button class="btn btn-sm" onclick="window.location.hash='#kanban'">📋 View Tasks</button>
|
|
<button class="btn btn-sm" onclick="window.location.hash='#network'">🌐 Check Network</button>
|
|
<button class="btn btn-sm" onclick="refreshDashboard()">🔄 Refresh</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ════════════ Agent Chat Panel ════════════ -->
|
|
<section id="agents" class="panel" hidden>
|
|
<div id="chat-app">
|
|
<div class="chat-header">
|
|
<div class="chat-profile-strip">
|
|
<span class="chat-profiles-label">Agent:</span>
|
|
<div id="chat-profile-tabs" class="chat-profile-tabs"></div>
|
|
</div>
|
|
</div>
|
|
<div id="chat-messages" class="chat-messages">
|
|
<div class="chat-welcome">
|
|
<div class="chat-welcome-icon">💬</div>
|
|
<h3>Agent Chat</h3>
|
|
<p>Select an agent profile above and type a message to start a conversation.</p>
|
|
</div>
|
|
</div>
|
|
<div id="chat-typing" class="chat-typing" hidden>
|
|
<span class="typing-dot"></span>
|
|
<span class="typing-dot"></span>
|
|
<span class="typing-dot"></span>
|
|
<span class="typing-label">Agent is typing...</span>
|
|
</div>
|
|
<div class="chat-input-area">
|
|
<textarea id="chat-input" rows="1" placeholder="Type a message..." maxlength="2000"></textarea>
|
|
<button id="chat-send-btn" class="btn btn-primary" disabled>Send</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ════════════ Config Editor Panel ════════════ -->
|
|
<section id="config" class="panel config-panel" hidden>
|
|
<div class="config-file-list" id="config-file-list">
|
|
<div class="config-header">
|
|
<h2 class="panel-title">⚙️ Config Editor</h2>
|
|
<span class="config-count" id="config-count">0 files</span>
|
|
</div>
|
|
<div class="config-files-container" id="config-files-container">
|
|
<p class="loading-text">Select a panel to open...</p>
|
|
</div>
|
|
</div>
|
|
<div class="config-editor" id="config-editor" hidden>
|
|
<div class="editor-header">
|
|
<button id="config-back-btn" class="btn btn-sm" title="Back to file list">← Back</button>
|
|
<span class="editor-filename" id="editor-filename"></span>
|
|
<div class="editor-actions">
|
|
<button id="config-save-btn" class="btn btn-primary btn-sm" disabled>Saved ✓</button>
|
|
</div>
|
|
</div>
|
|
<div class="editor-body">
|
|
<div class="editor-line-numbers" id="editor-line-numbers"></div>
|
|
<textarea class="editor-textarea" id="config-editor-textarea"
|
|
spellcheck="false" wrap="off" disabled
|
|
placeholder="Select a file to edit..."></textarea>
|
|
</div>
|
|
<div class="editor-status-bar">
|
|
<span id="status-path"></span>
|
|
<span id="status-meta"></span>
|
|
<span id="status-saved" class="status-saved"></span>
|
|
</div>
|
|
</div>
|
|
<div id="config-toast" class="config-toast" hidden></div>
|
|
</section>
|
|
|
|
<!-- ════════════ Kanban Panel ════════════ -->
|
|
<section id="kanban" class="panel" hidden>
|
|
<div class="kanban-header">
|
|
<h2 class="panel-title">📋 Kanban Boards</h2>
|
|
<div class="kanban-controls">
|
|
<select id="kanban-board-select" class="kanban-select" onchange="loadKanbanBoard()">
|
|
<option value="">Select a board...</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div id="kanban-summary" class="kanban-summary">
|
|
<div class="kanban-summary-item"><span class="ks-num" id="ks-done">0</span> Done</div>
|
|
<div class="kanban-summary-item"><span class="ks-num" id="ks-blocked">0</span> Blocked</div>
|
|
<div class="kanban-summary-item"><span class="ks-num" id="ks-ready">0</span> Ready</div>
|
|
<div class="kanban-summary-item"><span class="ks-num" id="ks-todo">0</span> Todo</div>
|
|
<div class="kanban-summary-item"><span class="ks-num" id="ks-total">0</span> Total</div>
|
|
</div>
|
|
<div id="kanban-task-list" class="kanban-task-list">
|
|
<p class="loading-text">Select a board to view tasks...</p>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ════════════ Vault Reader Panel ════════════ -->
|
|
<section id="vault" class="panel" hidden>
|
|
<div id="vault-app">
|
|
<div class="vault-toolbar">
|
|
<button id="vault-toggle-tree" class="vault-btn" title="Toggle file tree">📂</button>
|
|
<div class="vault-search-box">
|
|
<input type="text" id="vault-search-input" placeholder="Search vault..." />
|
|
<div id="vault-search-results" class="vault-search-dropdown" hidden></div>
|
|
</div>
|
|
</div>
|
|
<div class="vault-body">
|
|
<div id="vault-tree" class="vault-tree-panel"></div>
|
|
<div id="vault-content" class="vault-content-panel">
|
|
<div class="vault-welcome">
|
|
<h2>Obsidian Vault</h2>
|
|
<p>Select a file from the tree or search to get started.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ════════════ Services Panel ════════════ -->
|
|
<section id="services" class="panel" hidden>
|
|
<div class="services-panel-header">
|
|
<h2 class="panel-title">🔧 System Services</h2>
|
|
<button class="btn btn-sm" onclick="loadServices()">🔄 Refresh</button>
|
|
</div>
|
|
<div class="services-table-wrap">
|
|
<table class="services-table" id="services-table-svc">
|
|
<thead>
|
|
<tr>
|
|
<th>Service</th>
|
|
<th>Status</th>
|
|
<th>Sub</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="services-tbody-svc">
|
|
<tr><td colspan="4" class="loading-text">Loading services...</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ════════════ Network Dashboard Panel ════════════ -->
|
|
<section id="network" class="panel network-panel" hidden>
|
|
<div class="network-header">
|
|
<h2>🌐 Network Status</h2>
|
|
<div class="network-controls">
|
|
<div class="countdown-bar" id="countdown-bar">
|
|
<div class="countdown-fill" id="countdown-fill"></div>
|
|
</div>
|
|
<button class="btn btn-sm btn-refresh" id="network-refresh-btn" title="Refresh now">⟳</button>
|
|
<label class="auto-refresh-toggle" title="Toggle auto-refresh">
|
|
<input type="checkbox" id="auto-refresh-toggle" checked>
|
|
<span>Auto</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="network-summary" id="network-summary">
|
|
<div class="summary-item online"><span class="summary-count" id="hosts-online">0</span> Online</div>
|
|
<div class="summary-item degraded"><span class="summary-count" id="hosts-degraded">0</span> Degraded</div>
|
|
<div class="summary-item offline"><span class="summary-count" id="hosts-offline">0</span> Offline</div>
|
|
<div class="summary-item total"><span class="summary-count" id="hosts-total">0</span> Total</div>
|
|
</div>
|
|
<div class="network-tabs">
|
|
<button class="tab-btn active" data-tab="hosts">Hosts</button>
|
|
<button class="tab-btn" data-tab="services">Services</button>
|
|
<button class="tab-btn" data-tab="local">Local</button>
|
|
</div>
|
|
<div class="tab-content active" id="tab-hosts">
|
|
<div class="hosts-grid" id="hosts-grid">
|
|
<div class="loading-text">Loading hosts...</div>
|
|
</div>
|
|
</div>
|
|
<div class="tab-content" id="tab-services">
|
|
<div class="services-table-wrap">
|
|
<table class="services-table" id="services-table">
|
|
<thead>
|
|
<tr>
|
|
<th>Service</th><th>Category</th><th>URL / Port</th><th>Status</th><th>Latency</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="services-tbody">
|
|
<tr><td colspan="5" class="loading-text">Loading services...</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="tab-content" id="tab-local">
|
|
<div class="services-table-wrap">
|
|
<table class="services-table" id="local-services-table">
|
|
<thead><tr><th>Address</th><th>Port</th><th>Process</th></tr></thead>
|
|
<tbody id="local-services-tbody">
|
|
<tr><td colspan="3" class="loading-text">Loading local services...</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div class="network-footer">
|
|
<span class="last-updated" id="last-updated">Last updated: —</span>
|
|
<span class="cache-info" id="cache-info"></span>
|
|
</div>
|
|
</section>
|
|
|
|
</main>
|
|
</div>
|
|
<script src="/static/app.js?v=3"></script>
|
|
<script src="/static/vault.js?v=2"></script>
|
|
</body>
|
|
</html>
|