agentlytics 0.2.8 → 0.2.10
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 +60 -1
- package/deno.json +9 -0
- package/index.js +68 -8
- package/mod.ts +1020 -0
- package/package.json +7 -2
- package/relay-server.js +1 -1
- package/ui/package.json +1 -1
- package/ui/src/App.jsx +13 -8
- package/ui/src/hooks/useLive.jsx +15 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentlytics",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
4
4
|
"description": "Comprehensive analytics dashboard for AI coding agents — Cursor, Windsurf, Claude Code, VS Code Copilot, Zed, Antigravity, OpenCode, Command Code",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
"ui/package-lock.json",
|
|
24
24
|
"ui/vite.config.js",
|
|
25
25
|
"ui/eslint.config.js",
|
|
26
|
-
"README.md"
|
|
26
|
+
"README.md",
|
|
27
|
+
"mod.ts",
|
|
28
|
+
"deno.json"
|
|
27
29
|
],
|
|
28
30
|
"scripts": {
|
|
29
31
|
"start": "node index.js",
|
|
@@ -46,6 +48,9 @@
|
|
|
46
48
|
],
|
|
47
49
|
"author": "fkadev",
|
|
48
50
|
"license": "ISC",
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=20.19.0"
|
|
53
|
+
},
|
|
49
54
|
"repository": {
|
|
50
55
|
"type": "git",
|
|
51
56
|
"url": "https://github.com/f/agentlytics"
|
package/relay-server.js
CHANGED
|
@@ -542,7 +542,7 @@ function createRelayApp() {
|
|
|
542
542
|
if (fs.existsSync(index)) {
|
|
543
543
|
res.sendFile(index);
|
|
544
544
|
} else {
|
|
545
|
-
res.status(404).send('UI not built. Run: cd ui && npm install && npm run build');
|
|
545
|
+
res.status(404).send('UI not built. Run: cd ui && npm install && npm run build (or use your preferred package manager)');
|
|
546
546
|
}
|
|
547
547
|
});
|
|
548
548
|
|
package/ui/package.json
CHANGED
package/ui/src/App.jsx
CHANGED
|
@@ -3,6 +3,7 @@ import { Routes, Route, NavLink, useLocation } from 'react-router-dom'
|
|
|
3
3
|
import { Activity, BarChart3, GitCompare, MessageSquare, FolderOpen, DollarSign, CreditCard, Sun, Moon, RefreshCw, AlertTriangle, Github, Terminal, Database, Users, Plug, Copy, Check, Settings as SettingsIcon, Package, ChevronDown } from 'lucide-react'
|
|
4
4
|
import { fetchOverview, refetchAgents, fetchMode, fetchRelayConfig, getAuthToken, setOnAuthFailure } from './lib/api'
|
|
5
5
|
import { useTheme } from './lib/theme'
|
|
6
|
+
import { useLive } from './hooks/useLive'
|
|
6
7
|
import AnimatedLogo from './components/AnimatedLogo'
|
|
7
8
|
import AnimatedLoader from './components/AnimatedLoader'
|
|
8
9
|
import LoginScreen from './components/LoginScreen'
|
|
@@ -70,7 +71,7 @@ function NavDropdown({ icon: Icon, label, items }) {
|
|
|
70
71
|
export default function App() {
|
|
71
72
|
const [overview, setOverview] = useState(null)
|
|
72
73
|
const [refetchState, setRefetchState] = useState(null) // null | { scanned, total }
|
|
73
|
-
const
|
|
74
|
+
const { live, toggle: toggleLive } = useLive()
|
|
74
75
|
const [mode, setMode] = useState(null) // 'local' | 'relay'
|
|
75
76
|
const [needsAuth, setNeedsAuth] = useState(false)
|
|
76
77
|
const [authed, setAuthed] = useState(!!getAuthToken())
|
|
@@ -105,25 +106,29 @@ export default function App() {
|
|
|
105
106
|
if (mode === 'local') refreshOverview()
|
|
106
107
|
}, [mode])
|
|
107
108
|
|
|
108
|
-
|
|
109
|
+
const rescanAndRefresh = useCallback(async (onProgress) => {
|
|
110
|
+
await refetchAgents(onProgress)
|
|
111
|
+
const data = await fetchOverview()
|
|
112
|
+
setOverview(data)
|
|
113
|
+
}, [])
|
|
114
|
+
|
|
115
|
+
// Live mode: rescan & refresh every 60s
|
|
109
116
|
useEffect(() => {
|
|
110
117
|
if (live && mode === 'local') {
|
|
111
118
|
liveRef.current = setInterval(() => {
|
|
112
|
-
|
|
119
|
+
rescanAndRefresh().catch(() => {})
|
|
113
120
|
}, 60000)
|
|
114
121
|
} else {
|
|
115
122
|
if (liveRef.current) clearInterval(liveRef.current)
|
|
116
123
|
liveRef.current = null
|
|
117
124
|
}
|
|
118
125
|
return () => { if (liveRef.current) clearInterval(liveRef.current) }
|
|
119
|
-
}, [live,
|
|
126
|
+
}, [live, rescanAndRefresh])
|
|
120
127
|
|
|
121
128
|
const handleRefetch = async () => {
|
|
122
129
|
setRefetchState({ scanned: 0, total: 0 })
|
|
123
130
|
try {
|
|
124
|
-
await
|
|
125
|
-
const data = await fetchOverview()
|
|
126
|
-
setOverview(data)
|
|
131
|
+
await rescanAndRefresh((p) => setRefetchState({ scanned: p.scanned, total: p.total }))
|
|
127
132
|
} catch (e) { console.error(e) }
|
|
128
133
|
setRefetchState(null)
|
|
129
134
|
}
|
|
@@ -187,7 +192,7 @@ export default function App() {
|
|
|
187
192
|
{!isRelay && (
|
|
188
193
|
<>
|
|
189
194
|
<button
|
|
190
|
-
onClick={
|
|
195
|
+
onClick={toggleLive}
|
|
191
196
|
className="flex items-center gap-1.5 px-2 py-0.5 text-[11px] transition"
|
|
192
197
|
style={{
|
|
193
198
|
color: live ? '#22c55e' : 'var(--c-text3)',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback } from 'react'
|
|
2
|
+
|
|
3
|
+
const KEY = 'agentlytics-live'
|
|
4
|
+
|
|
5
|
+
export function useLive() {
|
|
6
|
+
const [live, setLive] = useState(() => localStorage.getItem(KEY) === 'true')
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
localStorage.setItem(KEY, live)
|
|
10
|
+
}, [live])
|
|
11
|
+
|
|
12
|
+
const toggle = useCallback(() => setLive(l => !l), [])
|
|
13
|
+
|
|
14
|
+
return { live, toggle }
|
|
15
|
+
}
|