agentlytics 0.1.3 → 0.1.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.
@@ -104,7 +104,7 @@ export default function ProjectDetail() {
104
104
  <div className="flex items-start gap-3">
105
105
  <button
106
106
  onClick={() => navigate('/projects')}
107
- className="flex items-center gap-1 text-[11px] transition mt-0.5 flex-shrink-0"
107
+ className="flex items-center gap-1 text-[12px] transition mt-0.5 flex-shrink-0"
108
108
  style={{ color: 'var(--c-text3)' }}
109
109
  >
110
110
  <ArrowLeft size={12} />
@@ -112,7 +112,7 @@ export default function ProjectDetail() {
112
112
  <FolderOpen size={18} className="flex-shrink-0 mt-0.5" style={{ color: 'var(--c-accent)' }} />
113
113
  <div className="flex-1 min-w-0">
114
114
  <h1 className="text-sm font-bold truncate" style={{ color: 'var(--c-white)' }}>{project.name}</h1>
115
- <div className="text-[10px] truncate" style={{ color: 'var(--c-text3)' }}>{project.folder}</div>
115
+ <div className="text-[11px] truncate" style={{ color: 'var(--c-text3)' }}>{project.folder}</div>
116
116
  </div>
117
117
  <div className="flex items-center gap-1.5 flex-shrink-0">
118
118
  {editorEntries.map(([e]) => (
@@ -120,7 +120,7 @@ export default function ProjectDetail() {
120
120
  ))}
121
121
  </div>
122
122
  </div>
123
- <div className="flex items-center gap-4 mt-3 pt-3 text-[10px]" style={{ borderTop: '1px solid var(--c-border)' }}>
123
+ <div className="flex items-center gap-4 mt-3 pt-3 text-[11px]" style={{ borderTop: '1px solid var(--c-border)' }}>
124
124
  <div className="flex items-center gap-1" style={{ color: 'var(--c-text3)' }}>
125
125
  <Calendar size={9} />
126
126
  <span>{formatDate(project.firstSeen)}</span>
@@ -169,11 +169,11 @@ export default function ProjectDetail() {
169
169
  className="accent-[var(--c-accent)] w-3 h-3 flex-shrink-0 cursor-pointer"
170
170
  />
171
171
  <EditorIcon source={e} size={11} />
172
- <span className="text-[10px] truncate flex-1 cursor-pointer select-none" onClick={() => toggleEditor(e)} style={{ color: checked ? 'var(--c-text2)' : 'var(--c-text3)', opacity: checked ? 1 : 0.4 }}>{editorLabel(e)}</span>
172
+ <span className="text-[11px] truncate flex-1 cursor-pointer select-none" onClick={() => toggleEditor(e)} style={{ color: checked ? 'var(--c-text2)' : 'var(--c-text3)', opacity: checked ? 1 : 0.4 }}>{editorLabel(e)}</span>
173
173
  <div className="w-16 h-3 rounded-sm overflow-hidden" style={{ background: 'var(--c-code-bg)' }}>
174
174
  <div className="h-full rounded-sm transition-all" style={{ width: `${(count / fMaxEditorCount * 100).toFixed(0)}%`, background: checked ? editorColor(e) : 'var(--c-text3)', opacity: checked ? 1 : 0.2 }} />
175
175
  </div>
176
- <span className="text-[10px] w-6 text-right font-bold" style={{ color: checked ? 'var(--c-white)' : 'var(--c-text3)', opacity: checked ? 1 : 0.4 }}>{count}</span>
176
+ <span className="text-[11px] w-6 text-right font-bold" style={{ color: checked ? 'var(--c-white)' : 'var(--c-text3)', opacity: checked ? 1 : 0.4 }}>{count}</span>
177
177
  </div>
178
178
  )
179
179
  })}
@@ -199,7 +199,7 @@ export default function ProjectDetail() {
199
199
  }}
200
200
  />
201
201
  </div>
202
- ) : <div className="text-[10px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no model data</div>}
202
+ ) : <div className="text-[11px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no model data</div>}
203
203
  </div>
204
204
 
205
205
  {/* Top tools horizontal bar */}
@@ -226,7 +226,7 @@ export default function ProjectDetail() {
226
226
  }}
227
227
  />
228
228
  </div>
229
- ) : <div className="text-[10px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no tool data</div>}
229
+ ) : <div className="text-[11px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no tool data</div>}
230
230
  </div>
231
231
  </div>
232
232
 
@@ -241,16 +241,16 @@ export default function ProjectDetail() {
241
241
  placeholder="filter sessions..."
242
242
  value={chatSearch}
243
243
  onChange={e => setChatSearch(e.target.value)}
244
- className="w-full pl-7 pr-3 py-1 text-[11px] outline-none rounded-sm"
244
+ className="w-full pl-7 pr-3 py-1 text-[12px] outline-none rounded-sm"
245
245
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
246
246
  />
247
247
  </div>
248
248
  </div>
249
249
 
250
250
  <div className="card overflow-hidden">
251
- <table className="w-full text-[11px]">
251
+ <table className="w-full text-[12px]">
252
252
  <thead>
253
- <tr className="text-[9px] uppercase tracking-wider" style={{ borderBottom: '1px solid var(--c-border)', color: 'var(--c-text3)' }}>
253
+ <tr className="text-[10px] uppercase tracking-wider" style={{ borderBottom: '1px solid var(--c-border)', color: 'var(--c-text3)' }}>
254
254
  <th className="text-left py-2 px-3 font-medium">editor</th>
255
255
  <th className="text-left py-2 px-3 font-medium">name</th>
256
256
  <th className="text-left py-2 px-3 font-medium">mode</th>
@@ -277,7 +277,7 @@ export default function ProjectDetail() {
277
277
  </td>
278
278
  <td className="py-2 px-3 font-medium truncate max-w-[280px]" style={{ color: 'var(--c-white)' }}>
279
279
  {c.name || <span style={{ color: 'var(--c-text3)' }}>Untitled</span>}
280
- {c.encrypted && <span className="ml-1.5 text-[9px] text-yellow-500/60">locked</span>}
280
+ {c.encrypted && <span className="ml-1.5 text-[10px] text-yellow-500/60">locked</span>}
281
281
  </td>
282
282
  <td className="py-2 px-3" style={{ color: 'var(--c-text2)' }}>{c.mode || ''}</td>
283
283
  <td className="py-2 px-3 font-mono truncate max-w-[150px]" style={{ color: 'var(--c-text2)' }} title={c.topModel || ''}>{c.topModel || ''}</td>
@@ -136,7 +136,7 @@ export default function Projects({ overview }) {
136
136
  <select
137
137
  value={editorFilter}
138
138
  onChange={e => setEditorFilter(e.target.value)}
139
- className="px-2 py-1.5 text-[11px] outline-none rounded-sm"
139
+ className="px-2 py-1.5 text-[12px] outline-none rounded-sm"
140
140
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
141
141
  >
142
142
  <option value="">All Editors</option>
@@ -151,7 +151,7 @@ export default function Projects({ overview }) {
151
151
  placeholder="search projects..."
152
152
  value={search}
153
153
  onChange={e => setSearch(e.target.value)}
154
- className="w-full pl-8 pr-3 py-1.5 text-[11px] outline-none rounded-sm"
154
+ className="w-full pl-8 pr-3 py-1.5 text-[12px] outline-none rounded-sm"
155
155
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
156
156
  />
157
157
  </div>
@@ -176,7 +176,7 @@ export default function Projects({ overview }) {
176
176
  <FolderOpen size={14} className="flex-shrink-0 mt-0.5" style={{ color: 'var(--c-accent)' }} />
177
177
  <div className="flex-1 min-w-0">
178
178
  <div className="text-[12px] font-bold truncate" style={{ color: 'var(--c-white)' }}>{p.name}</div>
179
- <div className="text-[9px] truncate" style={{ color: 'var(--c-text3)' }}>{p.folder}</div>
179
+ <div className="text-[10px] truncate" style={{ color: 'var(--c-text3)' }}>{p.folder}</div>
180
180
  </div>
181
181
  <div className="flex items-center gap-1 flex-shrink-0">
182
182
  {editorEntries.slice(0, 4).map(([e]) => (
@@ -191,7 +191,7 @@ export default function Projects({ overview }) {
191
191
  </div>
192
192
 
193
193
  {/* Stats grid */}
194
- <div className="grid grid-cols-2 gap-x-3 gap-y-1 text-[10px]">
194
+ <div className="grid grid-cols-2 gap-x-3 gap-y-1 text-[11px]">
195
195
  <div className="flex items-center gap-1">
196
196
  <MessageSquare size={9} style={{ color: 'var(--c-text3)' }} />
197
197
  <span style={{ color: 'var(--c-text2)' }}>{p.totalSessions} sessions</span>
@@ -213,7 +213,7 @@ export default function Projects({ overview }) {
213
213
  </div>
214
214
 
215
215
  {/* Footer: editors breakdown + date */}
216
- <div className="flex items-center gap-2 pt-1 text-[9px]" style={{ borderTop: '1px solid var(--c-border)' }}>
216
+ <div className="flex items-center gap-2 pt-1 text-[10px]" style={{ borderTop: '1px solid var(--c-border)' }}>
217
217
  <div className="flex items-center gap-1.5 flex-1 min-w-0">
218
218
  {editorEntries.map(([e, c]) => (
219
219
  <span key={e} className="inline-flex items-center gap-0.5 truncate">
@@ -88,7 +88,7 @@ function TeamSidebar({ userList, userColorMap, onUserClick, selectedUser }) {
88
88
  {u.username.charAt(0).toUpperCase()}
89
89
  </div>
90
90
  <div className="flex-1 min-w-0">
91
- <div className="text-[10px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{u.username}</div>
91
+ <div className="text-[11px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{u.username}</div>
92
92
  <div className="flex items-center gap-1 text-[8px]" style={{ color: 'var(--c-text3)' }}>
93
93
  <span>{u.sessions}s</span>
94
94
  <span>·</span>
@@ -110,8 +110,8 @@ function TeamSidebar({ userList, userColorMap, onUserClick, selectedUser }) {
110
110
  <div className="flex flex-col h-full">
111
111
  <div className="flex items-center gap-2 px-3 py-2.5 shrink-0" style={{ borderBottom: '1px solid var(--c-border)' }}>
112
112
  <Users size={12} style={{ color: 'var(--c-accent)' }} />
113
- <span className="text-[11px] font-medium uppercase tracking-wider" style={{ color: 'var(--c-text2)' }}>Team</span>
114
- <span className="text-[9px] ml-auto" style={{ color: 'var(--c-text3)' }}>{userList.length}</span>
113
+ <span className="text-[12px] font-medium uppercase tracking-wider" style={{ color: 'var(--c-text2)' }}>Team</span>
114
+ <span className="text-[10px] ml-auto" style={{ color: 'var(--c-text3)' }}>{userList.length}</span>
115
115
  </div>
116
116
 
117
117
  <div className="flex-1 overflow-y-auto scrollbar-thin py-1">
@@ -129,7 +129,7 @@ function TeamSidebar({ userList, userColorMap, onUserClick, selectedUser }) {
129
129
  >
130
130
  {isCollapsed ? <ChevronRight size={10} style={{ color: 'var(--c-text3)' }} /> : <ChevronDown size={10} style={{ color: 'var(--c-text3)' }} />}
131
131
  <FolderOpen size={10} style={{ color: '#818cf8' }} />
132
- <span className="text-[10px] font-medium truncate flex-1" style={{ color: 'var(--c-text2)' }} title={proj}>{projName}</span>
132
+ <span className="text-[11px] font-medium truncate flex-1" style={{ color: 'var(--c-text2)' }} title={proj}>{projName}</span>
133
133
  <span className="text-[8px]" style={{ color: 'var(--c-text3)' }}>{users.length}</span>
134
134
  </div>
135
135
  {!isCollapsed && (
@@ -145,7 +145,7 @@ function TeamSidebar({ userList, userColorMap, onUserClick, selectedUser }) {
145
145
  {ungrouped.length > 0 && (
146
146
  <div>
147
147
  {projectGroups.length > 0 && (
148
- <div className="px-2 py-1.5 text-[9px] uppercase tracking-wider" style={{ color: 'var(--c-text3)' }}>
148
+ <div className="px-2 py-1.5 text-[10px] uppercase tracking-wider" style={{ color: 'var(--c-text3)' }}>
149
149
  unassigned
150
150
  </div>
151
151
  )}
@@ -156,7 +156,7 @@ function TeamSidebar({ userList, userColorMap, onUserClick, selectedUser }) {
156
156
  )}
157
157
 
158
158
  {userList.length === 0 && (
159
- <div className="text-[10px] py-6 text-center" style={{ color: 'var(--c-text3)' }}>
159
+ <div className="text-[11px] py-6 text-center" style={{ color: 'var(--c-text3)' }}>
160
160
  No team members yet
161
161
  </div>
162
162
  )}
@@ -180,7 +180,7 @@ function MergeSection({ userList }) {
180
180
  return (
181
181
  <div className="shrink-0 px-2 py-2" style={{ borderTop: '1px solid var(--c-border)' }}>
182
182
  <div
183
- className="flex items-center gap-1.5 cursor-pointer text-[9px] uppercase tracking-wider"
183
+ className="flex items-center gap-1.5 cursor-pointer text-[10px] uppercase tracking-wider"
184
184
  style={{ color: 'var(--c-text3)' }}
185
185
  onClick={() => setOpen(!open)}
186
186
  >
@@ -193,7 +193,7 @@ function MergeSection({ userList }) {
193
193
  <select
194
194
  value={mergeFrom}
195
195
  onChange={e => setMergeFrom(e.target.value)}
196
- className="w-full text-[10px] px-1.5 py-1 outline-none rounded-sm"
196
+ className="w-full text-[11px] px-1.5 py-1 outline-none rounded-sm"
197
197
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
198
198
  >
199
199
  <option value="">from...</option>
@@ -204,7 +204,7 @@ function MergeSection({ userList }) {
204
204
  <select
205
205
  value={mergeTo}
206
206
  onChange={e => setMergeTo(e.target.value)}
207
- className="w-full text-[10px] px-1.5 py-1 outline-none rounded-sm"
207
+ className="w-full text-[11px] px-1.5 py-1 outline-none rounded-sm"
208
208
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
209
209
  >
210
210
  <option value="">into...</option>
@@ -228,7 +228,7 @@ function MergeSection({ userList }) {
228
228
  }
229
229
  setMerging(false)
230
230
  }}
231
- className="w-full text-[10px] px-2 py-1 font-medium transition rounded-sm"
231
+ className="w-full text-[11px] px-2 py-1 font-medium transition rounded-sm"
232
232
  style={{
233
233
  background: mergeFrom && mergeTo ? 'rgba(239,68,68,0.15)' : 'var(--c-bg3)',
234
234
  color: mergeFrom && mergeTo ? '#ef4444' : 'var(--c-text3)',
@@ -240,7 +240,7 @@ function MergeSection({ userList }) {
240
240
  {merging ? 'Merging...' : 'Merge'}
241
241
  </button>
242
242
  {mergeResult && (
243
- <div className="text-[9px]" style={{ color: mergeResult.error ? '#ef4444' : '#22c55e' }}>
243
+ <div className="text-[10px]" style={{ color: mergeResult.error ? '#ef4444' : '#22c55e' }}>
244
244
  {mergeResult.error ? `Error: ${mergeResult.error}` : 'Merged!'}
245
245
  </div>
246
246
  )}
@@ -334,25 +334,25 @@ export default function RelayDashboard() {
334
334
  <div className="card p-3">
335
335
  <div className="flex items-center justify-between mb-2">
336
336
  <SectionTitle>team token usage</SectionTitle>
337
- <span className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(totalTok)} total</span>
337
+ <span className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(totalTok)} total</span>
338
338
  </div>
339
339
  <ProportionBar height={10} segments={[
340
340
  { label: 'Input', value: stats.totalInputTokens, color: '#6366f1' },
341
341
  { label: 'Output', value: stats.totalOutputTokens, color: '#a78bfa' },
342
342
  ]} />
343
- <div className="flex items-center gap-4 mt-1.5 text-[9px]">
343
+ <div className="flex items-center gap-4 mt-1.5 text-[10px]">
344
344
  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm" style={{ background: '#6366f1' }} /> input {formatNumber(stats.totalInputTokens)}</span>
345
345
  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm" style={{ background: '#a78bfa' }} /> output {formatNumber(stats.totalOutputTokens)}</span>
346
346
  </div>
347
347
  {userList.length > 1 && (
348
348
  <div className="mt-3 pt-2" style={{ borderTop: '1px solid var(--c-border)' }}>
349
- <div className="text-[9px] mb-1.5" style={{ color: 'var(--c-text3)' }}>per-user contribution</div>
349
+ <div className="text-[10px] mb-1.5" style={{ color: 'var(--c-text3)' }}>per-user contribution</div>
350
350
  <ProportionBar height={8} segments={userList.map(u => ({
351
351
  label: u.username,
352
352
  value: u.totalInputTokens + u.totalOutputTokens,
353
353
  color: userColorMap[u.username],
354
354
  }))} />
355
- <div className="flex flex-wrap gap-3 mt-1 text-[9px]">
355
+ <div className="flex flex-wrap gap-3 mt-1 text-[10px]">
356
356
  {userList.map(u => (
357
357
  <span key={u.username} className="flex items-center gap-1" style={{ color: 'var(--c-text3)' }}>
358
358
  <span className="w-2 h-2 rounded-sm" style={{ background: userColorMap[u.username] }} />
@@ -445,14 +445,14 @@ export default function RelayDashboard() {
445
445
  value={search}
446
446
  onChange={e => setSearch(e.target.value)}
447
447
  placeholder="Search messages, files, topics across all users..."
448
- className="w-full pl-7 pr-3 py-1.5 text-[11px] outline-none rounded-sm"
448
+ className="w-full pl-7 pr-3 py-1.5 text-[12px] outline-none rounded-sm"
449
449
  style={{ background: 'var(--c-bg3)', color: 'var(--c-white)', border: '1px solid var(--c-border)' }}
450
450
  />
451
451
  </div>
452
452
  <button
453
453
  type="submit"
454
454
  disabled={searching}
455
- className="px-3 py-1.5 text-[10px] font-medium transition rounded-sm"
455
+ className="px-3 py-1.5 text-[11px] font-medium transition rounded-sm"
456
456
  style={{ background: 'var(--c-card)', border: '1px solid var(--c-border)', color: 'var(--c-white)' }}
457
457
  >
458
458
  {searching ? 'Searching...' : 'Search'}
@@ -461,9 +461,9 @@ export default function RelayDashboard() {
461
461
  {searchResults && (
462
462
  <div className="mt-3 max-h-[300px] overflow-y-auto scrollbar-thin">
463
463
  {searchResults.length === 0 ? (
464
- <div className="text-[11px] py-2" style={{ color: 'var(--c-text3)' }}>No results found</div>
464
+ <div className="text-[12px] py-2" style={{ color: 'var(--c-text3)' }}>No results found</div>
465
465
  ) : (
466
- <table className="w-full text-[11px]">
466
+ <table className="w-full text-[12px]">
467
467
  <tbody>
468
468
  {searchResults.map((r, i) => (
469
469
  <tr
@@ -475,14 +475,14 @@ export default function RelayDashboard() {
475
475
  onClick={() => { setSelectedChat(r.chatId); setSelectedUsername(r.username) }}
476
476
  >
477
477
  <td className="py-2 px-2 w-[80px]">
478
- <span className="text-[9px] font-medium px-1.5 py-0.5" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>{r.username}</span>
478
+ <span className="text-[10px] font-medium px-1.5 py-0.5" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>{r.username}</span>
479
479
  </td>
480
480
  <td className="py-2 px-2 w-[24px]"><EditorIcon source={r.source} size={11} /></td>
481
481
  <td className="py-2 px-2">
482
- <div className="text-[10px] truncate" style={{ color: 'var(--c-text3)' }}>{r.chatName}</div>
483
- <div className="text-[10px] line-clamp-1 mt-0.5" style={{ color: 'var(--c-text)' }}>{r.content}</div>
482
+ <div className="text-[11px] truncate" style={{ color: 'var(--c-text3)' }}>{r.chatName}</div>
483
+ <div className="text-[11px] line-clamp-1 mt-0.5" style={{ color: 'var(--c-text)' }}>{r.content}</div>
484
484
  </td>
485
- <td className="py-2 px-2 text-[9px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>{r.role}</td>
485
+ <td className="py-2 px-2 text-[10px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>{r.role}</td>
486
486
  </tr>
487
487
  ))}
488
488
  </tbody>
@@ -506,12 +506,12 @@ export default function RelayDashboard() {
506
506
  onClick={() => navigate(`/relay/user/${u.username}`)}
507
507
  >
508
508
  <div className="flex items-center gap-2 mb-2">
509
- <div className="w-7 h-7 flex items-center justify-center text-[11px] font-bold rounded-sm flex-shrink-0" style={{ background: `${color}20`, color }}>
509
+ <div className="w-7 h-7 flex items-center justify-center text-[12px] font-bold rounded-sm flex-shrink-0" style={{ background: `${color}20`, color }}>
510
510
  {u.username.charAt(0).toUpperCase()}
511
511
  </div>
512
512
  <div className="flex-1 min-w-0">
513
- <div className="text-[11px] font-bold truncate" style={{ color: 'var(--c-white)' }}>{u.username}</div>
514
- <div className="text-[9px]" style={{ color: 'var(--c-text3)' }}>
513
+ <div className="text-[12px] font-bold truncate" style={{ color: 'var(--c-white)' }}>{u.username}</div>
514
+ <div className="text-[10px]" style={{ color: 'var(--c-text3)' }}>
515
515
  {u.lastActive ? formatDate(u.lastActive) : 'No activity'}
516
516
  </div>
517
517
  </div>
@@ -529,7 +529,7 @@ export default function RelayDashboard() {
529
529
  [formatNumber(uTok), 'tokens'],
530
530
  ].map(([v, l]) => (
531
531
  <div key={l} className="p-1 rounded-sm" style={{ background: 'var(--c-code-bg)' }}>
532
- <div className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{v}</div>
532
+ <div className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{v}</div>
533
533
  <div className="text-[7px]" style={{ color: 'var(--c-text3)' }}>{l}</div>
534
534
  </div>
535
535
  ))}
@@ -554,7 +554,7 @@ export default function RelayDashboard() {
554
554
  <div className="card p-8 text-center">
555
555
  <Users size={32} className="mx-auto mb-3" style={{ color: 'var(--c-text3)' }} />
556
556
  <div className="text-[12px] font-medium mb-1" style={{ color: 'var(--c-white)' }}>No team members yet</div>
557
- <div className="text-[10px]" style={{ color: 'var(--c-text3)' }}>Share the join command with your team to start collecting data</div>
557
+ <div className="text-[11px]" style={{ color: 'var(--c-text3)' }}>Share the join command with your team to start collecting data</div>
558
558
  </div>
559
559
  )}
560
560
  </div>
@@ -575,7 +575,7 @@ export default function RelayDashboard() {
575
575
  username={selectedUsername}
576
576
  extraHeader={
577
577
  selectedUsername ? (
578
- <span className="text-[10px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
578
+ <span className="text-[11px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
579
579
  {selectedUsername}
580
580
  </span>
581
581
  ) : null
@@ -15,7 +15,7 @@ export default function RelaySessionDetail() {
15
15
  )
16
16
 
17
17
  const extraHeader = username ? (
18
- <span className="text-[10px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
18
+ <span className="text-[11px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
19
19
  {username}
20
20
  </span>
21
21
  ) : null
@@ -73,7 +73,7 @@ function SessionSidebar({ sessions, projects, selectedChat, onSelectChat }) {
73
73
  >
74
74
  <EditorIcon source={s.source} size={10} />
75
75
  <div className="flex-1 min-w-0">
76
- <div className="text-[10px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{s.name || 'Untitled'}</div>
76
+ <div className="text-[11px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{s.name || 'Untitled'}</div>
77
77
  <div className="flex items-center gap-1 text-[8px]" style={{ color: 'var(--c-text3)' }}>
78
78
  {s.totalMessages > 0 && <span>{s.totalMessages}m</span>}
79
79
  {s.totalMessages > 0 && s.lastUpdatedAt && <span>·</span>}
@@ -87,8 +87,8 @@ function SessionSidebar({ sessions, projects, selectedChat, onSelectChat }) {
87
87
  <div className="flex flex-col h-full">
88
88
  <div className="flex items-center gap-2 px-3 py-2.5 shrink-0" style={{ borderBottom: '1px solid var(--c-border)' }}>
89
89
  <Hash size={12} style={{ color: 'var(--c-accent)' }} />
90
- <span className="text-[11px] font-medium uppercase tracking-wider" style={{ color: 'var(--c-text2)' }}>Sessions</span>
91
- <span className="text-[9px] ml-auto" style={{ color: 'var(--c-text3)' }}>{sessions.length}</span>
90
+ <span className="text-[12px] font-medium uppercase tracking-wider" style={{ color: 'var(--c-text2)' }}>Sessions</span>
91
+ <span className="text-[10px] ml-auto" style={{ color: 'var(--c-text3)' }}>{sessions.length}</span>
92
92
  </div>
93
93
 
94
94
  <div className="flex-1 overflow-y-auto scrollbar-thin py-1">
@@ -105,7 +105,7 @@ function SessionSidebar({ sessions, projects, selectedChat, onSelectChat }) {
105
105
  >
106
106
  {isCollapsed ? <ChevronRight size={10} style={{ color: 'var(--c-text3)' }} /> : <ChevronDown size={10} style={{ color: 'var(--c-text3)' }} />}
107
107
  <FolderOpen size={10} style={{ color: '#818cf8' }} />
108
- <span className="text-[10px] font-medium truncate flex-1" style={{ color: 'var(--c-text2)' }} title={folder}>{folderName}</span>
108
+ <span className="text-[11px] font-medium truncate flex-1" style={{ color: 'var(--c-text2)' }} title={folder}>{folderName}</span>
109
109
  <span className="text-[8px]" style={{ color: 'var(--c-text3)' }}>{list.length}</span>
110
110
  </div>
111
111
  {!isCollapsed && (
@@ -120,7 +120,7 @@ function SessionSidebar({ sessions, projects, selectedChat, onSelectChat }) {
120
120
  {grouped.noProject.length > 0 && (
121
121
  <div>
122
122
  {grouped.sorted.length > 0 && (
123
- <div className="px-2 py-1.5 text-[9px] uppercase tracking-wider" style={{ color: 'var(--c-text3)' }}>no project</div>
123
+ <div className="px-2 py-1.5 text-[10px] uppercase tracking-wider" style={{ color: 'var(--c-text3)' }}>no project</div>
124
124
  )}
125
125
  <div className={grouped.sorted.length > 0 ? 'pl-1' : ''}>
126
126
  {grouped.noProject.map(s => <SessionItem key={s.id} s={s} />)}
@@ -270,13 +270,13 @@ export default function RelayUserDetail() {
270
270
  <div className="card p-3">
271
271
  <div className="flex items-center justify-between mb-2">
272
272
  <SectionTitle>token usage</SectionTitle>
273
- <span className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(totalTokens)} total</span>
273
+ <span className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(totalTokens)} total</span>
274
274
  </div>
275
275
  <ProportionBar height={10} segments={[
276
276
  { label: 'Input', value: totalInputTokens, color: '#6366f1' },
277
277
  { label: 'Output', value: totalOutputTokens, color: '#a78bfa' },
278
278
  ]} />
279
- <div className="flex items-center gap-4 mt-1.5 text-[9px]">
279
+ <div className="flex items-center gap-4 mt-1.5 text-[10px]">
280
280
  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm" style={{ background: '#6366f1' }} /> input {formatNumber(totalInputTokens)}</span>
281
281
  <span className="flex items-center gap-1"><span className="w-2 h-2 rounded-sm" style={{ background: '#a78bfa' }} /> output {formatNumber(totalOutputTokens)}</span>
282
282
  </div>
@@ -363,20 +363,20 @@ export default function RelayUserDetail() {
363
363
  <div key={folder} className="card px-3 py-2.5">
364
364
  <div className="flex items-center gap-1.5 mb-1.5">
365
365
  <FolderOpen size={11} style={{ color: '#818cf8' }} />
366
- <span className="text-[11px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{folder.split('/').pop()}</span>
366
+ <span className="text-[12px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{folder.split('/').pop()}</span>
367
367
  </div>
368
368
  <div className="text-[8px] truncate mb-2" style={{ color: 'var(--c-text3)' }}>{folder}</div>
369
369
  <div className="grid grid-cols-3 gap-1 text-center mb-1.5">
370
370
  <div className="p-1 rounded-sm" style={{ background: 'var(--c-code-bg)' }}>
371
- <div className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{info.count}</div>
371
+ <div className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{info.count}</div>
372
372
  <div className="text-[7px]" style={{ color: 'var(--c-text3)' }}>sessions</div>
373
373
  </div>
374
374
  <div className="p-1 rounded-sm" style={{ background: 'var(--c-code-bg)' }}>
375
- <div className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(info.messages)}</div>
375
+ <div className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(info.messages)}</div>
376
376
  <div className="text-[7px]" style={{ color: 'var(--c-text3)' }}>messages</div>
377
377
  </div>
378
378
  <div className="p-1 rounded-sm" style={{ background: 'var(--c-code-bg)' }}>
379
- <div className="text-[10px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(info.tokens)}</div>
379
+ <div className="text-[11px] font-bold" style={{ color: 'var(--c-white)' }}>{formatNumber(info.tokens)}</div>
380
380
  <div className="text-[7px]" style={{ color: 'var(--c-text3)' }}>tokens</div>
381
381
  </div>
382
382
  </div>
@@ -396,7 +396,7 @@ export default function RelayUserDetail() {
396
396
  <SectionTitle>top tools</SectionTitle>
397
397
  <div className="flex flex-wrap gap-1.5 mt-1">
398
398
  {tools.map(([name, count]) => (
399
- <span key={name} className="text-[9px] px-2 py-1 rounded-sm" style={{ background: 'var(--c-code-bg)', color: 'var(--c-text2)' }}>
399
+ <span key={name} className="text-[10px] px-2 py-1 rounded-sm" style={{ background: 'var(--c-code-bg)', color: 'var(--c-text2)' }}>
400
400
  {name} <span style={{ color: 'var(--c-text3)' }}>×{count}</span>
401
401
  </span>
402
402
  ))}
@@ -408,7 +408,7 @@ export default function RelayUserDetail() {
408
408
  <div className="card p-3">
409
409
  <SectionTitle>recent sessions</SectionTitle>
410
410
  <div className="max-h-[400px] overflow-y-auto scrollbar-thin">
411
- <table className="w-full text-[11px]">
411
+ <table className="w-full text-[12px]">
412
412
  <tbody>
413
413
  {sessions.slice(0, 50).map(s => (
414
414
  <tr
@@ -421,10 +421,10 @@ export default function RelayUserDetail() {
421
421
  >
422
422
  <td className="py-2 px-2 w-[24px]"><EditorIcon source={s.source} size={11} /></td>
423
423
  <td className="py-2 px-2">
424
- <div className="text-[10px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{s.name || 'Untitled'}</div>
425
- <div className="text-[9px] truncate" style={{ color: 'var(--c-text3)' }}>{s.folder ? s.folder.split('/').pop() : ''}</div>
424
+ <div className="text-[11px] font-medium truncate" style={{ color: 'var(--c-white)' }}>{s.name || 'Untitled'}</div>
425
+ <div className="text-[10px] truncate" style={{ color: 'var(--c-text3)' }}>{s.folder ? s.folder.split('/').pop() : ''}</div>
426
426
  </td>
427
- <td className="py-2 px-2 text-[9px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>
427
+ <td className="py-2 px-2 text-[10px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>
428
428
  {s.totalMessages > 0 && <span>{s.totalMessages}m</span>}
429
429
  </td>
430
430
  <td className="py-2 px-2">
@@ -432,7 +432,7 @@ export default function RelayUserDetail() {
432
432
  <span className="text-[8px] px-1.5 py-0.5 rounded-sm" style={{ background: 'rgba(168,85,247,0.1)', color: '#a855f7' }}>{s.mode}</span>
433
433
  )}
434
434
  </td>
435
- <td className="py-2 px-2 text-[9px] whitespace-nowrap text-right" style={{ color: 'var(--c-text3)' }}>
435
+ <td className="py-2 px-2 text-[10px] whitespace-nowrap text-right" style={{ color: 'var(--c-text3)' }}>
436
436
  {formatDate(s.lastUpdatedAt)}
437
437
  </td>
438
438
  </tr>
@@ -458,7 +458,7 @@ export default function RelayUserDetail() {
458
458
  fetchFn={fetchFn}
459
459
  username={username}
460
460
  extraHeader={
461
- <span className="text-[10px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
461
+ <span className="text-[11px] font-medium px-1.5 py-0.5 shrink-0" style={{ background: 'rgba(99,102,241,0.15)', color: '#818cf8' }}>
462
462
  {username}
463
463
  </span>
464
464
  }
@@ -250,15 +250,15 @@ export default function Sessions({ overview }) {
250
250
  <td className="py-2 px-3">
251
251
  <span className="inline-flex items-center gap-1.5">
252
252
  <EditorIcon source={c.source} size={12} />
253
- <span className="text-[11px]" style={{ color: 'var(--c-text2)' }}>{editorLabel(c.source)}</span>
253
+ <span className="text-[12px]" style={{ color: 'var(--c-text2)' }}>{editorLabel(c.source)}</span>
254
254
  </span>
255
255
  </td>
256
- <td className="py-2 px-3 font-medium truncate max-w-[280px] text-[11px]" style={{ color: 'var(--c-white)' }}>
256
+ <td className="py-2 px-3 font-medium truncate max-w-[280px] text-[12px]" style={{ color: 'var(--c-white)' }}>
257
257
  {c.name || <span style={{ color: 'var(--c-text3)' }}>Untitled</span>}
258
- {c.encrypted && <span className="ml-1.5 text-[9px] text-yellow-500/60">locked</span>}
258
+ {c.encrypted && <span className="ml-1.5 text-[10px] text-yellow-500/60">locked</span>}
259
259
  </td>
260
260
  {!groupByProject && (
261
- <td className="py-2 px-3 truncate max-w-[160px] text-[11px]" style={{ color: 'var(--c-text2)' }} title={c.folder}>
261
+ <td className="py-2 px-3 truncate max-w-[160px] text-[12px]" style={{ color: 'var(--c-text2)' }} title={c.folder}>
262
262
  {c.folder ? (
263
263
  <span
264
264
  className="cursor-pointer hover:underline"
@@ -268,11 +268,11 @@ export default function Sessions({ overview }) {
268
268
  ) : ''}
269
269
  </td>
270
270
  )}
271
- <td className="py-2 px-3 text-[11px]" style={{ color: 'var(--c-text2)' }}>{c.mode || ''}</td>
272
- <td className="py-2 px-3 text-[11px] font-mono truncate max-w-[150px]" style={{ color: 'var(--c-text2)' }} title={c.topModel || ''}>
271
+ <td className="py-2 px-3 text-[12px]" style={{ color: 'var(--c-text2)' }}>{c.mode || ''}</td>
272
+ <td className="py-2 px-3 text-[12px] font-mono truncate max-w-[150px]" style={{ color: 'var(--c-text2)' }} title={c.topModel || ''}>
273
273
  {c.topModel || ''}
274
274
  </td>
275
- <td className="py-2 px-3 text-[11px]">
275
+ <td className="py-2 px-3 text-[12px]">
276
276
  {c.bubbleCount >= 500 ? (
277
277
  <span className="inline-flex items-center gap-0.5 font-bold" style={{ color: '#ef4444' }}>
278
278
  <AlertTriangle size={9} />{c.bubbleCount}
@@ -285,7 +285,7 @@ export default function Sessions({ overview }) {
285
285
  <span style={{ color: 'var(--c-text3)' }}>{c.bubbleCount || 0}</span>
286
286
  )}
287
287
  </td>
288
- <td className="py-2 px-3 text-[11px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>
288
+ <td className="py-2 px-3 text-[12px] whitespace-nowrap" style={{ color: 'var(--c-text3)' }}>
289
289
  {formatDate(c.lastUpdatedAt || c.createdAt)}
290
290
  </td>
291
291
  </tr>
@@ -342,7 +342,7 @@ export default function Sessions({ overview }) {
342
342
  },
343
343
  }}
344
344
  />
345
- ) : <div className="text-[10px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no model data</div>}
345
+ ) : <div className="text-[11px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no model data</div>}
346
346
  </div>
347
347
  </div>
348
348
  <div className="card p-3">
@@ -367,7 +367,7 @@ export default function Sessions({ overview }) {
367
367
  plugins: { legend: { display: false }, tooltip: { bodyFont: { family: MONO, size: 10 }, titleFont: { family: MONO, size: 10 } } },
368
368
  }}
369
369
  />
370
- ) : <div className="text-[10px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no mode data</div>}
370
+ ) : <div className="text-[11px] py-8 text-center" style={{ color: 'var(--c-text3)' }}>no mode data</div>}
371
371
  </div>
372
372
  </div>
373
373
  </div>
@@ -379,12 +379,12 @@ export default function Sessions({ overview }) {
379
379
  <div className="flex items-center justify-between mb-2">
380
380
  <SectionTitle>
381
381
  session timeline
382
- <span className="ml-2 font-normal text-[9px]" style={{ color: 'var(--c-text3)' }}>(drag to select range)</span>
382
+ <span className="ml-2 font-normal text-[10px]" style={{ color: 'var(--c-text3)' }}>(drag to select range)</span>
383
383
  </SectionTitle>
384
384
  {dateRange && (
385
385
  <button
386
386
  onClick={() => setDateRange(null)}
387
- className="flex items-center gap-1 text-[10px] px-2 py-0.5 transition"
387
+ className="flex items-center gap-1 text-[11px] px-2 py-0.5 transition"
388
388
  style={{ color: 'var(--c-accent)', border: '1px solid var(--c-border)' }}
389
389
  >
390
390
  <X size={10} />
@@ -424,7 +424,7 @@ export default function Sessions({ overview }) {
424
424
  <select
425
425
  value={editor}
426
426
  onChange={e => setEditor(e.target.value)}
427
- className="pl-8 pr-3 py-1 text-[11px] outline-none appearance-none cursor-pointer"
427
+ className="pl-8 pr-3 py-1 text-[12px] outline-none appearance-none cursor-pointer"
428
428
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
429
429
  >
430
430
  <option value="">All Editors</option>
@@ -440,13 +440,13 @@ export default function Sessions({ overview }) {
440
440
  placeholder="search sessions..."
441
441
  value={search}
442
442
  onChange={e => setSearch(e.target.value)}
443
- className="w-full pl-8 pr-3 py-1 text-[11px] outline-none"
443
+ className="w-full pl-8 pr-3 py-1 text-[12px] outline-none"
444
444
  style={{ background: 'var(--c-bg3)', color: 'var(--c-text)', border: '1px solid var(--c-border)' }}
445
445
  />
446
446
  </div>
447
447
  <button
448
448
  onClick={() => setGroupByProject(!groupByProject)}
449
- className="flex items-center gap-1.5 px-3 py-1 text-[11px] transition"
449
+ className="flex items-center gap-1.5 px-3 py-1 text-[12px] transition"
450
450
  style={{
451
451
  border: groupByProject ? '1px solid var(--c-accent)' : '1px solid var(--c-border)',
452
452
  color: groupByProject ? 'var(--c-accent)' : 'var(--c-text2)',
@@ -456,7 +456,7 @@ export default function Sessions({ overview }) {
456
456
  {groupByProject ? <FolderOpen size={13} /> : <List size={13} />}
457
457
  {groupByProject ? 'grouped' : 'flat'}
458
458
  </button>
459
- <span className="text-[10px]" style={{ color: 'var(--c-text3)' }}>
459
+ <span className="text-[11px]" style={{ color: 'var(--c-text3)' }}>
460
460
  {loading ? 'loading...' : `${filtered.length} of ${total}`}
461
461
  </span>
462
462
  {/* Server-side date range filter */}
@@ -468,7 +468,7 @@ export default function Sessions({ overview }) {
468
468
  <div className="card overflow-hidden">
469
469
  <table className="w-full text-sm">
470
470
  <thead>
471
- <tr className="text-[9px] uppercase tracking-wider" style={{ borderBottom: '1px solid var(--c-border)', color: 'var(--c-text3)' }}>
471
+ <tr className="text-[10px] uppercase tracking-wider" style={{ borderBottom: '1px solid var(--c-border)', color: 'var(--c-text3)' }}>
472
472
  <th className="text-left py-2 px-3 font-medium">editor</th>
473
473
  <th className="text-left py-2 px-3 font-medium">name</th>
474
474
  <th className="text-left py-2 px-3 font-medium">project</th>
@@ -500,12 +500,12 @@ export default function Sessions({ overview }) {
500
500
  {isCollapsed ? <ChevronRight size={13} style={{ color: 'var(--c-text3)' }} /> : <ChevronDown size={13} style={{ color: 'var(--c-text3)' }} />}
501
501
  <FolderOpen size={13} style={{ color: 'var(--c-text3)' }} />
502
502
  <span className="text-xs font-medium" style={{ color: 'var(--c-white)' }}>{g.name}</span>
503
- <span className="text-[10px] truncate max-w-[300px]" style={{ color: 'var(--c-text3)' }}>{g.folder !== g.name && g.folder !== '(no project)' ? g.folder : ''}</span>
503
+ <span className="text-[11px] truncate max-w-[300px]" style={{ color: 'var(--c-text3)' }}>{g.folder !== g.name && g.folder !== '(no project)' ? g.folder : ''}</span>
504
504
  <span className="ml-auto flex items-center gap-2">
505
505
  {editorSet.slice(0, 5).map(e => (
506
506
  <span key={e} className="w-2 h-2 rounded-full" style={{ background: editorColor(e) }} title={editorLabel(e)} />
507
507
  ))}
508
- <span className="text-[10px]" style={{ color: 'var(--c-text3)' }}>{g.items.length}</span>
508
+ <span className="text-[11px]" style={{ color: 'var(--c-text3)' }}>{g.items.length}</span>
509
509
  </span>
510
510
  </div>
511
511
  {!isCollapsed && (