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.
@@ -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-4">
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-4">
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.5 text-[12px] outline-none rounded-sm"
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 flex-1">
155
- <Search size={13} className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: 'var(--c-text3)' }} />
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="search projects..."
161
+ placeholder="Search projects..."
159
162
  value={search}
160
163
  onChange={e => setSearch(e.target.value)}
161
- className="w-full pl-8 pr-3 py-1.5 text-[12px] outline-none rounded-sm"
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-4">
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-4">
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-4">
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-3">
425
- <div className="relative">
426
- <Filter size={13} className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: 'var(--c-text3)' }} />
427
- <select
428
- value={editor}
429
- onChange={e => setEditor(e.target.value)}
430
- className="pl-8 pr-3 py-1 text-[12px] outline-none appearance-none cursor-pointer"
431
- style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
432
- >
433
- <option value="">All Editors</option>
434
- {editors.map(e => (
435
- <option key={e.id} value={e.id}>{editorLabel(e.id)} ({e.count})</option>
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={13} className="absolute left-3 top-1/2 -translate-y-1/2" style={{ color: 'var(--c-text3)' }} />
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="search sessions..."
443
+ placeholder="Search sessions..."
444
444
  value={search}
445
445
  onChange={e => setSearch(e.target.value)}
446
- className="w-full pl-8 pr-3 py-1 text-[12px] outline-none"
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-4">
51
- <div className="flex items-center gap-1.5 text-[13px] font-bold" style={{ color: 'var(--c-white)' }}>
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
- <div className="flex items-center justify-between">
138
- <div className="flex items-center gap-2">
139
- <Database size={16} style={txtStyle} />
140
- <h1 className="text-sm font-semibold" style={txtStyle}>SQL Viewer</h1>
141
- <span className="text-[11px] px-1.5 py-0.5 rounded" style={{ ...txt2Style, background: 'var(--c-bg2)' }}>cache.db</span>
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
- <button
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-4">
368
- <div className="flex items-center gap-3">
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
- </div>
384
+ </PageHeader>
388
385
 
389
386
  {loading && !data && (
390
387
  <AnimatedLoader label="Loading subscriptions..." />