@nexus-cortex/server 4.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cortex/agents/AGENT_PROFILE_GUIDE.md +307 -0
- package/.cortex/agents/README.md +268 -0
- package/.cortex/agents/a-frontend-landing-page-designer.md +41 -0
- package/.cortex/agents/autoresearch-agent.md +49 -0
- package/.cortex/agents/code-reviewer.md +63 -0
- package/.cortex/agents/context-research.md +26 -0
- package/.cortex/agents/doc-writer.md +92 -0
- package/.cortex/agents/explore.md +63 -0
- package/.cortex/agents/new-model-api-integrator-analyst.md +41 -0
- package/.cortex/agents/plan.md +109 -0
- package/.cortex/agents/pr-architecture-reviewer.md +77 -0
- package/.cortex/agents/pr-code-quality.md +78 -0
- package/.cortex/agents/pr-implementer.md +50 -0
- package/.cortex/agents/pr-security-auditor.md +62 -0
- package/.cortex/agents/pr-test-writer.md +67 -0
- package/.cortex/agents/refactor.md +118 -0
- package/.cortex/agents/test-writer.md +72 -0
- package/.cortex/agents/web-researcher.md +72 -0
- package/.cortex/bench/tasks/sample-tasks.json +20 -0
- package/.cortex/commands/compare.md +14 -0
- package/.cortex/commands/deps.md +16 -0
- package/.cortex/commands/diff.md +14 -0
- package/.cortex/commands/explain.md +16 -0
- package/.cortex/commands/find-bug.md +13 -0
- package/.cortex/commands/profile.md +15 -0
- package/.cortex/commands/review.md +18 -0
- package/.cortex/commands/search.md +16 -0
- package/.cortex/commands/test.md +15 -0
- package/.cortex/permissions.dev.json +20 -0
- package/.cortex/permissions.example.json +71 -0
- package/.cortex/permissions.prod.json +63 -0
- package/.cortex/permissions.test.json +19 -0
- package/.cortex/skills/autoresearch/SKILL.md +77 -0
- package/.cortex/skills/autoresearch/personas/README.md +45 -0
- package/.cortex/skills/autoresearch/personas/aggressive-refactor.md +25 -0
- package/.cortex/skills/autoresearch/personas/creative.md +29 -0
- package/.cortex/skills/autoresearch/personas/perf-hunter.md +27 -0
- package/.cortex/skills/autoresearch/personas/precise.md +23 -0
- package/.cortex/skills/autoresearch/personas/root-cause.md +26 -0
- package/.cortex/skills/autoresearch/personas/security-auditor.md +29 -0
- package/.cortex/skills/autoresearch/personas/skeptic-reviewer.md +31 -0
- package/.cortex/skills/autoresearch/personas/test-first.md +25 -0
- package/.cortex/skills/best-of-n/SKILL.md +76 -0
- package/.cortex/skills/cortex/SKILL.md +834 -0
- package/.cortex/skills/cortex-bench/SKILL.md +354 -0
- package/.cortex/skills/docx/SKILL.md +83 -0
- package/.cortex/skills/pdf-documents/SKILL.md +297 -0
- package/.cortex/skills/pdf-documents/sections/01-image-acquisition.md +132 -0
- package/.cortex/skills/pdf-documents/sections/02-ai-image-generation.md +274 -0
- package/.cortex/skills/pdf-documents/sections/03-paper-sizes.md +89 -0
- package/.cortex/skills/pdf-documents/sections/04-design-system.md +549 -0
- package/.cortex/skills/pdf-documents/sections/05-css-print-rules.md +135 -0
- package/.cortex/skills/pdf-documents/sections/06-svg-charts.md +100 -0
- package/.cortex/skills/pdf-documents/sections/07-templates.md +224 -0
- package/.cortex/skills/pdf-documents/sections/08-scaled-output.md +164 -0
- package/.cortex/skills/pdf-documents/sections/09-preview-qa.md +66 -0
- package/.cortex/skills/pdf-documents/sections/10-reading-pdfs.md +499 -0
- package/.cortex/skills/pdf-documents/sections/11-form-filling.md +241 -0
- package/.cortex/skills/pptx/SKILL.md +90 -0
- package/.cortex/skills/resume-analyst/SKILL.md +373 -0
- package/.cortex/skills/verify-work/SKILL.md +74 -0
- package/.cortex/skills/xlsx/SKILL.md +101 -0
- package/.cortex/system-messages/messages/WORK_QUALITY.md +159 -0
- package/.cortex/system-messages/registry.json +18 -0
- package/LICENSE +202 -0
- package/NOTICE +2 -0
- package/README.md +13 -0
- package/bin/cortex-daemon.js +47 -0
- package/bin/cortex-server.js +15 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +513 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/cors.d.ts +10 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +11 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +10 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +15 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/routes/approval.d.ts +2 -0
- package/dist/routes/approval.d.ts.map +1 -0
- package/dist/routes/approval.js +96 -0
- package/dist/routes/approval.js.map +1 -0
- package/dist/routes/config.d.ts +2 -0
- package/dist/routes/config.d.ts.map +1 -0
- package/dist/routes/config.js +70 -0
- package/dist/routes/config.js.map +1 -0
- package/dist/routes/health.d.ts +2 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +1031 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/mcp.d.ts +2 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +251 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/messages.d.ts +5 -0
- package/dist/routes/messages.d.ts.map +1 -0
- package/dist/routes/messages.js +136 -0
- package/dist/routes/messages.js.map +1 -0
- package/dist/routes/middleware.d.ts +2 -0
- package/dist/routes/middleware.d.ts.map +1 -0
- package/dist/routes/middleware.js +146 -0
- package/dist/routes/middleware.js.map +1 -0
- package/dist/routes/models.d.ts +2 -0
- package/dist/routes/models.d.ts.map +1 -0
- package/dist/routes/models.js +29 -0
- package/dist/routes/models.js.map +1 -0
- package/dist/routes/permissions.d.ts +2 -0
- package/dist/routes/permissions.d.ts.map +1 -0
- package/dist/routes/permissions.js +253 -0
- package/dist/routes/permissions.js.map +1 -0
- package/dist/routes/pr.d.ts +2 -0
- package/dist/routes/pr.d.ts.map +1 -0
- package/dist/routes/pr.js +222 -0
- package/dist/routes/pr.js.map +1 -0
- package/dist/routes/sessions.d.ts +2 -0
- package/dist/routes/sessions.d.ts.map +1 -0
- package/dist/routes/sessions.js +628 -0
- package/dist/routes/sessions.js.map +1 -0
- package/dist/routes/system-messages.d.ts +2 -0
- package/dist/routes/system-messages.d.ts.map +1 -0
- package/dist/routes/system-messages.js +146 -0
- package/dist/routes/system-messages.js.map +1 -0
- package/dist/routes/tools.d.ts +2 -0
- package/dist/routes/tools.d.ts.map +1 -0
- package/dist/routes/tools.js +79 -0
- package/dist/routes/tools.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,1031 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* /health endpoint - server status and diagnostics
|
|
3
|
+
* HTML dashboard, holographic preset
|
|
4
|
+
*/
|
|
5
|
+
import { Router } from 'express';
|
|
6
|
+
import { ModularModelRegistry } from '@nexus-cortex/core';
|
|
7
|
+
export const healthRouter = Router();
|
|
8
|
+
healthRouter.get('/health', (req, res) => {
|
|
9
|
+
const registry = new ModularModelRegistry();
|
|
10
|
+
const modelIds = registry.listModels();
|
|
11
|
+
const uptime = process.uptime();
|
|
12
|
+
const uptimeFormatted = `${Math.floor(uptime / 3600)}h ${Math.floor((uptime % 3600) / 60)}m ${Math.floor(uptime % 60)}s`;
|
|
13
|
+
// Group models by provider
|
|
14
|
+
const modelsByProvider = modelIds.reduce((acc, modelId) => {
|
|
15
|
+
const model = registry.getModel(modelId);
|
|
16
|
+
if (!acc[model.provider])
|
|
17
|
+
acc[model.provider] = [];
|
|
18
|
+
acc[model.provider].push({
|
|
19
|
+
id: model.id,
|
|
20
|
+
name: model.displayName,
|
|
21
|
+
contextWindow: model.limits.contextWindow,
|
|
22
|
+
apiPattern: model.api.pattern
|
|
23
|
+
});
|
|
24
|
+
return acc;
|
|
25
|
+
}, {});
|
|
26
|
+
const data = {
|
|
27
|
+
status: 'healthy',
|
|
28
|
+
server: {
|
|
29
|
+
name: 'Nexus Cortex',
|
|
30
|
+
version: '4.0.0',
|
|
31
|
+
uptime: uptimeFormatted,
|
|
32
|
+
uptimeSeconds: Math.floor(uptime),
|
|
33
|
+
nodeVersion: process.version,
|
|
34
|
+
architecture: 'core-library'
|
|
35
|
+
},
|
|
36
|
+
availableProviders: Object.keys(modelsByProvider),
|
|
37
|
+
totalModels: modelIds.length,
|
|
38
|
+
models: modelsByProvider,
|
|
39
|
+
environment: {
|
|
40
|
+
hasAnthropicKey: !!process.env.ANTHROPIC_API_KEY,
|
|
41
|
+
hasOpenAIKey: !!process.env.OPENAI_API_KEY,
|
|
42
|
+
hasGoogleKey: !!process.env.GOOGLE_API_KEY || !!process.env.GEMINI_API_KEY,
|
|
43
|
+
hasXAIKey: !!process.env.XAI_API_KEY,
|
|
44
|
+
hasDeepSeekKey: !!process.env.DEEPSEEK_API_KEY,
|
|
45
|
+
hasHuggingFaceKey: !!process.env.HUGGINGFACE_API_KEY || !!process.env.HUGGINGFACE_TOKEN,
|
|
46
|
+
hasNvidiaKey: !!process.env.NVIDIA_API_KEY
|
|
47
|
+
},
|
|
48
|
+
endpoints: {
|
|
49
|
+
health: '/health',
|
|
50
|
+
models: '/models',
|
|
51
|
+
messages: '/v1/messages'
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const acceptsHtml = req.headers.accept?.includes('text/html');
|
|
55
|
+
if (acceptsHtml) {
|
|
56
|
+
const html = generateHolographicDashboard(data);
|
|
57
|
+
res.setHeader('Content-Type', 'text/html');
|
|
58
|
+
res.send(html);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
res.json(data);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Holographic-preset dashboard.
|
|
66
|
+
*
|
|
67
|
+
* Design tokens:
|
|
68
|
+
* Color: holographic preset (electric blue #00d4ff on near-black #050510)
|
|
69
|
+
* Style: holographic preset (thin border, subtle corners, pulsing glow,
|
|
70
|
+
* gradient dividers, holographic shimmer overlay, badge-outlined buttons)
|
|
71
|
+
* Typography: Oxygen Mono, 12px base
|
|
72
|
+
*/
|
|
73
|
+
function generateHolographicDashboard(data) {
|
|
74
|
+
const providerColors = {
|
|
75
|
+
anthropic: '#d4a574',
|
|
76
|
+
openai: '#00a67e',
|
|
77
|
+
google: '#4285f4',
|
|
78
|
+
xai: '#e8e8e8',
|
|
79
|
+
deepseek: '#00d4ff',
|
|
80
|
+
zhipu: '#6366f1',
|
|
81
|
+
qwen: '#a855f7',
|
|
82
|
+
moonshot: '#f59e0b',
|
|
83
|
+
minimax: '#ec4899',
|
|
84
|
+
openrouter: '#06b6d4',
|
|
85
|
+
gemma: '#34d399',
|
|
86
|
+
local: '#6b7280',
|
|
87
|
+
huggingface: '#fbbf24',
|
|
88
|
+
};
|
|
89
|
+
const envKeys = [
|
|
90
|
+
{ key: 'hasAnthropicKey', label: 'ANTHROPIC', color: '#d4a574' },
|
|
91
|
+
{ key: 'hasOpenAIKey', label: 'OPENAI', color: '#00a67e' },
|
|
92
|
+
{ key: 'hasGoogleKey', label: 'GOOGLE', color: '#4285f4' },
|
|
93
|
+
{ key: 'hasXAIKey', label: 'XAI', color: '#e8e8e8' },
|
|
94
|
+
{ key: 'hasDeepSeekKey', label: 'DEEPSEEK', color: '#00d4ff' },
|
|
95
|
+
{ key: 'hasHuggingFaceKey', label: 'HUGGINGFACE', color: '#fbbf24' },
|
|
96
|
+
{ key: 'hasNvidiaKey', label: 'NVIDIA', color: '#76b900' },
|
|
97
|
+
];
|
|
98
|
+
return `<!DOCTYPE html>
|
|
99
|
+
<html lang="en">
|
|
100
|
+
<head>
|
|
101
|
+
<meta charset="UTF-8">
|
|
102
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
103
|
+
<title>Cortex Intelligence Dashboard</title>
|
|
104
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
105
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
106
|
+
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;700&family=Oxygen+Mono&display=swap" rel="stylesheet">
|
|
107
|
+
<style>
|
|
108
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
109
|
+
HOLOGRAPHIC THEME
|
|
110
|
+
Colors: #00d4ff primary, #050510 bg, #e8f0ff text
|
|
111
|
+
Style: thin borders, subtle corners, pulsing glow, gradient dividers
|
|
112
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
113
|
+
|
|
114
|
+
:root {
|
|
115
|
+
--holo-primary: #4a90d9;
|
|
116
|
+
--holo-primary-rgb: 74, 144, 217;
|
|
117
|
+
--holo-positive: #4ade80;
|
|
118
|
+
--holo-positive-rgb: 74, 222, 128;
|
|
119
|
+
--holo-negative: #f87171;
|
|
120
|
+
--holo-negative-rgb: 248, 113, 113;
|
|
121
|
+
--holo-bg: #0f172a;
|
|
122
|
+
--holo-bg-secondary: #1e293b;
|
|
123
|
+
--holo-bg-surface: #253347;
|
|
124
|
+
--holo-bg-elevated: #2d3d53;
|
|
125
|
+
--holo-text: #e2e8f0;
|
|
126
|
+
--holo-text-secondary: #b0b8c4;
|
|
127
|
+
--holo-text-muted: #94a3b8;
|
|
128
|
+
--holo-text-heading: #f8fafc;
|
|
129
|
+
--holo-border: #334155;
|
|
130
|
+
--holo-border-subtle: #283548;
|
|
131
|
+
--holo-glow: 0 0 20px rgba(var(--holo-primary-rgb), 0.15);
|
|
132
|
+
--holo-glow-intense: 0 0 30px rgba(var(--holo-primary-rgb), 0.3), 0 0 60px rgba(var(--holo-primary-rgb), 0.1);
|
|
133
|
+
--holo-radius: 6px;
|
|
134
|
+
--holo-font: 'Oxygen Mono', monospace;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
138
|
+
|
|
139
|
+
body {
|
|
140
|
+
font-family: var(--holo-font);
|
|
141
|
+
font-size: 12px;
|
|
142
|
+
line-height: 1.5;
|
|
143
|
+
color: var(--holo-text);
|
|
144
|
+
background: var(--holo-bg);
|
|
145
|
+
min-height: 100vh;
|
|
146
|
+
overflow-x: hidden;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* ── Canvas background with subtle grid ── */
|
|
150
|
+
body::before {
|
|
151
|
+
content: '';
|
|
152
|
+
position: fixed;
|
|
153
|
+
inset: 0;
|
|
154
|
+
background:
|
|
155
|
+
radial-gradient(ellipse at 20% 50%, rgba(var(--holo-primary-rgb), 0.04) 0%, transparent 60%),
|
|
156
|
+
radial-gradient(ellipse at 80% 20%, rgba(0, 255, 136, 0.02) 0%, transparent 50%),
|
|
157
|
+
linear-gradient(180deg, var(--holo-bg) 0%, #080818 100%);
|
|
158
|
+
pointer-events: none;
|
|
159
|
+
z-index: 0;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
body::after {
|
|
163
|
+
content: '';
|
|
164
|
+
position: fixed;
|
|
165
|
+
inset: 0;
|
|
166
|
+
background-image:
|
|
167
|
+
linear-gradient(rgba(var(--holo-primary-rgb), 0.03) 1px, transparent 1px),
|
|
168
|
+
linear-gradient(90deg, rgba(var(--holo-primary-rgb), 0.03) 1px, transparent 1px);
|
|
169
|
+
background-size: 60px 60px;
|
|
170
|
+
pointer-events: none;
|
|
171
|
+
z-index: 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* ── Layout ── */
|
|
175
|
+
.shell {
|
|
176
|
+
position: relative;
|
|
177
|
+
z-index: 1;
|
|
178
|
+
max-width: 1440px;
|
|
179
|
+
margin: 0 auto;
|
|
180
|
+
padding: 24px 20px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
184
|
+
HEADER BAR — minimal header style
|
|
185
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
186
|
+
.header-bar {
|
|
187
|
+
display: flex;
|
|
188
|
+
align-items: center;
|
|
189
|
+
justify-content: space-between;
|
|
190
|
+
padding: 12px 16px;
|
|
191
|
+
background: var(--holo-bg-secondary);
|
|
192
|
+
border: 1px solid var(--holo-border);
|
|
193
|
+
border-radius: var(--holo-radius);
|
|
194
|
+
margin-bottom: 20px;
|
|
195
|
+
position: relative;
|
|
196
|
+
overflow: hidden;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Holographic shimmer overlay on header */
|
|
200
|
+
.header-bar::after {
|
|
201
|
+
content: '';
|
|
202
|
+
position: absolute;
|
|
203
|
+
inset: 0;
|
|
204
|
+
background: linear-gradient(
|
|
205
|
+
135deg,
|
|
206
|
+
transparent 0%,
|
|
207
|
+
rgba(var(--holo-primary-rgb), 0.06) 25%,
|
|
208
|
+
transparent 50%,
|
|
209
|
+
rgba(var(--holo-primary-rgb), 0.06) 75%,
|
|
210
|
+
transparent 100%
|
|
211
|
+
);
|
|
212
|
+
background-size: 200% 200%;
|
|
213
|
+
animation: holo-shimmer 4s ease-in-out infinite;
|
|
214
|
+
pointer-events: none;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
@keyframes holo-shimmer {
|
|
218
|
+
0%, 100% { background-position: 0% 0%; }
|
|
219
|
+
50% { background-position: 100% 100%; }
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.header-title {
|
|
223
|
+
display: flex;
|
|
224
|
+
align-items: center;
|
|
225
|
+
gap: 12px;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.header-title h1 {
|
|
229
|
+
font-family: 'Orbitron', var(--holo-font);
|
|
230
|
+
font-size: 14px;
|
|
231
|
+
font-weight: 500;
|
|
232
|
+
letter-spacing: 0.12em;
|
|
233
|
+
text-transform: uppercase;
|
|
234
|
+
color: var(--holo-text-heading);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.header-title .version {
|
|
238
|
+
font-size: 10px;
|
|
239
|
+
color: var(--holo-text-muted);
|
|
240
|
+
padding: 2px 8px;
|
|
241
|
+
border: 1px solid var(--holo-border-subtle);
|
|
242
|
+
border-radius: var(--holo-radius);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.header-status {
|
|
246
|
+
display: flex;
|
|
247
|
+
align-items: center;
|
|
248
|
+
gap: 16px;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.status-indicator {
|
|
252
|
+
display: flex;
|
|
253
|
+
align-items: center;
|
|
254
|
+
gap: 6px;
|
|
255
|
+
font-size: 10px;
|
|
256
|
+
text-transform: uppercase;
|
|
257
|
+
letter-spacing: 0.1em;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.status-dot {
|
|
261
|
+
width: 6px;
|
|
262
|
+
height: 6px;
|
|
263
|
+
border-radius: 50%;
|
|
264
|
+
background: var(--holo-positive);
|
|
265
|
+
box-shadow: 0 0 8px rgba(var(--holo-positive-rgb), 0.6);
|
|
266
|
+
animation: pulse-dot 2s ease-in-out infinite;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@keyframes pulse-dot {
|
|
270
|
+
0%, 100% { box-shadow: 0 0 8px rgba(var(--holo-positive-rgb), 0.6); }
|
|
271
|
+
50% { box-shadow: 0 0 14px rgba(var(--holo-positive-rgb), 0.9); }
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.status-dot.offline {
|
|
275
|
+
background: var(--holo-negative);
|
|
276
|
+
box-shadow: 0 0 8px rgba(var(--holo-negative-rgb), 0.6);
|
|
277
|
+
animation: none;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.uptime-label {
|
|
281
|
+
font-size: 10px;
|
|
282
|
+
color: var(--holo-text-muted);
|
|
283
|
+
letter-spacing: 0.05em;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
287
|
+
PANEL GRID — 3-column data panels
|
|
288
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
289
|
+
.panel-grid {
|
|
290
|
+
display: grid;
|
|
291
|
+
grid-template-columns: repeat(3, 1fr);
|
|
292
|
+
gap: 16px;
|
|
293
|
+
margin-bottom: 20px;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
@media (max-width: 960px) {
|
|
297
|
+
.panel-grid { grid-template-columns: 1fr; }
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.panel {
|
|
301
|
+
background: var(--holo-bg-secondary);
|
|
302
|
+
border: 1px solid var(--holo-border);
|
|
303
|
+
border-radius: var(--holo-radius);
|
|
304
|
+
overflow: hidden;
|
|
305
|
+
position: relative;
|
|
306
|
+
transition: box-shadow 200ms ease;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.panel:hover {
|
|
310
|
+
box-shadow: var(--holo-glow);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
.panel-header {
|
|
314
|
+
display: flex;
|
|
315
|
+
align-items: center;
|
|
316
|
+
justify-content: space-between;
|
|
317
|
+
padding: 10px 14px;
|
|
318
|
+
border-bottom: 1px solid var(--holo-border-subtle);
|
|
319
|
+
background: linear-gradient(90deg, rgba(var(--holo-primary-rgb), 0.04), transparent);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.panel-label {
|
|
323
|
+
font-size: 10px;
|
|
324
|
+
text-transform: uppercase;
|
|
325
|
+
letter-spacing: 0.12em;
|
|
326
|
+
color: var(--holo-text-muted);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
.panel-badge {
|
|
330
|
+
font-size: 9px;
|
|
331
|
+
color: var(--holo-primary);
|
|
332
|
+
border: 1px solid rgba(var(--holo-primary-rgb), 0.3);
|
|
333
|
+
padding: 1px 6px;
|
|
334
|
+
border-radius: var(--holo-radius);
|
|
335
|
+
letter-spacing: 0.05em;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.panel-body {
|
|
339
|
+
padding: 14px;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/* ── Data rows ── */
|
|
343
|
+
.data-row {
|
|
344
|
+
display: flex;
|
|
345
|
+
justify-content: space-between;
|
|
346
|
+
align-items: center;
|
|
347
|
+
padding: 6px 0;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.data-row + .data-row {
|
|
351
|
+
border-top: 1px solid var(--holo-border-subtle);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
.data-key {
|
|
355
|
+
font-size: 11px;
|
|
356
|
+
color: var(--holo-text-secondary);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.data-val {
|
|
360
|
+
font-size: 11px;
|
|
361
|
+
color: var(--holo-text);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.data-val.accent { color: var(--holo-primary); }
|
|
365
|
+
|
|
366
|
+
/* ── Stat blocks (big numbers) ── */
|
|
367
|
+
.stat-row {
|
|
368
|
+
display: flex;
|
|
369
|
+
gap: 16px;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
.stat-block {
|
|
373
|
+
flex: 1;
|
|
374
|
+
text-align: center;
|
|
375
|
+
padding: 12px 8px;
|
|
376
|
+
background: var(--holo-bg-surface);
|
|
377
|
+
border: 1px solid var(--holo-border-subtle);
|
|
378
|
+
border-radius: var(--holo-radius);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.stat-num {
|
|
382
|
+
font-family: 'Orbitron', var(--holo-font);
|
|
383
|
+
font-size: 28px;
|
|
384
|
+
font-weight: 500;
|
|
385
|
+
color: var(--holo-primary);
|
|
386
|
+
line-height: 1.1;
|
|
387
|
+
text-shadow: 0 0 20px rgba(var(--holo-primary-rgb), 0.3);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.stat-label {
|
|
391
|
+
font-size: 9px;
|
|
392
|
+
text-transform: uppercase;
|
|
393
|
+
letter-spacing: 0.12em;
|
|
394
|
+
color: var(--holo-text-muted);
|
|
395
|
+
margin-top: 6px;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
399
|
+
API KEY MATRIX — horizontal bar indicators
|
|
400
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
401
|
+
.key-row {
|
|
402
|
+
display: flex;
|
|
403
|
+
align-items: center;
|
|
404
|
+
gap: 10px;
|
|
405
|
+
padding: 5px 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.key-row + .key-row {
|
|
409
|
+
border-top: 1px solid var(--holo-border-subtle);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
.key-name {
|
|
413
|
+
font-size: 10px;
|
|
414
|
+
letter-spacing: 0.08em;
|
|
415
|
+
color: var(--holo-text-secondary);
|
|
416
|
+
width: 100px;
|
|
417
|
+
flex-shrink: 0;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
.key-bar {
|
|
421
|
+
flex: 1;
|
|
422
|
+
height: 4px;
|
|
423
|
+
border-radius: 2px;
|
|
424
|
+
background: var(--holo-bg-surface);
|
|
425
|
+
position: relative;
|
|
426
|
+
overflow: hidden;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.key-bar-fill {
|
|
430
|
+
height: 100%;
|
|
431
|
+
border-radius: 2px;
|
|
432
|
+
transition: width 600ms ease;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.key-bar-fill.active {
|
|
436
|
+
width: 100%;
|
|
437
|
+
animation: bar-glow 2s ease-in-out infinite;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.key-bar-fill.inactive {
|
|
441
|
+
width: 15%;
|
|
442
|
+
background: rgba(var(--holo-negative-rgb), 0.3);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
@keyframes bar-glow {
|
|
446
|
+
0%, 100% { opacity: 0.7; }
|
|
447
|
+
50% { opacity: 1; }
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.key-status {
|
|
451
|
+
font-size: 9px;
|
|
452
|
+
letter-spacing: 0.1em;
|
|
453
|
+
text-transform: uppercase;
|
|
454
|
+
width: 36px;
|
|
455
|
+
text-align: right;
|
|
456
|
+
flex-shrink: 0;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.key-status.set { color: var(--holo-positive); }
|
|
460
|
+
.key-status.missing { color: rgba(var(--holo-negative-rgb), 0.5); }
|
|
461
|
+
|
|
462
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
463
|
+
MODEL REGISTRY — provider-grouped collapsible list
|
|
464
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
465
|
+
.registry-panel {
|
|
466
|
+
background: var(--holo-bg-secondary);
|
|
467
|
+
border: 1px solid var(--holo-border);
|
|
468
|
+
border-radius: var(--holo-radius);
|
|
469
|
+
overflow: hidden;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
.registry-header {
|
|
473
|
+
display: flex;
|
|
474
|
+
align-items: center;
|
|
475
|
+
justify-content: space-between;
|
|
476
|
+
padding: 10px 14px;
|
|
477
|
+
border-bottom: 1px solid var(--holo-border-subtle);
|
|
478
|
+
background: linear-gradient(90deg, rgba(var(--holo-primary-rgb), 0.04), transparent);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
.registry-body {
|
|
482
|
+
max-height: 520px;
|
|
483
|
+
overflow-y: auto;
|
|
484
|
+
scrollbar-width: thin;
|
|
485
|
+
scrollbar-color: var(--holo-border) var(--holo-bg-secondary);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
.registry-body::-webkit-scrollbar { width: 4px; }
|
|
489
|
+
.registry-body::-webkit-scrollbar-track { background: var(--holo-bg-secondary); }
|
|
490
|
+
.registry-body::-webkit-scrollbar-thumb {
|
|
491
|
+
background: var(--holo-border);
|
|
492
|
+
border-radius: 2px;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/* Provider group */
|
|
496
|
+
.provider-group {
|
|
497
|
+
border-bottom: 1px solid var(--holo-border-subtle);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.provider-group:last-child { border-bottom: none; }
|
|
501
|
+
|
|
502
|
+
.provider-head {
|
|
503
|
+
display: flex;
|
|
504
|
+
align-items: center;
|
|
505
|
+
justify-content: space-between;
|
|
506
|
+
padding: 8px 14px;
|
|
507
|
+
cursor: pointer;
|
|
508
|
+
user-select: none;
|
|
509
|
+
transition: background 150ms ease;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
.provider-head:hover {
|
|
513
|
+
background: rgba(var(--holo-primary-rgb), 0.04);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.provider-info {
|
|
517
|
+
display: flex;
|
|
518
|
+
align-items: center;
|
|
519
|
+
gap: 8px;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.provider-dot {
|
|
523
|
+
width: 8px;
|
|
524
|
+
height: 8px;
|
|
525
|
+
border-radius: 50%;
|
|
526
|
+
flex-shrink: 0;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.provider-name {
|
|
530
|
+
font-size: 11px;
|
|
531
|
+
text-transform: uppercase;
|
|
532
|
+
letter-spacing: 0.1em;
|
|
533
|
+
color: var(--holo-text-heading);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.provider-count {
|
|
537
|
+
font-size: 9px;
|
|
538
|
+
color: var(--holo-text-muted);
|
|
539
|
+
padding: 1px 6px;
|
|
540
|
+
border: 1px solid var(--holo-border-subtle);
|
|
541
|
+
border-radius: var(--holo-radius);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.provider-chevron {
|
|
545
|
+
font-size: 10px;
|
|
546
|
+
color: var(--holo-text-muted);
|
|
547
|
+
transition: transform 200ms ease;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
.provider-group.open .provider-chevron {
|
|
551
|
+
transform: rotate(90deg);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.provider-models {
|
|
555
|
+
display: none;
|
|
556
|
+
padding: 0 14px 8px 30px;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.provider-group.open .provider-models {
|
|
560
|
+
display: block;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.model-entry {
|
|
564
|
+
display: flex;
|
|
565
|
+
align-items: baseline;
|
|
566
|
+
justify-content: space-between;
|
|
567
|
+
padding: 4px 0;
|
|
568
|
+
border-top: 1px solid rgba(var(--holo-primary-rgb), 0.04);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
.model-entry:first-child { border-top: none; }
|
|
572
|
+
|
|
573
|
+
.model-id {
|
|
574
|
+
font-size: 11px;
|
|
575
|
+
color: var(--holo-text);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.model-meta {
|
|
579
|
+
display: flex;
|
|
580
|
+
gap: 12px;
|
|
581
|
+
align-items: baseline;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
.model-ctx {
|
|
585
|
+
font-size: 9px;
|
|
586
|
+
color: var(--holo-text-muted);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.model-api {
|
|
590
|
+
font-size: 9px;
|
|
591
|
+
color: var(--holo-primary);
|
|
592
|
+
opacity: 0.6;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
596
|
+
ENDPOINT QUICK-REF — bottom bar
|
|
597
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
598
|
+
.endpoints-bar {
|
|
599
|
+
display: flex;
|
|
600
|
+
align-items: center;
|
|
601
|
+
gap: 24px;
|
|
602
|
+
padding: 10px 14px;
|
|
603
|
+
margin-top: 20px;
|
|
604
|
+
background: var(--holo-bg-secondary);
|
|
605
|
+
border: 1px solid var(--holo-border);
|
|
606
|
+
border-radius: var(--holo-radius);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.endpoint-item {
|
|
610
|
+
display: flex;
|
|
611
|
+
align-items: center;
|
|
612
|
+
gap: 6px;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.endpoint-method {
|
|
616
|
+
font-size: 9px;
|
|
617
|
+
padding: 1px 5px;
|
|
618
|
+
border-radius: var(--holo-radius);
|
|
619
|
+
letter-spacing: 0.05em;
|
|
620
|
+
font-weight: 400;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.endpoint-method.get {
|
|
624
|
+
color: var(--holo-positive);
|
|
625
|
+
border: 1px solid rgba(var(--holo-positive-rgb), 0.3);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.endpoint-method.post {
|
|
629
|
+
color: var(--holo-primary);
|
|
630
|
+
border: 1px solid rgba(var(--holo-primary-rgb), 0.3);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
.endpoint-path {
|
|
634
|
+
font-size: 11px;
|
|
635
|
+
color: var(--holo-text-secondary);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/* ── Pulsing glow on focused panel ── */
|
|
639
|
+
@keyframes glow-pulse {
|
|
640
|
+
0%, 100% { box-shadow: 0 0 15px rgba(var(--holo-primary-rgb), 0.15); }
|
|
641
|
+
50% { box-shadow: 0 0 25px rgba(var(--holo-primary-rgb), 0.3); }
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/* ── Gradient divider ── */
|
|
645
|
+
.gradient-divider {
|
|
646
|
+
height: 1px;
|
|
647
|
+
background: linear-gradient(90deg, transparent, rgba(var(--holo-primary-rgb), 0.3), transparent);
|
|
648
|
+
margin: 16px 0;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/* ── Refresh button — badge-outlined style ── */
|
|
652
|
+
.refresh-btn {
|
|
653
|
+
position: fixed;
|
|
654
|
+
bottom: 20px;
|
|
655
|
+
right: 20px;
|
|
656
|
+
font-family: var(--holo-font);
|
|
657
|
+
font-size: 10px;
|
|
658
|
+
letter-spacing: 0.08em;
|
|
659
|
+
text-transform: uppercase;
|
|
660
|
+
color: var(--holo-primary);
|
|
661
|
+
background: var(--holo-bg-secondary);
|
|
662
|
+
border: 1px solid rgba(var(--holo-primary-rgb), 0.3);
|
|
663
|
+
border-radius: var(--holo-radius);
|
|
664
|
+
padding: 8px 16px;
|
|
665
|
+
cursor: pointer;
|
|
666
|
+
transition: all 200ms ease;
|
|
667
|
+
z-index: 10;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.refresh-btn:hover {
|
|
671
|
+
background: rgba(var(--holo-primary-rgb), 0.08);
|
|
672
|
+
border-color: rgba(var(--holo-primary-rgb), 0.6);
|
|
673
|
+
box-shadow: 0 0 15px rgba(var(--holo-primary-rgb), 0.2);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/* ── Auto-refresh countdown ── */
|
|
677
|
+
.auto-refresh {
|
|
678
|
+
font-size: 9px;
|
|
679
|
+
color: var(--holo-text-muted);
|
|
680
|
+
text-align: right;
|
|
681
|
+
margin-top: 8px;
|
|
682
|
+
letter-spacing: 0.05em;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
/* ═══════════════════════════════════════════════════════════════════════
|
|
686
|
+
DASHBOARD SERVICES — linked cards to port 4001
|
|
687
|
+
═══════════════════════════════════════════════════════════════════════ */
|
|
688
|
+
.services-panel {
|
|
689
|
+
background: var(--holo-bg-secondary);
|
|
690
|
+
border: 1px solid var(--holo-border);
|
|
691
|
+
border-radius: var(--holo-radius);
|
|
692
|
+
margin-bottom: 20px;
|
|
693
|
+
overflow: hidden;
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.services-grid {
|
|
697
|
+
display: grid;
|
|
698
|
+
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
699
|
+
gap: 8px;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
.service-card {
|
|
703
|
+
display: flex;
|
|
704
|
+
align-items: center;
|
|
705
|
+
gap: 10px;
|
|
706
|
+
padding: 10px 12px;
|
|
707
|
+
background: var(--holo-bg-surface);
|
|
708
|
+
border: 1px solid var(--holo-border-subtle);
|
|
709
|
+
border-radius: var(--holo-radius);
|
|
710
|
+
text-decoration: none;
|
|
711
|
+
color: inherit;
|
|
712
|
+
transition: all 200ms ease;
|
|
713
|
+
cursor: pointer;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
.service-card:hover {
|
|
717
|
+
border-color: rgba(var(--holo-primary-rgb), 0.4);
|
|
718
|
+
background: var(--holo-bg-elevated);
|
|
719
|
+
box-shadow: 0 0 12px rgba(var(--holo-primary-rgb), 0.1);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.service-icon {
|
|
723
|
+
font-size: 16px;
|
|
724
|
+
color: var(--holo-primary);
|
|
725
|
+
width: 28px;
|
|
726
|
+
height: 28px;
|
|
727
|
+
display: flex;
|
|
728
|
+
align-items: center;
|
|
729
|
+
justify-content: center;
|
|
730
|
+
background: rgba(var(--holo-primary-rgb), 0.06);
|
|
731
|
+
border: 1px solid rgba(var(--holo-primary-rgb), 0.15);
|
|
732
|
+
border-radius: var(--holo-radius);
|
|
733
|
+
flex-shrink: 0;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
.service-info {
|
|
737
|
+
display: flex;
|
|
738
|
+
flex-direction: column;
|
|
739
|
+
gap: 2px;
|
|
740
|
+
flex: 1;
|
|
741
|
+
min-width: 0;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
.service-name {
|
|
745
|
+
font-size: 11px;
|
|
746
|
+
color: var(--holo-text-heading);
|
|
747
|
+
letter-spacing: 0.04em;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.service-desc {
|
|
751
|
+
font-size: 9px;
|
|
752
|
+
color: var(--holo-text-muted);
|
|
753
|
+
letter-spacing: 0.02em;
|
|
754
|
+
white-space: nowrap;
|
|
755
|
+
overflow: hidden;
|
|
756
|
+
text-overflow: ellipsis;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
.service-arrow {
|
|
760
|
+
font-size: 12px;
|
|
761
|
+
color: var(--holo-text-muted);
|
|
762
|
+
flex-shrink: 0;
|
|
763
|
+
transition: color 200ms ease, transform 200ms ease;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.service-card:hover .service-arrow {
|
|
767
|
+
color: var(--holo-primary);
|
|
768
|
+
transform: translateX(2px);
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/* ── Staggered entry animations ── */
|
|
772
|
+
@keyframes fade-up {
|
|
773
|
+
from { opacity: 0; transform: translateY(8px); }
|
|
774
|
+
to { opacity: 1; transform: translateY(0); }
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
.anim-in {
|
|
778
|
+
animation: fade-up 400ms ease both;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
.anim-d1 { animation-delay: 50ms; }
|
|
782
|
+
.anim-d2 { animation-delay: 120ms; }
|
|
783
|
+
.anim-d3 { animation-delay: 190ms; }
|
|
784
|
+
.anim-d4 { animation-delay: 260ms; }
|
|
785
|
+
.anim-d5 { animation-delay: 330ms; }
|
|
786
|
+
</style>
|
|
787
|
+
</head>
|
|
788
|
+
<body>
|
|
789
|
+
<div class="shell">
|
|
790
|
+
|
|
791
|
+
<!-- ══════ HEADER BAR ══════ -->
|
|
792
|
+
<div class="header-bar anim-in">
|
|
793
|
+
<div class="header-title">
|
|
794
|
+
<h1>Cortex Intelligence Dashboard</h1>
|
|
795
|
+
<span class="version">v${data.server.version}</span>
|
|
796
|
+
</div>
|
|
797
|
+
<div class="header-status">
|
|
798
|
+
<div class="status-indicator">
|
|
799
|
+
<span class="status-dot"></span>
|
|
800
|
+
<span style="color: var(--holo-positive);">${data.status.toUpperCase()}</span>
|
|
801
|
+
</div>
|
|
802
|
+
<span class="uptime-label">${data.server.uptime}</span>
|
|
803
|
+
</div>
|
|
804
|
+
</div>
|
|
805
|
+
|
|
806
|
+
<!-- ══════ DASHBOARD SERVICES — Port 4001 ══════ -->
|
|
807
|
+
<div class="services-panel anim-in anim-d1">
|
|
808
|
+
<div class="panel-header">
|
|
809
|
+
<span class="panel-label">Dashboard Services</span>
|
|
810
|
+
<span class="panel-badge">:4001</span>
|
|
811
|
+
</div>
|
|
812
|
+
<div class="panel-body" style="padding: 10px 14px;">
|
|
813
|
+
<div class="services-grid">
|
|
814
|
+
<a href="#" data-dash-path="/" class="service-card" target="_blank">
|
|
815
|
+
<div class="service-icon">▦</div>
|
|
816
|
+
<div class="service-info">
|
|
817
|
+
<span class="service-name">Sandbox Dashboard</span>
|
|
818
|
+
<span class="service-desc">Live artifact execution viewer</span>
|
|
819
|
+
</div>
|
|
820
|
+
<span class="service-arrow">→</span>
|
|
821
|
+
</a>
|
|
822
|
+
<a href="#" data-dash-path="/tmux" class="service-card" target="_blank">
|
|
823
|
+
<div class="service-icon">☰</div>
|
|
824
|
+
<div class="service-info">
|
|
825
|
+
<span class="service-name">Tmux Sessions</span>
|
|
826
|
+
<span class="service-desc">Persistent terminal sessions & agent monitoring</span>
|
|
827
|
+
</div>
|
|
828
|
+
<span class="service-arrow">→</span>
|
|
829
|
+
</a>
|
|
830
|
+
<a href="#" data-dash-path="/api/sandboxes" class="service-card" target="_blank">
|
|
831
|
+
<div class="service-icon">{}</div>
|
|
832
|
+
<div class="service-info">
|
|
833
|
+
<span class="service-name">Sandboxes API</span>
|
|
834
|
+
<span class="service-desc">GET /api/sandboxes — JSON listing</span>
|
|
835
|
+
</div>
|
|
836
|
+
<span class="service-arrow">→</span>
|
|
837
|
+
</a>
|
|
838
|
+
<a href="#" data-dash-path="/api/tmux/sessions" class="service-card" target="_blank">
|
|
839
|
+
<div class="service-icon">{}</div>
|
|
840
|
+
<div class="service-info">
|
|
841
|
+
<span class="service-name">Tmux API</span>
|
|
842
|
+
<span class="service-desc">GET /api/tmux/sessions — JSON listing</span>
|
|
843
|
+
</div>
|
|
844
|
+
<span class="service-arrow">→</span>
|
|
845
|
+
</a>
|
|
846
|
+
<a href="#" data-dash-path="/health" class="service-card" target="_blank">
|
|
847
|
+
<div class="service-icon">♥</div>
|
|
848
|
+
<div class="service-info">
|
|
849
|
+
<span class="service-name">Dashboard Health</span>
|
|
850
|
+
<span class="service-desc">GET /health — service status</span>
|
|
851
|
+
</div>
|
|
852
|
+
<span class="service-arrow">→</span>
|
|
853
|
+
</a>
|
|
854
|
+
</div>
|
|
855
|
+
</div>
|
|
856
|
+
</div>
|
|
857
|
+
|
|
858
|
+
<!-- ══════ 3-COLUMN PANELS ══════ -->
|
|
859
|
+
<div class="panel-grid">
|
|
860
|
+
|
|
861
|
+
<!-- Server Info -->
|
|
862
|
+
<div class="panel anim-in anim-d1">
|
|
863
|
+
<div class="panel-header">
|
|
864
|
+
<span class="panel-label">System</span>
|
|
865
|
+
<span class="panel-badge">CORE</span>
|
|
866
|
+
</div>
|
|
867
|
+
<div class="panel-body">
|
|
868
|
+
<div class="data-row">
|
|
869
|
+
<span class="data-key">Architecture</span>
|
|
870
|
+
<span class="data-val accent">${data.server.architecture}</span>
|
|
871
|
+
</div>
|
|
872
|
+
<div class="data-row">
|
|
873
|
+
<span class="data-key">Node</span>
|
|
874
|
+
<span class="data-val">${data.server.nodeVersion}</span>
|
|
875
|
+
</div>
|
|
876
|
+
<div class="data-row">
|
|
877
|
+
<span class="data-key">Uptime</span>
|
|
878
|
+
<span class="data-val">${data.server.uptime}</span>
|
|
879
|
+
</div>
|
|
880
|
+
<div class="data-row">
|
|
881
|
+
<span class="data-key">PID</span>
|
|
882
|
+
<span class="data-val" style="color: var(--holo-text-muted);">${process.pid}</span>
|
|
883
|
+
</div>
|
|
884
|
+
<div class="data-row">
|
|
885
|
+
<span class="data-key">Memory</span>
|
|
886
|
+
<span class="data-val" style="color: var(--holo-text-muted);">${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB</span>
|
|
887
|
+
</div>
|
|
888
|
+
</div>
|
|
889
|
+
</div>
|
|
890
|
+
|
|
891
|
+
<!-- Stats -->
|
|
892
|
+
<div class="panel anim-in anim-d2">
|
|
893
|
+
<div class="panel-header">
|
|
894
|
+
<span class="panel-label">Registry</span>
|
|
895
|
+
<span class="panel-badge">LIVE</span>
|
|
896
|
+
</div>
|
|
897
|
+
<div class="panel-body">
|
|
898
|
+
<div class="stat-row">
|
|
899
|
+
<div class="stat-block">
|
|
900
|
+
<div class="stat-num">${data.totalModels}</div>
|
|
901
|
+
<div class="stat-label">Models</div>
|
|
902
|
+
</div>
|
|
903
|
+
<div class="stat-block">
|
|
904
|
+
<div class="stat-num">${data.availableProviders.length}</div>
|
|
905
|
+
<div class="stat-label">Providers</div>
|
|
906
|
+
</div>
|
|
907
|
+
</div>
|
|
908
|
+
<div class="gradient-divider"></div>
|
|
909
|
+
<div style="display: flex; flex-wrap: wrap; gap: 4px;">
|
|
910
|
+
${data.availableProviders.map((p) => `<span style="
|
|
911
|
+
font-size: 9px;
|
|
912
|
+
padding: 2px 6px;
|
|
913
|
+
border: 1px solid ${providerColors[p] || 'var(--holo-border)'}40;
|
|
914
|
+
color: ${providerColors[p] || 'var(--holo-text-muted)'};
|
|
915
|
+
border-radius: var(--holo-radius);
|
|
916
|
+
letter-spacing: 0.05em;
|
|
917
|
+
text-transform: uppercase;
|
|
918
|
+
">${p}</span>`).join('')}
|
|
919
|
+
</div>
|
|
920
|
+
</div>
|
|
921
|
+
</div>
|
|
922
|
+
|
|
923
|
+
<!-- API Keys -->
|
|
924
|
+
<div class="panel anim-in anim-d3">
|
|
925
|
+
<div class="panel-header">
|
|
926
|
+
<span class="panel-label">Credentials</span>
|
|
927
|
+
<span class="panel-badge">${envKeys.filter(k => data.environment[k.key]).length}/${envKeys.length}</span>
|
|
928
|
+
</div>
|
|
929
|
+
<div class="panel-body">
|
|
930
|
+
${envKeys.map(k => {
|
|
931
|
+
const active = data.environment[k.key];
|
|
932
|
+
return `<div class="key-row">
|
|
933
|
+
<span class="key-name">${k.label}</span>
|
|
934
|
+
<div class="key-bar">
|
|
935
|
+
<div class="key-bar-fill ${active ? 'active' : 'inactive'}" style="background: ${active ? k.color + '80' : ''}; ${active ? `box-shadow: 0 0 8px ${k.color}40;` : ''}"></div>
|
|
936
|
+
</div>
|
|
937
|
+
<span class="key-status ${active ? 'set' : 'missing'}">${active ? 'SET' : '---'}</span>
|
|
938
|
+
</div>`;
|
|
939
|
+
}).join('')}
|
|
940
|
+
</div>
|
|
941
|
+
</div>
|
|
942
|
+
|
|
943
|
+
</div>
|
|
944
|
+
|
|
945
|
+
<!-- ══════ MODEL REGISTRY ══════ -->
|
|
946
|
+
<div class="registry-panel anim-in anim-d4">
|
|
947
|
+
<div class="registry-header">
|
|
948
|
+
<span class="panel-label">Model Registry</span>
|
|
949
|
+
<span class="panel-badge">${data.totalModels} REGISTERED</span>
|
|
950
|
+
</div>
|
|
951
|
+
<div class="registry-body">
|
|
952
|
+
${Object.entries(data.models).map(([provider, models]) => {
|
|
953
|
+
const dotColor = providerColors[provider] || '#6080cc';
|
|
954
|
+
return `<div class="provider-group">
|
|
955
|
+
<div class="provider-head" onclick="this.parentElement.classList.toggle('open')">
|
|
956
|
+
<div class="provider-info">
|
|
957
|
+
<span class="provider-dot" style="background: ${dotColor}; box-shadow: 0 0 6px ${dotColor}60;"></span>
|
|
958
|
+
<span class="provider-name">${provider}</span>
|
|
959
|
+
<span class="provider-count">${models.length}</span>
|
|
960
|
+
</div>
|
|
961
|
+
<span class="provider-chevron">▶</span>
|
|
962
|
+
</div>
|
|
963
|
+
<div class="provider-models">
|
|
964
|
+
${models.map((m) => `<div class="model-entry">
|
|
965
|
+
<span class="model-id">${m.id}</span>
|
|
966
|
+
<span class="model-meta">
|
|
967
|
+
<span class="model-ctx">${m.contextWindow ? (m.contextWindow / 1000).toFixed(0) + 'K' : '-'}</span>
|
|
968
|
+
<span class="model-api">${m.apiPattern}</span>
|
|
969
|
+
</span>
|
|
970
|
+
</div>`).join('')}
|
|
971
|
+
</div>
|
|
972
|
+
</div>`;
|
|
973
|
+
}).join('')}
|
|
974
|
+
</div>
|
|
975
|
+
</div>
|
|
976
|
+
|
|
977
|
+
<!-- ══════ ENDPOINTS BAR ══════ -->
|
|
978
|
+
<div class="endpoints-bar anim-in anim-d5">
|
|
979
|
+
<div class="endpoint-item">
|
|
980
|
+
<span class="endpoint-method get">GET</span>
|
|
981
|
+
<span class="endpoint-path">/health</span>
|
|
982
|
+
</div>
|
|
983
|
+
<div class="endpoint-item">
|
|
984
|
+
<span class="endpoint-method get">GET</span>
|
|
985
|
+
<span class="endpoint-path">/models</span>
|
|
986
|
+
</div>
|
|
987
|
+
<div class="endpoint-item">
|
|
988
|
+
<span class="endpoint-method post">POST</span>
|
|
989
|
+
<span class="endpoint-path">/v1/messages</span>
|
|
990
|
+
</div>
|
|
991
|
+
<div class="endpoint-item">
|
|
992
|
+
<span class="endpoint-method get">GET</span>
|
|
993
|
+
<span class="endpoint-path">/sessions</span>
|
|
994
|
+
</div>
|
|
995
|
+
<div class="endpoint-item" style="margin-left: auto;">
|
|
996
|
+
<span class="auto-refresh" id="countdown"></span>
|
|
997
|
+
</div>
|
|
998
|
+
</div>
|
|
999
|
+
|
|
1000
|
+
</div>
|
|
1001
|
+
|
|
1002
|
+
<button class="refresh-btn" onclick="location.reload()">Refresh</button>
|
|
1003
|
+
|
|
1004
|
+
<script>
|
|
1005
|
+
// Auto-refresh every 30s
|
|
1006
|
+
let remaining = 30;
|
|
1007
|
+
const el = document.getElementById('countdown');
|
|
1008
|
+
setInterval(() => {
|
|
1009
|
+
remaining--;
|
|
1010
|
+
if (el) el.textContent = 'refresh in ' + remaining + 's';
|
|
1011
|
+
if (remaining <= 0) location.reload();
|
|
1012
|
+
}, 1000);
|
|
1013
|
+
if (el) el.textContent = 'refresh in 30s';
|
|
1014
|
+
|
|
1015
|
+
// All provider groups closed by default
|
|
1016
|
+
|
|
1017
|
+
// Resolve dashboard service links (port + 1 from current origin)
|
|
1018
|
+
(function() {
|
|
1019
|
+
const loc = window.location;
|
|
1020
|
+
const currentPort = parseInt(loc.port) || (loc.protocol === 'https:' ? 443 : 80);
|
|
1021
|
+
const dashPort = currentPort + 1;
|
|
1022
|
+
const dashBase = loc.protocol + '//' + loc.hostname + ':' + dashPort;
|
|
1023
|
+
document.querySelectorAll('[data-dash-path]').forEach(function(a) {
|
|
1024
|
+
a.setAttribute('href', dashBase + a.getAttribute('data-dash-path'));
|
|
1025
|
+
});
|
|
1026
|
+
})();
|
|
1027
|
+
</script>
|
|
1028
|
+
</body>
|
|
1029
|
+
</html>`;
|
|
1030
|
+
}
|
|
1031
|
+
//# sourceMappingURL=health.js.map
|