agentlytics 0.2.4 → 0.2.5
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/editors/antigravity.js +10 -1
- package/editors/base.js +185 -0
- package/editors/claude.js +11 -1
- package/editors/codex.js +6 -0
- package/editors/commandcode.js +6 -1
- package/editors/copilot.js +6 -1
- package/editors/cursor-agent.js +6 -1
- package/editors/cursor.js +9 -1
- package/editors/gemini.js +10 -1
- package/editors/goose.js +50 -1
- package/editors/index.js +52 -1
- package/editors/kiro.js +10 -1
- package/editors/opencode.js +32 -1
- package/editors/vscode.js +13 -1
- package/editors/windsurf.js +14 -1
- package/editors/zed.js +31 -1
- package/index.js +5 -0
- package/package.json +1 -1
- package/server.js +288 -0
- package/ui/src/App.jsx +3 -0
- package/ui/src/components/PageHeader.jsx +11 -0
- package/ui/src/lib/api.js +7 -0
- package/ui/src/pages/Artifacts.jsx +16 -29
- package/ui/src/pages/Compare.jsx +4 -3
- package/ui/src/pages/CostAnalysis.jsx +6 -9
- package/ui/src/pages/Dashboard.jsx +15 -12
- package/ui/src/pages/DeepAnalysis.jsx +6 -5
- package/ui/src/pages/MCPs.jsx +744 -0
- package/ui/src/pages/ProjectDetail.jsx +1 -1
- package/ui/src/pages/Projects.jsx +9 -6
- package/ui/src/pages/RelayDashboard.jsx +4 -1
- package/ui/src/pages/RelayUserDetail.jsx +1 -1
- package/ui/src/pages/Sessions.jsx +19 -19
- package/ui/src/pages/Settings.jsx +3 -5
- package/ui/src/pages/SqlViewer.jsx +15 -16
- package/ui/src/pages/Subscriptions.jsx +4 -7
|
@@ -102,7 +102,7 @@ export default function ProjectDetail() {
|
|
|
102
102
|
const avgMsgs = allEnabled && project.totalSessions > 0 ? (project.totalMessages / project.totalSessions).toFixed(1) : 0
|
|
103
103
|
|
|
104
104
|
return (
|
|
105
|
-
<div className="fade-in space-y-
|
|
105
|
+
<div className="fade-in space-y-3">
|
|
106
106
|
{/* Header card */}
|
|
107
107
|
<div className="card p-4">
|
|
108
108
|
<div className="flex items-start gap-3">
|
|
@@ -11,6 +11,7 @@ import EditorIcon from '../components/EditorIcon'
|
|
|
11
11
|
import DateRangePicker from '../components/DateRangePicker'
|
|
12
12
|
import SectionTitle from '../components/SectionTitle'
|
|
13
13
|
import AnimatedLoader from '../components/AnimatedLoader'
|
|
14
|
+
import PageHeader from '../components/PageHeader'
|
|
14
15
|
|
|
15
16
|
ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement)
|
|
16
17
|
|
|
@@ -63,7 +64,9 @@ export default function Projects({ overview }) {
|
|
|
63
64
|
const top10 = projects.slice(0, 10)
|
|
64
65
|
|
|
65
66
|
return (
|
|
66
|
-
<div className="fade-in space-y-
|
|
67
|
+
<div className="fade-in space-y-3">
|
|
68
|
+
<PageHeader icon={FolderOpen} title="Projects" />
|
|
69
|
+
|
|
67
70
|
{/* KPIs */}
|
|
68
71
|
<div className="grid gap-2" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(90px, 1fr))' }}>
|
|
69
72
|
<KpiCard label="projects" value={projects.length} />
|
|
@@ -143,7 +146,7 @@ export default function Projects({ overview }) {
|
|
|
143
146
|
<select
|
|
144
147
|
value={editorFilter}
|
|
145
148
|
onChange={e => setEditorFilter(e.target.value)}
|
|
146
|
-
className="px-2 py-1
|
|
149
|
+
className="px-2 py-1 text-[12px] outline-none"
|
|
147
150
|
style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
|
|
148
151
|
>
|
|
149
152
|
<option value="">All Editors</option>
|
|
@@ -151,14 +154,14 @@ export default function Projects({ overview }) {
|
|
|
151
154
|
<option key={e.id} value={e.id}>{editorLabel(e.id)}</option>
|
|
152
155
|
))}
|
|
153
156
|
</select>
|
|
154
|
-
<div className="relative max-w-sm
|
|
155
|
-
<Search size={
|
|
157
|
+
<div className="relative flex-1 max-w-sm">
|
|
158
|
+
<Search size={12} className="absolute left-2.5 top-1/2 -translate-y-1/2" style={{ color: 'var(--c-text3)' }} />
|
|
156
159
|
<input
|
|
157
160
|
type="text"
|
|
158
|
-
placeholder="
|
|
161
|
+
placeholder="Search projects..."
|
|
159
162
|
value={search}
|
|
160
163
|
onChange={e => setSearch(e.target.value)}
|
|
161
|
-
className="w-full pl-
|
|
164
|
+
className="w-full pl-7 pr-3 py-1 text-[12px] outline-none"
|
|
162
165
|
style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
|
|
163
166
|
/>
|
|
164
167
|
</div>
|
|
@@ -11,6 +11,7 @@ import LiveFeed from '../components/LiveFeed'
|
|
|
11
11
|
import { editorColor, editorLabel, formatNumber, formatDate } from '../lib/constants'
|
|
12
12
|
import { fetchRelayTeamStats, fetchRelaySearch, fetchRelaySession, mergeRelayUsers } from '../lib/api'
|
|
13
13
|
import AnimatedLoader from '../components/AnimatedLoader'
|
|
14
|
+
import PageHeader from '../components/PageHeader'
|
|
14
15
|
import { useTheme } from '../lib/theme'
|
|
15
16
|
|
|
16
17
|
ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement)
|
|
@@ -319,7 +320,9 @@ export default function RelayDashboard() {
|
|
|
319
320
|
</div>
|
|
320
321
|
|
|
321
322
|
{/* ── Center: scrollable content ── */}
|
|
322
|
-
<div className="flex-1 min-w-0 overflow-y-auto p-4 space-y-
|
|
323
|
+
<div className="flex-1 min-w-0 overflow-y-auto p-4 space-y-3">
|
|
324
|
+
<PageHeader icon={Users} title="Team Relay" />
|
|
325
|
+
|
|
323
326
|
{/* KPIs */}
|
|
324
327
|
<div className="grid gap-2" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(90px, 1fr))' }}>
|
|
325
328
|
<KpiCard label="team members" value={stats.totalUsers} />
|
|
@@ -228,7 +228,7 @@ export default function RelayUserDetail() {
|
|
|
228
228
|
</div>
|
|
229
229
|
|
|
230
230
|
{/* ── Center: scrollable content ── */}
|
|
231
|
-
<div className="flex-1 min-w-0 overflow-y-auto p-4 space-y-
|
|
231
|
+
<div className="flex-1 min-w-0 overflow-y-auto p-4 space-y-3">
|
|
232
232
|
{/* Header */}
|
|
233
233
|
<div className="flex items-center gap-3">
|
|
234
234
|
<button
|
|
@@ -11,6 +11,7 @@ import EditorIcon from '../components/EditorIcon'
|
|
|
11
11
|
import SectionTitle from '../components/SectionTitle'
|
|
12
12
|
import DateRangePicker from '../components/DateRangePicker'
|
|
13
13
|
import ChatSidebar from '../components/ChatSidebar'
|
|
14
|
+
import PageHeader from '../components/PageHeader'
|
|
14
15
|
|
|
15
16
|
ChartJS.register(ArcElement, CategoryScale, LinearScale, PointElement, LineElement, BarElement, Tooltip, Legend, Filler)
|
|
16
17
|
|
|
@@ -295,7 +296,9 @@ export default function Sessions({ overview }) {
|
|
|
295
296
|
)
|
|
296
297
|
|
|
297
298
|
return (
|
|
298
|
-
<div className="fade-in space-y-
|
|
299
|
+
<div className="fade-in space-y-3">
|
|
300
|
+
<PageHeader icon={List} title="Sessions" />
|
|
301
|
+
|
|
299
302
|
{/* KPIs */}
|
|
300
303
|
<div className="grid gap-2" style={{ gridTemplateColumns: 'repeat(auto-fit, minmax(90px, 1fr))' }}>
|
|
301
304
|
<KpiCard label="sessions" value={formatNumber(filtered.length)} sub={filtered.length !== total ? `of ${formatNumber(total)}` : ''} />
|
|
@@ -421,29 +424,26 @@ export default function Sessions({ overview }) {
|
|
|
421
424
|
)}
|
|
422
425
|
|
|
423
426
|
{/* Filters */}
|
|
424
|
-
<div className="flex items-center gap-
|
|
425
|
-
<
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
<option value=
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
))}
|
|
437
|
-
</select>
|
|
438
|
-
</div>
|
|
427
|
+
<div className="flex items-center gap-2">
|
|
428
|
+
<select
|
|
429
|
+
value={editor}
|
|
430
|
+
onChange={e => setEditor(e.target.value)}
|
|
431
|
+
className="px-2 py-1 text-[12px] outline-none"
|
|
432
|
+
style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
|
|
433
|
+
>
|
|
434
|
+
<option value="">All Editors</option>
|
|
435
|
+
{editors.map(e => (
|
|
436
|
+
<option key={e.id} value={e.id}>{editorLabel(e.id)} ({e.count})</option>
|
|
437
|
+
))}
|
|
438
|
+
</select>
|
|
439
439
|
<div className="relative flex-1 max-w-sm">
|
|
440
|
-
<Search size={
|
|
440
|
+
<Search size={12} className="absolute left-2.5 top-1/2 -translate-y-1/2" style={{ color: 'var(--c-text3)' }} />
|
|
441
441
|
<input
|
|
442
442
|
type="text"
|
|
443
|
-
placeholder="
|
|
443
|
+
placeholder="Search sessions..."
|
|
444
444
|
value={search}
|
|
445
445
|
onChange={e => setSearch(e.target.value)}
|
|
446
|
-
className="w-full pl-
|
|
446
|
+
className="w-full pl-7 pr-3 py-1 text-[12px] outline-none"
|
|
447
447
|
style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
|
|
448
448
|
/>
|
|
449
449
|
</div>
|
|
@@ -5,6 +5,7 @@ import { editorLabel, formatNumber, formatDate } from '../lib/constants'
|
|
|
5
5
|
import EditorIcon from '../components/EditorIcon'
|
|
6
6
|
import SectionTitle from '../components/SectionTitle'
|
|
7
7
|
import AnimatedLoader from '../components/AnimatedLoader'
|
|
8
|
+
import PageHeader from '../components/PageHeader'
|
|
8
9
|
|
|
9
10
|
export default function Settings() {
|
|
10
11
|
const [config, setConfig] = useState(null)
|
|
@@ -47,11 +48,8 @@ export default function Settings() {
|
|
|
47
48
|
const sorted = [...filtered].sort((a, b) => a.name.localeCompare(b.name))
|
|
48
49
|
|
|
49
50
|
return (
|
|
50
|
-
<div className="fade-in space-y-
|
|
51
|
-
<
|
|
52
|
-
<SettingsIcon size={14} style={{ color: '#6366f1' }} />
|
|
53
|
-
Settings
|
|
54
|
-
</div>
|
|
51
|
+
<div className="fade-in space-y-3">
|
|
52
|
+
<PageHeader icon={SettingsIcon} title="Settings" />
|
|
55
53
|
|
|
56
54
|
<div className="card overflow-hidden">
|
|
57
55
|
<div className="px-3 py-2 flex items-center justify-between" style={{ borderBottom: '1px solid var(--c-border)' }}>
|
|
@@ -4,6 +4,7 @@ import { Chart as ChartJS, ArcElement, Tooltip, Legend, CategoryScale, LinearSca
|
|
|
4
4
|
import { Bar, Line, Doughnut } from 'react-chartjs-2'
|
|
5
5
|
import { executeQuery, fetchSchema } from '../lib/api'
|
|
6
6
|
import { useTheme } from '../lib/theme'
|
|
7
|
+
import PageHeader from '../components/PageHeader'
|
|
7
8
|
|
|
8
9
|
ChartJS.register(ArcElement, Tooltip, Legend, CategoryScale, LinearScale, BarElement, PointElement, LineElement, Filler)
|
|
9
10
|
|
|
@@ -132,24 +133,22 @@ export default function SqlViewer() {
|
|
|
132
133
|
const cardBg = { background: 'var(--c-card)', border: '1px solid var(--c-border)' }
|
|
133
134
|
|
|
134
135
|
return (
|
|
135
|
-
<div className="space-y-3">
|
|
136
|
+
<div className="fade-in space-y-3">
|
|
136
137
|
{/* Header */}
|
|
137
|
-
<
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
138
|
+
<PageHeader icon={Database} title="SQL Viewer">
|
|
139
|
+
<span className="text-[10px] px-1.5 py-0.5" style={{ color: 'var(--c-text3)', background: 'var(--c-bg3)' }}>cache.db</span>
|
|
140
|
+
<div className="ml-auto">
|
|
141
|
+
<button
|
|
142
|
+
onClick={() => setShowSchema(!showSchema)}
|
|
143
|
+
className="flex items-center gap-1 text-[11px] px-2 py-1 transition hover:bg-[var(--c-card)]"
|
|
144
|
+
style={{ color: 'var(--c-text2)', border: '1px solid var(--c-border)' }}
|
|
145
|
+
>
|
|
146
|
+
<Table2 size={11} />
|
|
147
|
+
Schema
|
|
148
|
+
<ChevronDown size={10} className={`transition ${showSchema ? 'rotate-180' : ''}`} />
|
|
149
|
+
</button>
|
|
142
150
|
</div>
|
|
143
|
-
|
|
144
|
-
onClick={() => setShowSchema(!showSchema)}
|
|
145
|
-
className="flex items-center gap-1 text-[12px] px-2 py-1 rounded transition hover:bg-[var(--c-card)]"
|
|
146
|
-
style={txt2Style}
|
|
147
|
-
>
|
|
148
|
-
<Table2 size={12} />
|
|
149
|
-
Schema
|
|
150
|
-
<ChevronDown size={10} className={`transition ${showSchema ? 'rotate-180' : ''}`} />
|
|
151
|
-
</button>
|
|
152
|
-
</div>
|
|
151
|
+
</PageHeader>
|
|
153
152
|
|
|
154
153
|
{/* Schema panel */}
|
|
155
154
|
{showSchema && schema && (
|
|
@@ -4,6 +4,7 @@ import { fetchUsage } from '../lib/api'
|
|
|
4
4
|
import { editorLabel, editorColor } from '../lib/constants'
|
|
5
5
|
import EditorIcon from '../components/EditorIcon'
|
|
6
6
|
import AnimatedLoader from '../components/AnimatedLoader'
|
|
7
|
+
import PageHeader from '../components/PageHeader'
|
|
7
8
|
|
|
8
9
|
function UsageBar({ value, max = 100, color, label }) {
|
|
9
10
|
const pct = max > 0 ? Math.min((value / max) * 100, 100) : 0
|
|
@@ -364,12 +365,8 @@ export default function Subscriptions() {
|
|
|
364
365
|
useEffect(() => { load() }, [])
|
|
365
366
|
|
|
366
367
|
return (
|
|
367
|
-
<div className="fade-in space-y-
|
|
368
|
-
<
|
|
369
|
-
<div className="flex items-center gap-1.5 text-[13px] font-bold" style={{ color: 'var(--c-white)' }}>
|
|
370
|
-
<CreditCard size={14} style={{ color: '#6366f1' }} />
|
|
371
|
-
Subscriptions
|
|
372
|
-
</div>
|
|
368
|
+
<div className="fade-in space-y-3">
|
|
369
|
+
<PageHeader icon={CreditCard} title="Subscriptions">
|
|
373
370
|
<button
|
|
374
371
|
onClick={load}
|
|
375
372
|
disabled={loading}
|
|
@@ -384,7 +381,7 @@ export default function Subscriptions() {
|
|
|
384
381
|
{data.length} subscription{data.length !== 1 ? 's' : ''} detected
|
|
385
382
|
</span>
|
|
386
383
|
)}
|
|
387
|
-
</
|
|
384
|
+
</PageHeader>
|
|
388
385
|
|
|
389
386
|
{loading && !data && (
|
|
390
387
|
<AnimatedLoader label="Loading subscriptions..." />
|