jfl 0.2.4 → 0.3.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/README.md +16 -0
- package/dist/commands/agent.d.ts +7 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +170 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/context-hub.d.ts.map +1 -1
- package/dist/commands/context-hub.js +274 -27
- package/dist/commands/context-hub.js.map +1 -1
- package/dist/commands/digest.d.ts.map +1 -1
- package/dist/commands/digest.js +45 -0
- package/dist/commands/digest.js.map +1 -1
- package/dist/commands/doctor.d.ts +7 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +236 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/eval.d.ts +6 -0
- package/dist/commands/eval.d.ts.map +1 -0
- package/dist/commands/eval.js +236 -0
- package/dist/commands/eval.js.map +1 -0
- package/dist/commands/hooks.d.ts +2 -0
- package/dist/commands/hooks.d.ts.map +1 -1
- package/dist/commands/hooks.js +1 -0
- package/dist/commands/hooks.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +230 -145
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/portfolio.d.ts +6 -0
- package/dist/commands/portfolio.d.ts.map +1 -0
- package/dist/commands/portfolio.js +296 -0
- package/dist/commands/portfolio.js.map +1 -0
- package/dist/commands/scope.d.ts +1 -0
- package/dist/commands/scope.d.ts.map +1 -1
- package/dist/commands/scope.js +189 -2
- package/dist/commands/scope.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +6 -0
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/voice.js.map +1 -1
- package/dist/dashboard/components.d.ts +1 -1
- package/dist/dashboard/components.d.ts.map +1 -1
- package/dist/dashboard/components.js +418 -6
- package/dist/dashboard/components.js.map +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +32 -5
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/pages.d.ts +1 -1
- package/dist/dashboard/pages.d.ts.map +1 -1
- package/dist/dashboard/pages.js +961 -123
- package/dist/dashboard/pages.js.map +1 -1
- package/dist/dashboard/styles.d.ts +1 -1
- package/dist/dashboard/styles.d.ts.map +1 -1
- package/dist/dashboard/styles.js +701 -88
- package/dist/dashboard/styles.js.map +1 -1
- package/dist/index.js +88 -45
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-manifest.d.ts +35 -0
- package/dist/lib/agent-manifest.d.ts.map +1 -0
- package/dist/lib/agent-manifest.js +75 -0
- package/dist/lib/agent-manifest.js.map +1 -0
- package/dist/lib/eval-store.d.ts +15 -0
- package/dist/lib/eval-store.d.ts.map +1 -0
- package/dist/lib/eval-store.js +179 -0
- package/dist/lib/eval-store.js.map +1 -0
- package/dist/lib/flow-engine.d.ts +12 -0
- package/dist/lib/flow-engine.d.ts.map +1 -1
- package/dist/lib/flow-engine.js +181 -4
- package/dist/lib/flow-engine.js.map +1 -1
- package/dist/lib/kuva.d.ts +45 -0
- package/dist/lib/kuva.d.ts.map +1 -0
- package/dist/lib/kuva.js +131 -0
- package/dist/lib/kuva.js.map +1 -0
- package/dist/lib/service-gtm.d.ts +10 -1
- package/dist/lib/service-gtm.d.ts.map +1 -1
- package/dist/lib/service-gtm.js +35 -2
- package/dist/lib/service-gtm.js.map +1 -1
- package/dist/lib/trajectory-loader.d.ts +82 -0
- package/dist/lib/trajectory-loader.d.ts.map +1 -0
- package/dist/lib/trajectory-loader.js +406 -0
- package/dist/lib/trajectory-loader.js.map +1 -0
- package/dist/mcp/context-hub-mcp.js +60 -0
- package/dist/mcp/context-hub-mcp.js.map +1 -1
- package/dist/types/eval.d.ts +18 -0
- package/dist/types/eval.d.ts.map +1 -0
- package/dist/types/eval.js +5 -0
- package/dist/types/eval.js.map +1 -0
- package/dist/types/flows.d.ts +7 -0
- package/dist/types/flows.d.ts.map +1 -1
- package/dist/types/journal.d.ts +133 -0
- package/dist/types/journal.d.ts.map +1 -0
- package/dist/types/journal.js +59 -0
- package/dist/types/journal.js.map +1 -0
- package/dist/types/map.d.ts +1 -1
- package/dist/types/map.d.ts.map +1 -1
- package/dist/types/map.js.map +1 -1
- package/dist/ui/service-dashboard.js.map +1 -1
- package/dist/utils/wallet.js.map +1 -1
- package/package.json +1 -1
- package/scripts/migrate-to-branch-sessions.sh +201 -0
- package/scripts/session/fix-tracked-logs.sh +97 -0
- package/scripts/session/session-cleanup.sh +28 -10
- package/scripts/session/session-end.sh +0 -10
- package/scripts/session/session-init.sh +0 -16
- package/template/THEORY.md +26 -0
- package/template/scripts/session/session-cleanup.sh +28 -10
- package/template/scripts/session/session-sync.sh +10 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard reusable Preact components
|
|
3
3
|
*
|
|
4
|
-
* @purpose Preact+HTM component JS strings for Nav, Card,
|
|
4
|
+
* @purpose Preact+HTM component JS strings for Nav, Card, MetricCard, ChartCard, RunActivityChart, ActivityRow, etc.
|
|
5
5
|
*/
|
|
6
6
|
export declare function getComponentsJS(): string;
|
|
7
7
|
//# sourceMappingURL=components.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/dashboard/components.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,eAAe,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/dashboard/components.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,eAAe,IAAI,MAAM,CAwjBxC"}
|
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard reusable Preact components
|
|
3
3
|
*
|
|
4
|
-
* @purpose Preact+HTM component JS strings for Nav, Card,
|
|
4
|
+
* @purpose Preact+HTM component JS strings for Nav, Card, MetricCard, ChartCard, RunActivityChart, ActivityRow, etc.
|
|
5
5
|
*/
|
|
6
6
|
export function getComponentsJS() {
|
|
7
7
|
return `
|
|
8
|
-
function Nav({ currentPage, setPage, projectName, port }) {
|
|
9
|
-
const
|
|
8
|
+
function Nav({ currentPage, setPage, projectName, port, mode }) {
|
|
9
|
+
const m = mode || 'gtm'
|
|
10
|
+
const portfolioPages = [
|
|
11
|
+
{ id: 'portfolio', label: 'Portfolio Overview' },
|
|
12
|
+
{ id: 'evals', label: 'Leaderboard' },
|
|
13
|
+
{ id: 'events', label: 'Events' },
|
|
14
|
+
{ id: 'costs', label: 'Costs' },
|
|
15
|
+
{ id: 'projects', label: 'Health' },
|
|
16
|
+
]
|
|
17
|
+
const gtmPages = [
|
|
10
18
|
{ id: 'overview', label: 'Command Center' },
|
|
11
19
|
{ id: 'journal', label: 'Journal' },
|
|
12
20
|
{ id: 'agents', label: 'Agents' },
|
|
21
|
+
{ id: 'evals', label: 'Evals' },
|
|
13
22
|
{ id: 'events', label: 'Events' },
|
|
23
|
+
{ id: 'costs', label: 'Costs' },
|
|
24
|
+
{ id: 'flows', label: 'Flows' },
|
|
14
25
|
{ id: 'sessions', label: 'Sessions' },
|
|
26
|
+
{ id: 'scope', label: 'Scope' },
|
|
15
27
|
{ id: 'projects', label: 'Projects' },
|
|
16
28
|
]
|
|
29
|
+
const servicePages = [
|
|
30
|
+
{ id: 'service', label: 'My Status' },
|
|
31
|
+
{ id: 'journal', label: 'Journal' },
|
|
32
|
+
{ id: 'evals', label: 'My Evals' },
|
|
33
|
+
{ id: 'events', label: 'Events' },
|
|
34
|
+
{ id: 'costs', label: 'Costs' },
|
|
35
|
+
{ id: 'sessions', label: 'Sessions' },
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
const pages = m === 'portfolio' ? portfolioPages : m === 'service' ? servicePages : gtmPages
|
|
17
39
|
|
|
18
40
|
return html\`
|
|
19
41
|
<div class="sidebar">
|
|
20
42
|
<div class="sidebar-brand">
|
|
21
43
|
<h1>\${projectName || 'Context Hub'}</h1>
|
|
44
|
+
<\${ModeBadge} mode=\${m} />
|
|
22
45
|
<div class="port-badge">Port \${port}</div>
|
|
23
46
|
</div>
|
|
24
47
|
<ul class="nav-items">
|
|
@@ -45,6 +68,112 @@ export function getComponentsJS() {
|
|
|
45
68
|
\`
|
|
46
69
|
}
|
|
47
70
|
|
|
71
|
+
function MetricCard({ icon, value, label, description, onClick, color }) {
|
|
72
|
+
return html\`
|
|
73
|
+
<div class="metric-card" onClick=\${onClick}>
|
|
74
|
+
\${icon && html\`<div style="font-size: 0.875rem; color: var(--muted-foreground); margin-bottom: 0.5rem;">\${icon}</div>\`}
|
|
75
|
+
<div class="metric-value" style=\${color ? 'color:' + color : ''}>\${value}</div>
|
|
76
|
+
<div class="metric-label">\${label}</div>
|
|
77
|
+
\${description && html\`<div class="metric-description">\${description}</div>\`}
|
|
78
|
+
</div>
|
|
79
|
+
\`
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function ChartCard({ title, subtitle, children }) {
|
|
83
|
+
return html\`
|
|
84
|
+
<div class="chart-card">
|
|
85
|
+
<div style="margin-bottom: 1rem;">
|
|
86
|
+
<div class="chart-card-title">\${title}</div>
|
|
87
|
+
\${subtitle && html\`<div class="chart-card-subtitle">\${subtitle}</div>\`}
|
|
88
|
+
</div>
|
|
89
|
+
\${children}
|
|
90
|
+
</div>
|
|
91
|
+
\`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function RunActivityChart({ events, days }) {
|
|
95
|
+
const numDays = days || 14
|
|
96
|
+
const now = new Date()
|
|
97
|
+
const buckets = []
|
|
98
|
+
|
|
99
|
+
for (let i = numDays - 1; i >= 0; i--) {
|
|
100
|
+
const d = new Date(now)
|
|
101
|
+
d.setDate(d.getDate() - i)
|
|
102
|
+
const key = d.toISOString().slice(0, 10)
|
|
103
|
+
buckets.push({ date: key, success: 0, failed: 0, other: 0, dayIndex: numDays - 1 - i })
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const dateSet = new Set(buckets.map(b => b.date))
|
|
107
|
+
|
|
108
|
+
for (const e of (events || [])) {
|
|
109
|
+
const ts = e.ts || e.timestamp
|
|
110
|
+
if (!ts) continue
|
|
111
|
+
const day = new Date(ts).toISOString().slice(0, 10)
|
|
112
|
+
const bucket = buckets.find(b => b.date === day)
|
|
113
|
+
if (!bucket) continue
|
|
114
|
+
const t = (e.type || '').toLowerCase()
|
|
115
|
+
if (t.includes('completed') || t.includes('success')) bucket.success++
|
|
116
|
+
else if (t.includes('failed') || t.includes('error')) bucket.failed++
|
|
117
|
+
else bucket.other++
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const maxCount = Math.max(1, ...buckets.map(b => b.success + b.failed + b.other))
|
|
121
|
+
|
|
122
|
+
return html\`
|
|
123
|
+
<div>
|
|
124
|
+
<div class="stacked-bars">
|
|
125
|
+
\${buckets.map((b, i) => {
|
|
126
|
+
const total = b.success + b.failed + b.other
|
|
127
|
+
const h = 80
|
|
128
|
+
const successH = total > 0 ? Math.max(2, Math.round((b.success / maxCount) * h)) : 0
|
|
129
|
+
const failedH = total > 0 ? Math.max(2, Math.round((b.failed / maxCount) * h)) : 0
|
|
130
|
+
const otherH = total > 0 ? Math.max(2, Math.round((b.other / maxCount) * h)) : 0
|
|
131
|
+
|
|
132
|
+
return html\`
|
|
133
|
+
<div key=\${i} class="stacked-bar" title=\${b.date + ': ' + total + ' events'}>
|
|
134
|
+
\${total === 0 ? html\`<div class="stacked-bar-empty"></div>\` : html\`
|
|
135
|
+
\${successH > 0 && html\`<div class="stacked-bar-segment stacked-bar-segment-success" style=\${'height:' + successH + 'px'}></div>\`}
|
|
136
|
+
\${failedH > 0 && html\`<div class="stacked-bar-segment stacked-bar-segment-error" style=\${'height:' + failedH + 'px'}></div>\`}
|
|
137
|
+
\${otherH > 0 && html\`<div class="stacked-bar-segment stacked-bar-segment-warning" style=\${'height:' + otherH + 'px'}></div>\`}
|
|
138
|
+
\`}
|
|
139
|
+
</div>
|
|
140
|
+
\`
|
|
141
|
+
})}
|
|
142
|
+
</div>
|
|
143
|
+
<div style="display: flex; justify-content: space-between; margin-top: 0.25rem;">
|
|
144
|
+
<span class="stacked-bar-label">\${buckets[0]?.date.slice(5) || ''}</span>
|
|
145
|
+
<span class="stacked-bar-label">\${buckets[Math.floor(numDays / 2)]?.date.slice(5) || ''}</span>
|
|
146
|
+
<span class="stacked-bar-label">\${buckets[numDays - 1]?.date.slice(5) || ''}</span>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
\`
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function ActivityRow({ event, isNew }) {
|
|
153
|
+
const time = new Date(event.ts || event.timestamp).toLocaleTimeString()
|
|
154
|
+
const t = (event.type || '').toLowerCase()
|
|
155
|
+
let icon = ''
|
|
156
|
+
if (t.includes('completed') || t.includes('success')) icon = 'var(--success)'
|
|
157
|
+
else if (t.includes('failed') || t.includes('error')) icon = 'var(--error)'
|
|
158
|
+
else if (t.includes('started') || t.includes('start')) icon = 'var(--info)'
|
|
159
|
+
else icon = 'var(--dim)'
|
|
160
|
+
|
|
161
|
+
const detail = event.data
|
|
162
|
+
? (typeof event.data === 'object'
|
|
163
|
+
? (event.data.message || event.data.task || event.data.title || JSON.stringify(event.data).slice(0, 80))
|
|
164
|
+
: String(event.data))
|
|
165
|
+
: ''
|
|
166
|
+
|
|
167
|
+
return html\`
|
|
168
|
+
<div class=\${'activity-row' + (isNew ? ' activity-row-enter' : '')}>
|
|
169
|
+
<span style=\${'width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; background:' + icon}></span>
|
|
170
|
+
<span style="font-size: 0.75rem; color: var(--dim); white-space: nowrap; min-width: 60px;">\${time}</span>
|
|
171
|
+
<\${TypeBadge} type=\${event.type} />
|
|
172
|
+
<span style="font-size: 0.8rem; color: var(--muted-foreground); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1;">\${detail}</span>
|
|
173
|
+
</div>
|
|
174
|
+
\`
|
|
175
|
+
}
|
|
176
|
+
|
|
48
177
|
function StatusBadge({ status }) {
|
|
49
178
|
const s = (status || 'unknown').toLowerCase()
|
|
50
179
|
return html\`<span class=\${'badge badge-' + s}>\${status}</span>\`
|
|
@@ -133,10 +262,21 @@ export function getComponentsJS() {
|
|
|
133
262
|
}
|
|
134
263
|
|
|
135
264
|
function LiveIndicator({ connected }) {
|
|
265
|
+
if (connected) {
|
|
266
|
+
return html\`
|
|
267
|
+
<span style="display: inline-flex; align-items: center; gap: 0.375rem; font-size: 0.8rem; color: var(--muted-foreground);">
|
|
268
|
+
<span class="pulse-dot">
|
|
269
|
+
<span class="pulse-dot-ping" style="background: var(--success);"></span>
|
|
270
|
+
<span class="pulse-dot-core" style="background: var(--success);"></span>
|
|
271
|
+
</span>
|
|
272
|
+
Live
|
|
273
|
+
</span>
|
|
274
|
+
\`
|
|
275
|
+
}
|
|
136
276
|
return html\`
|
|
137
|
-
<span style="display: inline-flex; align-items: center; font-size: 0.8rem;">
|
|
138
|
-
<span
|
|
139
|
-
|
|
277
|
+
<span style="display: inline-flex; align-items: center; gap: 0.375rem; font-size: 0.8rem; color: var(--error);">
|
|
278
|
+
<span style="width: 8px; height: 8px; border-radius: 50%; background: var(--error);"></span>
|
|
279
|
+
Disconnected
|
|
140
280
|
</span>
|
|
141
281
|
\`
|
|
142
282
|
}
|
|
@@ -158,6 +298,278 @@ export function getComponentsJS() {
|
|
|
158
298
|
</div>
|
|
159
299
|
\`
|
|
160
300
|
}
|
|
301
|
+
|
|
302
|
+
function Sparkline({ data, width, height, color }) {
|
|
303
|
+
const w = width || 60
|
|
304
|
+
const h = height || 20
|
|
305
|
+
const c = color || 'var(--accent)'
|
|
306
|
+
if (!data || data.length < 2) {
|
|
307
|
+
return html\`<svg width=\${w} height=\${h} class="sparkline"><line x1="0" y1=\${h/2} x2=\${w} y2=\${h/2} stroke="var(--dim)" stroke-width="1" stroke-dasharray="2,2" /></svg>\`
|
|
308
|
+
}
|
|
309
|
+
const min = Math.min(...data)
|
|
310
|
+
const max = Math.max(...data)
|
|
311
|
+
const range = max - min || 1
|
|
312
|
+
const pad = 2
|
|
313
|
+
const points = data.map((v, i) => {
|
|
314
|
+
const x = (i / (data.length - 1)) * w
|
|
315
|
+
const y = h - pad - ((v - min) / range) * (h - pad * 2)
|
|
316
|
+
return x + ',' + y
|
|
317
|
+
}).join(' ')
|
|
318
|
+
return html\`
|
|
319
|
+
<svg width=\${w} height=\${h} class="sparkline">
|
|
320
|
+
<polyline points=\${points} fill="none" stroke=\${c} stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" />
|
|
321
|
+
</svg>
|
|
322
|
+
\`
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function EvalChart({ data, width, height, label }) {
|
|
326
|
+
const w = width || 500
|
|
327
|
+
const h = height || 200
|
|
328
|
+
const pad = { top: 10, right: 10, bottom: 25, left: 45 }
|
|
329
|
+
const cw = w - pad.left - pad.right
|
|
330
|
+
const ch = h - pad.top - pad.bottom
|
|
331
|
+
|
|
332
|
+
if (!data || data.length < 2) {
|
|
333
|
+
return html\`
|
|
334
|
+
<div class="eval-chart-container" style=\${'width:' + w + 'px;height:' + h + 'px;'}>
|
|
335
|
+
<div class="empty-state" style="padding: 2rem;">No eval data yet</div>
|
|
336
|
+
</div>
|
|
337
|
+
\`
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const values = data.map(d => d.value)
|
|
341
|
+
const min = Math.min(...values) * 0.95
|
|
342
|
+
const max = Math.max(...values) * 1.05
|
|
343
|
+
const range = max - min || 1
|
|
344
|
+
|
|
345
|
+
const points = data.map((d, i) => {
|
|
346
|
+
const x = pad.left + (i / (data.length - 1)) * cw
|
|
347
|
+
const y = pad.top + ch - ((d.value - min) / range) * ch
|
|
348
|
+
return { x, y, value: d.value, ts: d.ts, model: d.model_version }
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
const polyline = points.map(p => p.x + ',' + p.y).join(' ')
|
|
352
|
+
const gradientPath = 'M' + points[0].x + ',' + (pad.top + ch) + ' L' + points.map(p => p.x + ',' + p.y).join(' L') + ' L' + points[points.length - 1].x + ',' + (pad.top + ch) + ' Z'
|
|
353
|
+
|
|
354
|
+
const yTicks = 5
|
|
355
|
+
const yLines = Array.from({ length: yTicks }, (_, i) => {
|
|
356
|
+
const val = min + (range * i) / (yTicks - 1)
|
|
357
|
+
const y = pad.top + ch - (i / (yTicks - 1)) * ch
|
|
358
|
+
return { val, y }
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
return html\`
|
|
362
|
+
<div class="eval-chart-container">
|
|
363
|
+
<svg width=\${w} height=\${h} viewBox=\${'0 0 ' + w + ' ' + h}>
|
|
364
|
+
<defs>
|
|
365
|
+
<linearGradient id="evalGrad" x1="0" y1="0" x2="0" y2="1">
|
|
366
|
+
<stop offset="0%" stop-color="var(--accent)" stop-opacity="0.3" />
|
|
367
|
+
<stop offset="100%" stop-color="var(--accent)" stop-opacity="0" />
|
|
368
|
+
</linearGradient>
|
|
369
|
+
</defs>
|
|
370
|
+
\${yLines.map(t => html\`
|
|
371
|
+
<g key=\${t.val}>
|
|
372
|
+
<line x1=\${pad.left} y1=\${t.y} x2=\${w - pad.right} y2=\${t.y} stroke="var(--border)" stroke-width="0.5" />
|
|
373
|
+
<text x=\${pad.left - 5} y=\${t.y + 3} text-anchor="end" fill="var(--dim)" font-size="10">\${t.val.toFixed(2)}</text>
|
|
374
|
+
</g>
|
|
375
|
+
\`)}
|
|
376
|
+
<path d=\${gradientPath} fill="url(#evalGrad)" />
|
|
377
|
+
<polyline points=\${polyline} fill="none" stroke="var(--accent)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
|
|
378
|
+
\${points.map((p, i) => html\`
|
|
379
|
+
<g key=\${i} class="eval-point">
|
|
380
|
+
<circle cx=\${p.x} cy=\${p.y} r="3" fill="var(--card)" stroke="var(--accent)" stroke-width="1.5" />
|
|
381
|
+
<title>\${(p.model || '') + ' ' + p.value.toFixed(4) + '\\n' + new Date(p.ts).toLocaleDateString()}</title>
|
|
382
|
+
</g>
|
|
383
|
+
\`)}
|
|
384
|
+
\${label && html\`<text x=\${pad.left} y=\${h - 3} fill="var(--dim)" font-size="10">\${label}</text>\`}
|
|
385
|
+
</svg>
|
|
386
|
+
</div>
|
|
387
|
+
\`
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function HealthCard({ child }) {
|
|
391
|
+
const dotClass = child.status === 'ok' ? 'health-dot-ok' : child.status === 'error' ? 'health-dot-error' : 'health-dot-down'
|
|
392
|
+
return html\`
|
|
393
|
+
<div class="card health-card">
|
|
394
|
+
<div style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.5rem;">
|
|
395
|
+
<span class=\${'health-dot ' + dotClass}></span>
|
|
396
|
+
<span style="font-weight: 700; font-size: 0.9rem;">\${child.name}</span>
|
|
397
|
+
</div>
|
|
398
|
+
\${child.composite != null && html\`
|
|
399
|
+
<div style="display: flex; align-items: center; gap: 0.75rem;">
|
|
400
|
+
<span class="metric-value" style="font-size: 1.5rem;">\${child.composite.toFixed(2)}</span>
|
|
401
|
+
\${child.delta != null && html\`<\${DeltaBadge} delta=\${child.delta} />\`}
|
|
402
|
+
</div>
|
|
403
|
+
\`}
|
|
404
|
+
\${child.sparkline && child.sparkline.length > 1 && html\`
|
|
405
|
+
<div style="margin-top: 0.5rem;">
|
|
406
|
+
<\${Sparkline} data=\${child.sparkline} width=\${120} height=\${24} />
|
|
407
|
+
</div>
|
|
408
|
+
\`}
|
|
409
|
+
\${child.activeSessions != null && html\`
|
|
410
|
+
<div style="font-size: 0.7rem; color: var(--dim); margin-top: 0.375rem;">\${child.activeSessions} active sessions</div>
|
|
411
|
+
\`}
|
|
412
|
+
<div style="font-size: 0.65rem; color: var(--dim); margin-top: 0.25rem;">Port \${child.port}</div>
|
|
413
|
+
</div>
|
|
414
|
+
\`
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function DeltaBadge({ delta }) {
|
|
418
|
+
if (delta == null || delta === 0) {
|
|
419
|
+
return html\`<span class="delta-neutral">—</span>\`
|
|
420
|
+
}
|
|
421
|
+
const isUp = delta > 0
|
|
422
|
+
const cls = isUp ? 'delta-up' : 'delta-down'
|
|
423
|
+
const arrow = isUp ? '▲' : '▼'
|
|
424
|
+
return html\`<span class=\${cls}>\${arrow} \${Math.abs(delta).toFixed(3)}</span>\`
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function CostBar({ prompt, completion }) {
|
|
428
|
+
const total = (prompt || 0) + (completion || 0)
|
|
429
|
+
if (total === 0) return html\`<div class="cost-bar"><div class="cost-bar-empty">—</div></div>\`
|
|
430
|
+
const pPct = Math.round((prompt / total) * 100)
|
|
431
|
+
const cPct = 100 - pPct
|
|
432
|
+
return html\`
|
|
433
|
+
<div class="cost-bar">
|
|
434
|
+
<div class="cost-bar-prompt" style=\${'width:' + pPct + '%'} title=\${'Prompt: ' + prompt.toLocaleString()}></div>
|
|
435
|
+
<div class="cost-bar-completion" style=\${'width:' + cPct + '%'} title=\${'Completion: ' + completion.toLocaleString()}></div>
|
|
436
|
+
</div>
|
|
437
|
+
\`
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
function UtilBar({ value, max, label }) {
|
|
441
|
+
const pct = max > 0 ? Math.min(100, Math.round((value / max) * 100)) : 0
|
|
442
|
+
const cls = pct < 60 ? 'util-bar-green' : pct < 85 ? 'util-bar-yellow' : 'util-bar-red'
|
|
443
|
+
return html\`
|
|
444
|
+
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
|
445
|
+
<div class="util-bar" style="flex: 1;">
|
|
446
|
+
<div class=\${'util-bar-fill ' + cls} style=\${'width:' + pct + '%'}></div>
|
|
447
|
+
</div>
|
|
448
|
+
<span style="font-size: 0.65rem; color: var(--muted-foreground); font-weight: 600; min-width: 28px;">\${pct}%</span>
|
|
449
|
+
</div>
|
|
450
|
+
\`
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function SuccessRateBar({ rate }) {
|
|
454
|
+
const pct = Math.round((rate || 0) * 100)
|
|
455
|
+
const color = pct >= 95 ? 'var(--success)' : pct >= 80 ? 'var(--warning)' : 'var(--error)'
|
|
456
|
+
return html\`
|
|
457
|
+
<div style="display: flex; align-items: center; gap: 0.375rem;">
|
|
458
|
+
<div class="success-bar">
|
|
459
|
+
<div class="success-bar-fill" style=\${'width:' + pct + '%; background:' + color}></div>
|
|
460
|
+
</div>
|
|
461
|
+
<span style="font-size: 0.65rem; color: var(--muted-foreground); font-weight: 600; min-width: 28px;">\${pct}%</span>
|
|
462
|
+
</div>
|
|
463
|
+
\`
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
function UtilizationRing({ value, max, label }) {
|
|
467
|
+
const pct = max > 0 ? Math.min(1, value / max) : 0
|
|
468
|
+
const r = 30
|
|
469
|
+
const circumference = 2 * Math.PI * r
|
|
470
|
+
const offset = circumference * (1 - pct)
|
|
471
|
+
const color = pct < 0.6 ? 'var(--success)' : pct < 0.85 ? 'var(--warning)' : 'var(--error)'
|
|
472
|
+
return html\`
|
|
473
|
+
<div class="util-ring">
|
|
474
|
+
<svg width="76" height="76" viewBox="0 0 76 76">
|
|
475
|
+
<circle cx="38" cy="38" r=\${r} fill="none" stroke="var(--border)" stroke-width="6" />
|
|
476
|
+
<circle cx="38" cy="38" r=\${r} fill="none" stroke=\${color} stroke-width="6"
|
|
477
|
+
stroke-dasharray=\${circumference} stroke-dashoffset=\${offset}
|
|
478
|
+
stroke-linecap="round" transform="rotate(-90 38 38)" />
|
|
479
|
+
<text x="38" y="35" text-anchor="middle" fill="var(--foreground)" font-size="14" font-weight="700">\${Math.round(pct * 100)}%</text>
|
|
480
|
+
\${label && html\`<text x="38" y="50" text-anchor="middle" fill="var(--dim)" font-size="9">\${label}</text>\`}
|
|
481
|
+
</svg>
|
|
482
|
+
</div>
|
|
483
|
+
\`
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function ActiveAgentCard({ agent }) {
|
|
487
|
+
const a = agent
|
|
488
|
+
const isLive = a.status === 'active'
|
|
489
|
+
const duration = a.startedAt ? Math.round((Date.now() - new Date(a.startedAt).getTime()) / 1000) : null
|
|
490
|
+
const durationStr = duration !== null
|
|
491
|
+
? duration < 60 ? duration + 's'
|
|
492
|
+
: duration < 3600 ? Math.round(duration / 60) + 'm'
|
|
493
|
+
: Math.round(duration / 3600) + 'h'
|
|
494
|
+
: ''
|
|
495
|
+
|
|
496
|
+
function feedColor(type) {
|
|
497
|
+
if (!type) return 'feed-line-dim'
|
|
498
|
+
if (type.includes('error') || type.includes('failed')) return 'feed-line-error'
|
|
499
|
+
if (type.includes('warn')) return 'feed-line-warn'
|
|
500
|
+
if (type.includes('health') || type.includes('analysis') || type.includes('info')) return 'feed-line-info'
|
|
501
|
+
if (type.includes('completed') || type.includes('complete') || type.includes('success')) return 'feed-line-success'
|
|
502
|
+
return 'feed-line-dim'
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
return html\`
|
|
506
|
+
<div class=\${'active-agent-card' + (isLive ? ' active-agent-card-live' : '')}>
|
|
507
|
+
<div class="active-agent-header">
|
|
508
|
+
<div style="display: flex; align-items: center; gap: 0.5rem;">
|
|
509
|
+
\${isLive ? html\`
|
|
510
|
+
<span class="pulse-dot">
|
|
511
|
+
<span class="pulse-dot-ping" style="background: var(--success);"></span>
|
|
512
|
+
<span class="pulse-dot-core" style="background: var(--success);"></span>
|
|
513
|
+
</span>
|
|
514
|
+
\` : html\`
|
|
515
|
+
<span class="agent-dot agent-dot-idle"></span>
|
|
516
|
+
\`}
|
|
517
|
+
<span style="font-weight: 700; font-size: 0.9rem;">\${a.name}</span>
|
|
518
|
+
\${a.model && html\`<span class="model-badge">\${a.model}</span>\`}
|
|
519
|
+
</div>
|
|
520
|
+
<span style="font-size: 0.75rem; color: var(--dim);">\${durationStr}</span>
|
|
521
|
+
</div>
|
|
522
|
+
\${a.currentTask && html\`
|
|
523
|
+
<div class="active-agent-task">\${a.currentTask}</div>
|
|
524
|
+
\`}
|
|
525
|
+
\${a.role && html\`<div style="font-size: 0.7rem; color: var(--dim); margin-bottom: 0.5rem;">\${a.role}</div>\`}
|
|
526
|
+
\${a.recentEvents && a.recentEvents.length > 0 && html\`
|
|
527
|
+
<div class="run-feed">
|
|
528
|
+
\${a.recentEvents.slice(0, 5).map((e, i) => html\`
|
|
529
|
+
<div key=\${i} class="run-feed-line">
|
|
530
|
+
<span class="run-feed-seq">\${String(i + 1).padStart(2, '0')}</span>
|
|
531
|
+
<span class=\${'run-feed-type ' + feedColor(e.type)}>\${(e.type || '').split(':').pop()}</span>
|
|
532
|
+
<span class="run-feed-data">\${e.data ? (typeof e.data === 'object' ? (e.data.message || e.data.task || JSON.stringify(e.data).slice(0, 60)) : String(e.data)) : ''}</span>
|
|
533
|
+
</div>
|
|
534
|
+
\`)}
|
|
535
|
+
</div>
|
|
536
|
+
\`}
|
|
537
|
+
</div>
|
|
538
|
+
\`
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
function AgentCard({ agent }) {
|
|
542
|
+
const a = agent
|
|
543
|
+
const age = a.lastSeen ? Math.round((Date.now() - new Date(a.lastSeen).getTime()) / 1000) : null
|
|
544
|
+
const ageStr = age !== null
|
|
545
|
+
? age < 60 ? age + 's ago'
|
|
546
|
+
: age < 3600 ? Math.round(age / 60) + 'm ago'
|
|
547
|
+
: Math.round(age / 3600) + 'h ago'
|
|
548
|
+
: ''
|
|
549
|
+
|
|
550
|
+
return html\`
|
|
551
|
+
<div style="display: flex; align-items: center; justify-content: space-between; padding: 0.5rem 0; border-bottom: 1px solid var(--border);">
|
|
552
|
+
<div style="display: flex; align-items: center; gap: 0.625rem;">
|
|
553
|
+
<span class=\${'agent-dot agent-dot-' + a.status}></span>
|
|
554
|
+
<div>
|
|
555
|
+
<div style="font-size: 0.85rem; font-weight: 600;">\${a.name}</div>
|
|
556
|
+
\${a.role && html\`<div style="font-size: 0.7rem; color: var(--dim);">\${a.role}</div>\`}
|
|
557
|
+
</div>
|
|
558
|
+
</div>
|
|
559
|
+
<div style="display: flex; align-items: center; gap: 0.5rem; text-align: right;">
|
|
560
|
+
\${a.model && html\`<span class="model-badge">\${a.model}</span>\`}
|
|
561
|
+
\${a.runtime && a.runtime !== 'local' && html\`<span class="runtime-badge">\${a.runtime}</span>\`}
|
|
562
|
+
<span style="font-size: 0.65rem; color: var(--dim); min-width: 50px;">\${ageStr}</span>
|
|
563
|
+
</div>
|
|
564
|
+
</div>
|
|
565
|
+
\`
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
function ModeBadge({ mode }) {
|
|
569
|
+
const cls = 'mode-badge mode-' + mode
|
|
570
|
+
const label = mode === 'portfolio' ? 'PORTFOLIO' : mode === 'gtm' ? 'GTM' : mode === 'service' ? 'SERVICE' : 'STANDALONE'
|
|
571
|
+
return html\`<span class=\${cls}>\${label}</span>\`
|
|
572
|
+
}
|
|
161
573
|
`;
|
|
162
574
|
}
|
|
163
575
|
//# sourceMappingURL=components.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/dashboard/components.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,eAAe;IAC7B,OAAO
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/dashboard/components.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,UAAU,eAAe;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsjBN,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAK5B,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAA;AAK5B,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CA4H/E;AAWD,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAiBT"}
|
package/dist/dashboard/index.js
CHANGED
|
@@ -63,7 +63,7 @@ export function generateDashboardHTML(projectName, port) {
|
|
|
63
63
|
}
|
|
64
64
|
const res = await fetch(path, { ...opts, headers })
|
|
65
65
|
if (res.status === 401) {
|
|
66
|
-
document.getElementById('app').innerHTML = '<div style="padding: 3rem; text-align: center; color: var(--error);"><h2>Unauthorized</h2><p style="color: var(--
|
|
66
|
+
document.getElementById('app').innerHTML = '<div style="padding: 3rem; text-align: center; color: var(--error);"><h2>Unauthorized</h2><p style="color: var(--muted-foreground); margin-top: 0.5rem;">Token expired or invalid. Run: jfl context-hub dashboard</p></div>'
|
|
67
67
|
throw new Error('Unauthorized')
|
|
68
68
|
}
|
|
69
69
|
return res.json()
|
|
@@ -77,16 +77,42 @@ export function generateDashboardHTML(projectName, port) {
|
|
|
77
77
|
|
|
78
78
|
// App
|
|
79
79
|
function App() {
|
|
80
|
-
const
|
|
80
|
+
const { mode, config, children, loading: modeLoading } = useWorkspaceMode()
|
|
81
|
+
const defaultPage = mode === 'portfolio' ? 'portfolio' : mode === 'service' ? 'service' : 'overview'
|
|
82
|
+
const [page, setPage] = useState(defaultPage)
|
|
81
83
|
|
|
82
|
-
|
|
84
|
+
// Update default page when mode loads
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (!modeLoading) {
|
|
87
|
+
const dp = mode === 'portfolio' ? 'portfolio' : mode === 'service' ? 'service' : 'overview'
|
|
88
|
+
setPage(prev => {
|
|
89
|
+
// Only update if still on the initial 'overview' default
|
|
90
|
+
if (prev === 'overview' && dp !== 'overview') return dp
|
|
91
|
+
return prev
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}, [mode, modeLoading])
|
|
95
|
+
|
|
96
|
+
const pageMap = {
|
|
83
97
|
overview: OverviewPage,
|
|
84
98
|
journal: JournalPage,
|
|
85
99
|
agents: AgentsPage,
|
|
86
100
|
events: EventsPage,
|
|
87
101
|
sessions: SessionsPage,
|
|
88
102
|
projects: ProjectsPage,
|
|
89
|
-
|
|
103
|
+
portfolio: PortfolioOverviewPage,
|
|
104
|
+
evals: EvalsPage,
|
|
105
|
+
scope: ScopePage,
|
|
106
|
+
service: ServiceOverviewPage,
|
|
107
|
+
costs: CostsPage,
|
|
108
|
+
flows: FlowsPage,
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const pageComponent = pageMap[page] || OverviewPage
|
|
112
|
+
|
|
113
|
+
if (modeLoading) {
|
|
114
|
+
return html\`<div class="loading" style="width: 100%; height: 100vh;">Loading dashboard</div>\`
|
|
115
|
+
}
|
|
90
116
|
|
|
91
117
|
return html\`
|
|
92
118
|
<\${Nav}
|
|
@@ -94,9 +120,10 @@ export function generateDashboardHTML(projectName, port) {
|
|
|
94
120
|
setPage=\${setPage}
|
|
95
121
|
projectName="${escapeHtml(projectName)}"
|
|
96
122
|
port=\${${port}}
|
|
123
|
+
mode=\${mode}
|
|
97
124
|
/>
|
|
98
125
|
<div class="main-content">
|
|
99
|
-
<\${pageComponent} />
|
|
126
|
+
<\${pageComponent} mode=\${mode} config=\${config} children=\${children} />
|
|
100
127
|
</div>
|
|
101
128
|
\`
|
|
102
129
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,UAAU,qBAAqB,CAAC,WAAmB,EAAE,IAAY;IACrE,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAA;IACnC,MAAM,UAAU,GAAG,eAAe,EAAE,CAAA;IACpC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAA;IAE1B,OAAO;;;;;WAKE,UAAU,CAAC,WAAW,CAAC;;;;;;;;;;;WAWvB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyCX,UAAU;;;MAGV,KAAK
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dashboard/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,UAAU,qBAAqB,CAAC,WAAmB,EAAE,IAAY;IACrE,MAAM,MAAM,GAAG,kBAAkB,EAAE,CAAA;IACnC,MAAM,UAAU,GAAG,eAAe,EAAE,CAAA;IACpC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAA;IAE1B,OAAO;;;;;WAKE,UAAU,CAAC,WAAW,CAAC;;;;;;;;;;;WAWvB,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAyCX,UAAU;;;MAGV,KAAK;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA6Cc,UAAU,CAAC,WAAW,CAAC;oBAC5B,IAAI;;;;;;;;;;;;QAYhB,CAAA;AACR,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG;SACP,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC;SACvB,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;AAC3B,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,GAAyB,EACzB,GAAwB,EACxB,WAAmB,EACnB,IAAY;IAEZ,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,oBAAoB,IAAI,EAAE,CAAC,CAAA;IAE/D,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAA;IACd,CAAC;IAED,qCAAqC;IACrC,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,aAAa,CAAA;IAEjE,MAAM,IAAI,GAAG,qBAAqB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;IACrD,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,cAAc,EAAE,0BAA0B;QAC1C,eAAe,EAAE,UAAU;KAC5B,CAAC,CAAA;IACF,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACb,OAAO,IAAI,CAAA;AACb,CAAC"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Dashboard page components
|
|
3
3
|
*
|
|
4
|
-
* @purpose Command center pages:
|
|
4
|
+
* @purpose Command center pages: mode-aware overview, evals, portfolio, scope, service, events, agents, projects, sessions, journal
|
|
5
5
|
*/
|
|
6
6
|
export declare function getPagesJS(): string;
|
|
7
7
|
//# sourceMappingURL=pages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/dashboard/pages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,UAAU,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"pages.d.ts","sourceRoot":"","sources":["../../src/dashboard/pages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wBAAgB,UAAU,IAAI,MAAM,CAqiDnC"}
|